using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using System.Linq; namespace XED.Util { public class CustomAssetRenderObject : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { private GameObject renderObject; private MeshRenderer objectRenderer; private List snapPoints = new List(); private BoxCollider boxCollider; private Material matCubeShow; private Material matCubeSelected; private Material matCubeCollided; private HashSet objectsInTrigger = new HashSet(); public System.Action onTransformChanged; public Func getBounds; public Func instantiateObject; public bool isSelected = false; public bool isCollided = false; private void Awake() { objectRenderer = GetComponentInChildren(); snapPoints = GetComponentsInChildren().Select(x => x.transform).ToList(); boxCollider = GetComponent(); matCubeShow = Resources.Load("Materials/Mat_CubeShow"); matCubeSelected = Resources.Load("Materials/Mat_CubeSelected"); matCubeCollided = Resources.Load("Materials/Mat_CubeCollided"); } // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { ResetBoundary(); } private void OnEnable() { CreateRenderObject(); } private void OnDisable() { DestroyRenderObject(); ClearTriggerObjects(); } private void OnTriggerEnter(Collider other) { CustomAssetRenderObject otherRenderObject = other.gameObject.GetComponent(); if (otherRenderObject != null) { isCollided = true; objectsInTrigger.Add(other.gameObject); if (isSelected == false) { objectRenderer.material = matCubeCollided; } Show(); } } private void OnTriggerExit(Collider other) { CustomAssetRenderObject otherRenderObject = other.gameObject.GetComponent(); if (otherRenderObject != null) { objectsInTrigger.Remove(other.gameObject); } if (objectsInTrigger.Count == 0) { isCollided = false; if (isSelected == false) { Hide(); } } } public void OnPointerEnter(PointerEventData eventData) { //ResizeBoundary(); if (isSelected || isCollided) { return; } objectRenderer.material = matCubeShow; Show(); } public void OnPointerExit(PointerEventData eventData) { if (isSelected || isCollided) { return; } Hide(); } void ResetBoundary() { Bounds meshBounds = objectRenderer.bounds; Vector3 localCenter = transform.InverseTransformPoint(meshBounds.center); Vector3 localSize = transform.InverseTransformVector(meshBounds.size); boxCollider.center = localCenter; boxCollider.size = localSize; } void ClearTriggerObjects() { foreach (GameObject obj in new List(objectsInTrigger)) { if (obj != null) { obj.SendMessage("OnTriggerExit", GetComponent(), SendMessageOptions.DontRequireReceiver); } } objectsInTrigger.Clear(); } public void ResizeBoundary() { Bounds? boundary = getBounds?.Invoke(); if (boundary.HasValue) { ResizeBoundary(boundary.Value); } } public void ResizeBoundary(Bounds meshBounds) { Vector3 localCenter = transform.InverseTransformPoint(meshBounds.center); Vector3 localSize = transform.InverseTransformVector(meshBounds.size); objectRenderer.transform.localScale = localSize; objectRenderer.transform.localPosition = meshBounds.center; if (snapPoints.Count == 8) { Vector3 boundPointMin = meshBounds.min; Vector3 boundPointMax = meshBounds.max; snapPoints[0].localPosition = boundPointMin; snapPoints[1].localPosition = boundPointMax; snapPoints[2].localPosition = new Vector3(boundPointMin.x, boundPointMin.y, boundPointMax.z); snapPoints[3].localPosition = new Vector3(boundPointMin.x, boundPointMax.y, boundPointMin.z); snapPoints[4].localPosition = new Vector3(boundPointMax.x, boundPointMin.y, boundPointMin.z); snapPoints[5].localPosition = new Vector3(boundPointMin.x, boundPointMax.y, boundPointMax.z); snapPoints[6].localPosition = new Vector3(boundPointMax.x, boundPointMin.y, boundPointMax.z); snapPoints[7].localPosition = new Vector3(boundPointMax.x, boundPointMax.y, boundPointMin.z); } ResetBoundary(); } public void Show() { objectRenderer.enabled = true; } public void Hide() { objectRenderer.enabled = false; } public bool ToggleSelect() { isSelected = !isSelected; if (isSelected) { objectRenderer.material = matCubeSelected; Show(); } else if (isCollided) { objectRenderer.material = matCubeCollided; Show(); } else { objectRenderer.material = matCubeShow; Hide(); } return isSelected; } public void Select() { //ResizeBoundary(); isSelected = true; objectRenderer.material = matCubeSelected; Show(); } public void Deselect() { isSelected = false; if (isCollided) { objectRenderer.material = matCubeCollided; Show(); return; } objectRenderer.material = matCubeShow; Hide(); } public void CreateRenderObject() { if (renderObject == null) { renderObject = instantiateObject?.Invoke(transform); } ResizeBoundary(); } public void DestroyRenderObject() { if (renderObject) { Destroy(renderObject); renderObject = null; } } public Bounds GetBounds() { return boxCollider.bounds; } public List GetRenderObjectVertices() { MeshFilter[] meshFilters = renderObject.GetComponentsInChildren(); List points = new List(); for (int i = 0; i < meshFilters.Length; i++) { Vector3[] vertices = meshFilters[i].mesh.vertices; for (int k = 0; k < vertices.Length; k++) { Vector3 pt = renderObject.transform.TransformPoint(vertices[k]); points.Add(pt); } } return points; } public KDTree GetVertexPointKDTree() { if (renderObject == null) return null; return new KDTree(renderObject); } } }