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

469 lines
23 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using XED.UI;
using XRLib;
using XED.Manage;
using XED.Util;
using XED.Hierarchy;
using System.Linq;
namespace XED.Asset
{
public class CustomAssetConnector : MonoBehaviour, ISingle
{
private CustomScrollRect assetScrollRect;
private PooledScrollView assetScrollView;
private PooledScrollView componentScrollView;
private GameObject renderObjectPrefab;
private float objectShowDistance = 1000.0f;
private List<ConnectedAsset> connectedAssets = new List<ConnectedAsset>();
private List<CustomAssetData> selectedAssetDatas = new List<CustomAssetData>();
private CustomAssetData selectedAssetData;
private GameObject selectedItem;
private CustomAssetRenderObject selectRenderObject;
public SaveLoadFBXData saveLoadFBXData;
public RenderObjectHandler renderObjectHandler;
public event System.Action<string, List<GameObject>> onSelectObjects;
public event System.Action onDeselectObjects;
public event System.Action onRemoveObjects;
public event System.Action onAssetDropped;
void Awake()
{
saveLoadFBXData = FindFirstObjectByType<SaveLoadFBXData>();
renderObjectHandler = FindFirstObjectByType<RenderObjectHandler>();
}
void Start()
{
assetScrollRect = FindSingle<Canvas_Windows>().panel_assetlibrary.scrollRect;
assetScrollView = FindSingle<Canvas_Windows>().panel_assetlibrary.scrollView;
componentScrollView = FindSingle<Canvas_Windows>().panel_componentlibrary.scrollView;
renderObjectPrefab = Resources.Load<GameObject>("Prefabs/PRF_RenderObject");
assetScrollRect.onDragBegin.AddListener(OnAssetSelected);
assetScrollRect.onDragAndDrop.AddListener(OnAssetDropped);
assetScrollView.onSelect.AddListener(OnSelectAssetFromHierarchy);
componentScrollView.onSelect.AddListener(OnSelectObjectFromHierarchy);
componentScrollView.onParentChanged.AddListener(OnParentChanged);
saveLoadFBXData.onLoadFbxFile.AddListener(OnLoadFbxFile);
saveLoadFBXData.onRemoveFbxFile.AddListener(OnRemoveFbxFile);
renderObjectHandler.onSelectObject.AddListener(OnSelectObjectFromObjectHandler);
renderObjectHandler.onCopyObject.AddListener(OnCopyObject);
renderObjectHandler.onRemoveObject.AddListener(OnRemoveObject);
renderObjectHandler.onOrderByHierachy.AddListener(OrderByHierarchy);
renderObjectHandler.onDeselectAll += OnDeselectAll;
}
// Update is called once per frame
void Update()
{
if (selectedAssetData != null)
{
Vector3? pos = GetMousePointOnYPlane(objectShowDistance);
if (pos.HasValue)
{
selectedItem.transform.position = pos.Value;
selectedAssetData.OnTransformDataChanged();
}
}
}
void CreateConnectedAsset()
{
ConnectedAsset connectedAsset = new ConnectedAsset();
connectedAsset.assetData = selectedAssetData;
connectedAsset.hierarchyItem = componentScrollView.AddItem(selectedAssetData.assetName, selectedItem, HierarchyItemType.obj);
connectedAsset.renderObject = selectRenderObject;
connectedAsset.renderObject.onTransformChanged = connectedAsset.assetData.OnTransformDataChanged;
var command = new ActionCommand(
() =>
{
if (connectedAsset.renderObject.gameObject.activeSelf == false)
{
connectedAsset.assetData.AddTransformToRender(connectedAsset.renderObject.transform);
connectedAsset.renderObject.gameObject.SetActive(true);
componentScrollView.AddItem(connectedAsset.hierarchyItem);
}
connectedAsset.renderObject.Hide();
connectedAssets.Add(connectedAsset);
},
() =>
{
connectedAssets.Remove(connectedAsset);
connectedAsset.assetData.RemoveTransform(connectedAsset.renderObject.transform);
connectedAsset.renderObject.gameObject.SetActive(false);
componentScrollView.RemoveItem(connectedAsset.hierarchyItem);
});
CommandManager.I.ExecuteCommand(command);
}
public void OnLoadFbxFile(string objectName, string folderName, CustomAssetData assetData)
{
HierarchyItem parent = assetScrollView.FindItem(folderName, HierarchyItemType.folder);
if (parent == null)
{
parent = assetScrollView.AddItem(folderName, null, HierarchyItemType.folder);
}
HierarchyItem item = assetScrollView.AddItem(objectName, assetData.gameObject, HierarchyItemType.file, parent);
assetData.onLoadProgress.RemoveAllListeners();
assetData.onLoadProgress.AddListener((x) => item.onLoadProgress?.Invoke(x));
}
public void OnRemoveFbxFile(string objectName)
{
assetScrollView.RemoveItem(objectName, HierarchyItemType.file);
}
public void OnAssetSelected(HierarchyItem item)
{
if (item == null || item.linkedObject == null)
{
selectedAssetData = null;
return;
}
selectedAssetData = item.linkedObject.GetComponent<CustomAssetData>();
if (selectedAssetData == null || selectedAssetData.isLoadComplete == false)
{
selectedAssetData = null;
return;
}
selectedItem = Instantiate(renderObjectPrefab);
selectRenderObject = selectedItem.GetComponent<CustomAssetRenderObject>();
selectRenderObject.instantiateObject = selectedAssetData.InstantiateLoadedObject;
selectRenderObject.getBounds = selectedAssetData.GetCombinedBoundary;
selectRenderObject.CreateRenderObject();
selectRenderObject.Select();
selectedAssetData.AddTransformToRender(selectedItem.transform);
}
public void OnAssetDropped(HierarchyItem item)
{
if (selectedAssetData == null)
return;
bool isPointerOutScrollRect = !assetScrollRect.IsPointerOverScrollRect();
if (item != null && isPointerOutScrollRect)
{
CreateConnectedAsset();
}
else
{
selectedAssetData.RemoveTransform(selectedItem.transform);
Destroy(selectedItem);
}
selectRenderObject.Deselect();
selectedAssetData = null;
onAssetDropped?.Invoke();
}
public void OnSelectObjectFromHierarchy(List<HierarchyItem> selectedItems)
{
if (selectedItems.Count == 0)
{
return;
}
string name = "";
List<GameObject> selectedObjects = new List<GameObject>();
foreach (ConnectedAsset connectedAsset in connectedAssets)
{
connectedAsset.renderObject.Deselect();
}
renderObjectHandler.RemoveAllSelections();
for (int i = 0; i < selectedItems.Count; i++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.hierarchyItem == selectedItems[i]);
name = i == 0 ? searchAsset.hierarchyItem.name : name.Equals(searchAsset.hierarchyItem.name) ? searchAsset.hierarchyItem.name : "-";
selectedObjects.Add(searchAsset.renderObject.gameObject);
renderObjectHandler.AddSelection(searchAsset.renderObject);
}
renderObjectHandler.ResetGizmoTargetObjects();
onSelectObjects?.Invoke(name, selectedObjects);
}
public void OnSelectAssetFromHierarchy(List<HierarchyItem> selectedItems)
{
selectedAssetDatas.Clear();
if (selectedItems.Count == 0)
{
return;
}
for (int i = 0; i < selectedItems.Count; i++)
{
HierarchyItem assetItem = selectedItems[i];
CustomAssetData assetData = null;
if (assetItem.linkedObject)
{
assetItem.linkedObject.GetComponent<CustomAssetData>();
}
if (assetData != null)
{
selectedAssetDatas.Add(assetData);
}
}
}
public void OnSelectObjectFromObjectHandler(List<CustomAssetRenderObject> objects)
{
if (objects.Count == 0)
{
return;
}
string name = "";
List<GameObject> selectedObjects = new List<GameObject>();
List<HierarchyItem> selectedItems = new List<HierarchyItem>();
for (int i = 0; i < objects.Count; i++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.renderObject == objects[i]);
selectedItems.Add(searchAsset.hierarchyItem);
name = i == 0 ? searchAsset.hierarchyItem.name : name.Equals(searchAsset.hierarchyItem.name) ? searchAsset.hierarchyItem.name : "-";
selectedObjects.Add(searchAsset.renderObject.gameObject);
}
componentScrollView.OnSelect(selectedItems);
onSelectObjects?.Invoke(name, selectedObjects);
}
public void OnDragBoxSelect(Rect selectionBoxRect)
{
List<ConnectedAsset> activeAssets = connectedAssets.FindAll(x => x.renderObject != null && x.renderObject.gameObject.activeSelf);
if (activeAssets.Count == 0)
{
return;
}
string name = "";
List<HierarchyItem> selectedItems = new List<HierarchyItem>();
List<CustomAssetRenderObject> selectedRenderObjects = new List<CustomAssetRenderObject>();
renderObjectHandler.RemoveAllSelections();
for (int i = 0; i < activeAssets.Count; i++)
{
ConnectedAsset activeAsset = activeAssets[i];
if (selectionBoxRect.Contains(Camera.main.WorldToScreenPoint(activeAsset.renderObject.transform.position)))
{
name = i == 0 ? activeAsset.hierarchyItem.name : name.Equals(activeAsset.hierarchyItem.name) ? activeAsset.hierarchyItem.name : "-";
selectedItems.Add(activeAsset.hierarchyItem);
selectedRenderObjects.Add(activeAsset.renderObject);
}
}
renderObjectHandler.AddSelection(selectedRenderObjects);
componentScrollView.OnSelect(selectedItems);
onSelectObjects?.Invoke(name, selectedRenderObjects.Select(x => x.gameObject).ToList());
}
public void OnRemoveObject(List<CustomAssetRenderObject> objects)
{
if (objects.Count == 0)
{
return;
}
List<ConnectedAsset> removeList = new List<ConnectedAsset>();
List<int> siblingIndex = new List<int>();
for (int i = 0; i < objects.Count; i++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.renderObject == objects[i]);
removeList.Add(searchAsset);
siblingIndex.Add(searchAsset.hierarchyItem.GetSiblingIndex());
}
var command = new ActionCommand(
() =>
{
for (int i = 0; i < removeList.Count; i++)
{
ConnectedAsset connectedAsset = removeList[i];
componentScrollView.RemoveItem(connectedAsset.hierarchyItem);
connectedAsset.assetData.RemoveTransform(connectedAsset.renderObject.transform);
connectedAsset.renderObject.gameObject.SetActive(false);
List<HierarchyItem> childItems = connectedAsset.hierarchyItem.GetAll(true);
for (int k = 0; k < childItems.Count; k++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.hierarchyItem == childItems[k]);
searchAsset.assetData.RemoveTransform(searchAsset.renderObject.transform);
searchAsset.renderObject.gameObject.SetActive(false);
}
}
onRemoveObjects?.Invoke();
componentScrollView.DeselectAll();
},
() =>
{
for (int i = 0; i < removeList.Count; i++)
{
ConnectedAsset connectedAsset = removeList[i];
componentScrollView.AttachItem(connectedAsset.hierarchyItem.parent, connectedAsset.hierarchyItem, siblingIndex[i]);
connectedAsset.assetData.AddTransformToRender(connectedAsset.renderObject.transform);
connectedAsset.renderObject.gameObject.SetActive(true);
}
for (int i = 0; i < removeList.Count; i++)
{
ConnectedAsset connectedAsset = removeList[i];
List<HierarchyItem> childItems = connectedAsset.hierarchyItem.GetAll(true);
for (int k = 0; k < childItems.Count; k++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.hierarchyItem == childItems[k]);
searchAsset.assetData.AddTransformToRender(searchAsset.renderObject.transform);
searchAsset.renderObject.gameObject.SetActive(true);
}
}
});
CommandManager.I.ExecuteCommand(command);
}
public void OnCopyObject(List<CustomAssetRenderObject> objects)
{
if (objects.Count == 0)
{
return;
}
List<ConnectedAsset> copySources = new List<ConnectedAsset>();
List<ConnectedAsset> copyList = new List<ConnectedAsset>();
for (int i = 0; i < objects.Count; i++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.renderObject == objects[i]);
copySources.Add(searchAsset);
ConnectedAsset copyAsset = new ConnectedAsset();
copyList.Add(copyAsset);
connectedAssets.Add(copyAsset);
}
var command = new ActionCommand(
() =>
{
for (int i = 0; i < copyList.Count; i++)
{
ConnectedAsset copySource = copySources[i];
ConnectedAsset copyAsset = copyList[i];
if (copyAsset.hierarchyItem == null)
{
GameObject copyObject = Instantiate(renderObjectPrefab);
copyAsset.assetData = copySource.assetData;
copyAsset.hierarchyItem = copySource.hierarchyItem.Copy();
copyAsset.renderObject = copyObject.GetComponent<CustomAssetRenderObject>();
copyAsset.renderObject.getBounds = copySource.assetData.GetCombinedBoundary;
copyAsset.renderObject.onTransformChanged = copySource.assetData.OnTransformDataChanged;
copyAsset.renderObject.instantiateObject = copySource.assetData.InstantiateLoadedObject;
copyAsset.renderObject.CreateRenderObject();
copyAsset.renderObject.transform.position = copySource.renderObject.transform.position;
copyAsset.renderObject.transform.rotation = copySource.renderObject.transform.rotation;
copyAsset.renderObject.transform.localScale = copySource.renderObject.transform.localScale;
List<Transform> lastParent = new List<Transform>();
for (int j = 0; j < copyAsset.hierarchyItem.layerNum + 1; j++)
{
lastParent.Add(copyAsset.renderObject.transform);
}
List<HierarchyItem> srcChildren = copySource.hierarchyItem.GetAll(true);
List<HierarchyItem> dstChildren = copyAsset.hierarchyItem.GetAll(true);
for (int k = 0; k < srcChildren.Count; k++)
{
ConnectedAsset childSource = connectedAssets.Find((x) => x.hierarchyItem == srcChildren[k]);
GameObject copyChildObject = Instantiate(renderObjectPrefab);
ConnectedAsset childAsset = new ConnectedAsset();
childAsset.assetData = childSource.assetData;
childAsset.hierarchyItem = dstChildren[k];
childAsset.renderObject = copyChildObject.GetComponent<CustomAssetRenderObject>(); ;
childAsset.renderObject.getBounds = childAsset.assetData.GetCombinedBoundary;
childAsset.renderObject.onTransformChanged = childAsset.assetData.OnTransformDataChanged;
childAsset.renderObject.instantiateObject = copySource.assetData.InstantiateLoadedObject;
childAsset.renderObject.CreateRenderObject();
childAsset.renderObject.transform.position = childSource.renderObject.transform.position;
childAsset.renderObject.transform.rotation = childSource.renderObject.transform.rotation;
childAsset.renderObject.transform.localScale = childSource.renderObject.transform.localScale;
childAsset.renderObject.transform.parent = lastParent[childAsset.hierarchyItem.layerNum - 1];
if (lastParent.Count <= childAsset.hierarchyItem.layerNum)
{
lastParent.Add(childAsset.renderObject.transform);
}
else
{
lastParent[childAsset.hierarchyItem.layerNum] = childAsset.renderObject.transform;
}
connectedAssets.Add(childAsset);
}
}
copyAsset.assetData.AddTransformToRender(copyAsset.renderObject.transform);
copyAsset.renderObject.gameObject.SetActive(true);
copyAsset.renderObject.Hide();
componentScrollView.AddItem(copyAsset.hierarchyItem);
}
for (int i = 0; i < copyList.Count; i++)
{
ConnectedAsset connectedAsset = copyList[i];
List<HierarchyItem> childItems = connectedAsset.hierarchyItem.GetAll(true);
for (int k = 0; k < childItems.Count; k++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.hierarchyItem == childItems[k]);
searchAsset.assetData.AddTransformToRender(searchAsset.renderObject.transform);
searchAsset.renderObject.gameObject.SetActive(true);
}
}
},
() =>
{
for (int i = 0; i < copyList.Count; i++)
{
ConnectedAsset connectedAsset = copyList[i];
componentScrollView.RemoveItem(connectedAsset.hierarchyItem);
connectedAsset.assetData.RemoveTransform(connectedAsset.renderObject.transform);
connectedAsset.renderObject.gameObject.SetActive(false);
List<HierarchyItem> childItems = connectedAsset.hierarchyItem.GetAll(true);
for (int k = 0; k < childItems.Count; k++)
{
ConnectedAsset searchAsset = connectedAssets.Find((x) => x.hierarchyItem == childItems[k]);
searchAsset.assetData.RemoveTransform(searchAsset.renderObject.transform);
searchAsset.renderObject.gameObject.SetActive(false);
}
}
onRemoveObjects?.Invoke();
componentScrollView.DeselectAll();
});
CommandManager.I.ExecuteCommand(command);
}
public void OnParentChanged(HierarchyItem parentItem, HierarchyItem childItem)
{
ConnectedAsset parentAsset = connectedAssets.Find((x) => x.hierarchyItem == parentItem);
ConnectedAsset childAsset = connectedAssets.Find((x) => x.hierarchyItem == childItem);
if (childAsset == null || childAsset.renderObject == null)
{
return;
}
if (parentAsset == null || parentAsset.renderObject == null)
{
childAsset.renderObject.transform.parent = null;
return;
}
childAsset.renderObject.transform.parent = parentAsset.renderObject.transform;
}
public void OnDeselectAll()
{
onDeselectObjects?.Invoke();
componentScrollView.DeselectAll();
}
public void SaveSelectedAssetDatasToLocal()
{
saveLoadFBXData.SaveToLocalData(selectedAssetDatas);
}
public void LoadLocalAssetDatas()
{
saveLoadFBXData.LoadLocalData();
}
public void OrderByHierarchy(List<CustomAssetRenderObject> objectsToOrder)
{
SortedDictionary<int, CustomAssetRenderObject> itemToObject = new SortedDictionary<int, CustomAssetRenderObject>();
for (int i = 0; i < objectsToOrder.Count; i++)
{
CustomAssetRenderObject objectToOrder = objectsToOrder[i];
ConnectedAsset connectedAsset = connectedAssets.Find(x => x.renderObject == objectToOrder);
itemToObject.Add(componentScrollView.GetItemIndex(connectedAsset.hierarchyItem), objectToOrder);
}
objectsToOrder = itemToObject.Values.ToList();
}
Vector3? GetMousePointOnYPlane(float maxDistance)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane yPlane = new Plane(Vector3.up, Vector3.zero);
if (yPlane.Raycast(ray, out float distance))
{
if (distance <= maxDistance)
{
return ray.GetPoint(distance);
}
}
return null;
}
}
public class ConnectedAsset
{
public HierarchyItem hierarchyItem;
public CustomAssetData assetData;
public CustomAssetRenderObject renderObject;
}
}