Files
Studio/Assets/Scripts/XED/AssetTool/CustomAssetRenderObject.cs
SullyunShin f1587ae47d 객체 스냅 기능 업데이트
고정된 큐브 꼭짓점이 아닌 Convecx Hull 포인트로 스냅하도록 수정
2025-02-24 15:55:44 +09:00

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);
}
}
}