328 lines
10 KiB
C#
328 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices.WindowsRuntime;
|
|
using System.Security.Cryptography;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
|
|
public class SelectDetector
|
|
{
|
|
//GameObject
|
|
public GameObject detectedObject;
|
|
private List<GameObject> objects;
|
|
private List<int> objectIds;
|
|
|
|
private Shader objectEncodeShader;
|
|
private Material objectEncodeMaterial;
|
|
private Dictionary<int, Material> objectEncodeMaterials;
|
|
|
|
//Gizmo
|
|
public GameObject detectedGizmo;
|
|
private List<GameObject> gizmos;
|
|
private List<int> gizmoIds;
|
|
|
|
private Shader gizmoEncodeShader;
|
|
private Material gizmoEncodeMaterial;
|
|
private Dictionary<int,Material> gizmoEncodeMaterials;
|
|
|
|
private CommandBuffer encodeCmdBuffer;
|
|
|
|
private Camera selectCamera;
|
|
private GameObject cameraObject;
|
|
|
|
private Texture2D encodeTexture2d;
|
|
private RenderTexture encodeTexture;
|
|
|
|
private bool isCursorOnPanels = false;
|
|
|
|
public void Initialize()
|
|
{
|
|
//Encode CommandBuffer Initialize
|
|
encodeCmdBuffer = new CommandBuffer();
|
|
|
|
//Object Encode Material Initialize
|
|
objectEncodeShader = Shader.Find("Custom/ObjectSelectEncode");
|
|
objectEncodeMaterial = new Material(objectEncodeShader);
|
|
objectEncodeMaterial.SetColor("_ID", IntToRGBA(-1));
|
|
|
|
//Gizmo Encode Material Initialize
|
|
gizmoEncodeShader = Shader.Find("Custom/GizmoSelectEncode");
|
|
gizmoEncodeMaterial = new Material(gizmoEncodeShader);
|
|
gizmoEncodeMaterial.SetColor("_ID", IntToRGBA(-1));
|
|
|
|
//Encode Texture Initialize
|
|
encodeTexture = new RenderTexture(Screen.width, Screen.height, 24);
|
|
encodeTexture2d = new Texture2D(1, 1, TextureFormat.ARGB32, false);
|
|
|
|
//Camera Initialize
|
|
cameraObject = new GameObject();
|
|
cameraObject.name = "SelectDetector";
|
|
cameraObject.GetComponent<Transform>().parent = GameObject.Find("Main Camera").GetComponent<Transform>();
|
|
cameraObject.GetComponent<Transform>().localPosition = Vector3.zero;
|
|
cameraObject.GetComponent<Transform>().rotation = Quaternion.identity;
|
|
selectCamera = cameraObject.AddComponent<Camera>();
|
|
selectCamera.targetTexture = encodeTexture;
|
|
selectCamera.GetComponent<Transform>().position = Camera.main.transform.position;
|
|
selectCamera.GetComponent<Transform>().rotation = Camera.main.transform.rotation;
|
|
|
|
//List Initialize
|
|
objects = new List<GameObject>();
|
|
objectIds = new List<int>();
|
|
objectEncodeMaterials = new Dictionary<int, Material>();
|
|
gizmos = new List<GameObject>();
|
|
gizmoIds = new List<int>();
|
|
gizmoEncodeMaterials = new Dictionary<int, Material>();
|
|
}
|
|
|
|
public void InitializeScene()
|
|
{
|
|
//Original GameObjects Initialize
|
|
foreach (GameObject root in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects())
|
|
{
|
|
foreach (Transform child_transform in root.GetComponentsInChildren<Transform>(true))
|
|
{
|
|
GameObject child = child_transform.gameObject;
|
|
objects.Add(child);
|
|
objectIds.Add(child.GetInstanceID());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (isCursorOnPanels) { return; }
|
|
|
|
//Select Camera Update
|
|
//selectCamera.GetComponent<Transform>().position = Camera.main.transform.position;
|
|
//selectCamera.GetComponent<Transform>().rotation = Camera.main.transform.rotation;
|
|
selectCamera.RemoveAllCommandBuffers();
|
|
|
|
|
|
//Encode CommandBuffer Update
|
|
encodeCmdBuffer.Clear();
|
|
encodeCmdBuffer.ClearRenderTarget(true, true, Color.white);
|
|
|
|
//Add Object Render Command
|
|
for (int i = 0; i < objects.Count; i++)
|
|
{
|
|
GameObject tmpObject = objects[i];
|
|
if (tmpObject == null) { continue; }
|
|
if (tmpObject.activeSelf == false) { continue; }
|
|
MeshRenderer tmpRenderer = tmpObject.GetComponent<MeshRenderer>();
|
|
if (tmpRenderer != null)
|
|
{
|
|
int tmpId = tmpObject.GetInstanceID();
|
|
Material tempMaterial = objectEncodeMaterials[tmpId];
|
|
encodeCmdBuffer.DrawRenderer(tmpRenderer, tempMaterial);
|
|
}
|
|
}
|
|
//Add Gizmo Render Command
|
|
for (int i = 0; i < gizmos.Count; i++)
|
|
{
|
|
GameObject tmpGizmo = gizmos[i];
|
|
MeshRenderer tmpRenderer = tmpGizmo.GetComponent<MeshRenderer>();
|
|
if (tmpRenderer != null)
|
|
{
|
|
int tmpId = tmpGizmo.GetInstanceID();
|
|
Material tmpMaterial = gizmoEncodeMaterials[tmpId];
|
|
encodeCmdBuffer.DrawRenderer(tmpRenderer, tmpMaterial);
|
|
}
|
|
}
|
|
selectCamera.AddCommandBuffer(CameraEvent.AfterEverything, encodeCmdBuffer);
|
|
|
|
|
|
//Detected Object&Gizmo Update
|
|
Vector2 input = Input.mousePosition;
|
|
int inputX = (int)input.x;
|
|
int inputY = (int)input.y;
|
|
int clampInputX = Mathf.Clamp(inputX, 0, encodeTexture.width - 1);
|
|
int clampInputY = Mathf.Clamp(inputY, 0, encodeTexture.height - 1);
|
|
RenderTexture.active = encodeTexture;
|
|
encodeTexture2d.ReadPixels(new Rect(clampInputX, clampInputY, 1, 1), 0, 0);
|
|
encodeTexture2d.Apply();
|
|
Color color = encodeTexture2d.GetPixel(0, 0);
|
|
int id = RGBAToInt(color);
|
|
detectedObject = FindObjectByID(id);
|
|
detectedGizmo = FindGizmoByID(id);
|
|
}
|
|
|
|
|
|
//Object Add&Remove&Find
|
|
public void AddObjects(GameObject root_object)
|
|
{
|
|
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
|
|
{
|
|
GameObject child = child_transform.gameObject;
|
|
AddObject(child);
|
|
}
|
|
}
|
|
|
|
public void RemoveObjects(GameObject root_object)
|
|
{
|
|
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
|
|
{
|
|
GameObject child = child_transform.gameObject;
|
|
RemoveObject(child);
|
|
}
|
|
}
|
|
|
|
public void AddObjects(List<GameObject> objects)
|
|
{
|
|
foreach(GameObject obj in objects)
|
|
{
|
|
AddObject(obj);
|
|
}
|
|
}
|
|
|
|
public void RemoveObjects(List<GameObject> objects)
|
|
{
|
|
foreach(GameObject obj in objects)
|
|
{
|
|
RemoveObject(obj);
|
|
}
|
|
}
|
|
|
|
|
|
public void AddObject(GameObject p_object)
|
|
{
|
|
if(p_object == null) { return; }
|
|
objects.Add(p_object);
|
|
int id = p_object.GetInstanceID();
|
|
objectIds.Add(id);
|
|
|
|
//Encode Material
|
|
Material encodeMaterial = new Material(objectEncodeMaterial);
|
|
encodeMaterial.SetColor("_ID", IntToRGBA(id));
|
|
objectEncodeMaterials.Add(id, encodeMaterial);
|
|
}
|
|
|
|
public void RemoveObject(GameObject p_object)
|
|
{
|
|
if (p_object == null) { return; }
|
|
if (!objects.Contains(p_object)) { return; }
|
|
objects.Remove(p_object);
|
|
int id = p_object.GetInstanceID();
|
|
objectIds.Remove(id);
|
|
objectEncodeMaterials.Remove(id);
|
|
}
|
|
|
|
private GameObject FindObjectByID(int id)
|
|
{
|
|
for (int i = 0; i < objects.Count; i++)
|
|
{
|
|
if (objectIds[i] == id)
|
|
{
|
|
return objects[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
//Gizmo Add&Remove&Find
|
|
public void AddGizmos(GameObject root_object)
|
|
{
|
|
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
|
|
{
|
|
GameObject child = child_transform.gameObject;
|
|
AddGizmo(child);
|
|
}
|
|
}
|
|
public void RemoveGizmos(GameObject root_object)
|
|
{
|
|
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
|
|
{
|
|
GameObject child = child_transform.gameObject;
|
|
RemoveGizmo(child);
|
|
}
|
|
}
|
|
|
|
public void AddGizmos(List<GameObject> objects)
|
|
{
|
|
foreach(GameObject gameObject in objects)
|
|
{
|
|
AddGizmo(gameObject);
|
|
}
|
|
}
|
|
|
|
public void RemoveGizmos(List<GameObject> objects)
|
|
{
|
|
foreach(GameObject gameObject in objects)
|
|
{
|
|
RemoveGizmo(gameObject);
|
|
}
|
|
}
|
|
|
|
|
|
public void AddGizmo(GameObject p_gizmo)
|
|
{
|
|
if (p_gizmo == null) { return; }
|
|
gizmos.Add(p_gizmo);
|
|
int id = p_gizmo.GetInstanceID();
|
|
gizmoIds.Add(id);
|
|
|
|
//Encode Material
|
|
Material encodeMaterial = new Material(gizmoEncodeMaterial);
|
|
encodeMaterial.SetColor("_ID", IntToRGBA(id));
|
|
gizmoEncodeMaterials.Add(id, encodeMaterial);
|
|
}
|
|
|
|
public void RemoveGizmo(GameObject p_gizmo)
|
|
{
|
|
if (p_gizmo == null) { return; }
|
|
if (!gizmos.Contains(p_gizmo)) { return; }
|
|
gizmos.Remove(p_gizmo);
|
|
int id = p_gizmo.GetInstanceID();
|
|
gizmoIds.Remove(id);
|
|
gizmoEncodeMaterials.Remove(id);
|
|
}
|
|
|
|
private GameObject FindGizmoByID(int id)
|
|
{
|
|
for (int i = 0; i < gizmos.Count; i++)
|
|
{
|
|
if (gizmoIds[i] == id)
|
|
{
|
|
return gizmos[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
//Tool
|
|
private Color IntToRGBA(int value)
|
|
{
|
|
byte red = (byte)((value >> 24) & 0xFF);
|
|
|
|
byte green = (byte)((value >> 16) & 0xFF);
|
|
|
|
byte blue = (byte)((value >> 8) & 0xFF);
|
|
|
|
byte alpha = (byte)(value & 0xFF);
|
|
|
|
return new Color32(red, green, blue, alpha);
|
|
}
|
|
|
|
private int RGBAToInt(Color32 color)
|
|
{
|
|
int result = (color.r << 24) |
|
|
(color.g << 16) |
|
|
(color.b << 8) |
|
|
color.a;
|
|
|
|
return result;
|
|
}
|
|
|
|
private int RGBAToInt(Color color)
|
|
{
|
|
Color32 color32 = new Color32((byte)(color.r * 255),
|
|
(byte)(color.g * 255),
|
|
(byte)(color.b * 255),
|
|
(byte)(color.a * 255));
|
|
return RGBAToInt(color32);
|
|
}
|
|
|
|
}
|