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 objects; private List objectIds; private Shader objectEncodeShader; private Material objectEncodeMaterial; private Dictionary objectEncodeMaterials; //Gizmo public GameObject detectedGizmo; private List gizmos; private List gizmoIds; private Shader gizmoEncodeShader; private Material gizmoEncodeMaterial; private Dictionary 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().parent = GameObject.Find("Main Camera").GetComponent(); cameraObject.GetComponent().localPosition = Vector3.zero; cameraObject.GetComponent().rotation = Quaternion.identity; selectCamera = cameraObject.AddComponent(); selectCamera.targetTexture = encodeTexture; selectCamera.GetComponent().position = Camera.main.transform.position; selectCamera.GetComponent().rotation = Camera.main.transform.rotation; //List Initialize objects = new List(); objectIds = new List(); objectEncodeMaterials = new Dictionary(); gizmos = new List(); gizmoIds = new List(); gizmoEncodeMaterials = new Dictionary(); } public void InitializeScene() { //Original GameObjects Initialize foreach (GameObject root in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects()) { foreach (Transform child_transform in root.GetComponentsInChildren(true)) { GameObject child = child_transform.gameObject; objects.Add(child); objectIds.Add(child.GetInstanceID()); } } } public void Update() { if (isCursorOnPanels) { return; } //Select Camera Update //selectCamera.GetComponent().position = Camera.main.transform.position; //selectCamera.GetComponent().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(); 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(); 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(true)) { GameObject child = child_transform.gameObject; AddObject(child); } } public void RemoveObjects(GameObject root_object) { foreach (Transform child_transform in root_object.GetComponentsInChildren(true)) { GameObject child = child_transform.gameObject; RemoveObject(child); } } public void AddObjects(List objects) { foreach(GameObject obj in objects) { AddObject(obj); } } public void RemoveObjects(List 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(true)) { GameObject child = child_transform.gameObject; AddGizmo(child); } } public void RemoveGizmos(GameObject root_object) { foreach (Transform child_transform in root_object.GetComponentsInChildren(true)) { GameObject child = child_transform.gameObject; RemoveGizmo(child); } } public void AddGizmos(List objects) { foreach(GameObject gameObject in objects) { AddGizmo(gameObject); } } public void RemoveGizmos(List 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); } }