234 lines
8.0 KiB
C#
234 lines
8.0 KiB
C#
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<Transform> snapPoints = new List<Transform>();
|
|
private BoxCollider boxCollider;
|
|
private Material matCubeShow;
|
|
private Material matCubeSelected;
|
|
private Material matCubeCollided;
|
|
private HashSet<GameObject> objectsInTrigger = new HashSet<GameObject>();
|
|
|
|
public System.Action onTransformChanged;
|
|
public Func<Bounds> getBounds;
|
|
public Func<Transform, GameObject> instantiateObject;
|
|
public bool isSelected = false;
|
|
public bool isCollided = false;
|
|
|
|
private void Awake()
|
|
{
|
|
objectRenderer = GetComponentInChildren<MeshRenderer>();
|
|
snapPoints = GetComponentsInChildren<ObjectSnap>().Select(x => x.transform).ToList();
|
|
boxCollider = GetComponent<BoxCollider>();
|
|
matCubeShow = Resources.Load<Material>("Materials/Mat_CubeShow");
|
|
matCubeSelected = Resources.Load<Material>("Materials/Mat_CubeSelected");
|
|
matCubeCollided = Resources.Load<Material>("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<CustomAssetRenderObject>();
|
|
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<CustomAssetRenderObject>();
|
|
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<GameObject>(objectsInTrigger))
|
|
{
|
|
if (obj != null)
|
|
{
|
|
obj.SendMessage("OnTriggerExit", GetComponent<Collider>(), 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<Vector3> GetRenderObjectVertices()
|
|
{
|
|
MeshFilter[] meshFilters = renderObject.GetComponentsInChildren<MeshFilter>();
|
|
List<Vector3> points = new List<Vector3>();
|
|
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);
|
|
}
|
|
}
|
|
}
|