395 lines
17 KiB
C#
395 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using Studio.AssetTool;
|
|
using Studio.Command;
|
|
using Studio.DataStructures;
|
|
using Studio.Interfaces;
|
|
using Studio.Manage;
|
|
using Studio.RuntimeGizmo;
|
|
using Studio.HierarchyTree;
|
|
|
|
namespace Studio.AssetTool
|
|
{
|
|
public class RenderObjectHandler : Manager, IModeController, IInputHandler
|
|
{
|
|
public ModePanel.ProgramMode mode => ModePanel.ProgramMode.ObjectLayout;
|
|
public List<CustomAssetRenderObject> selectedRenderObjects = new List<CustomAssetRenderObject>();
|
|
List<CustomAssetRenderObject> copyRenderObjects = new List<CustomAssetRenderObject>();
|
|
List<GameObject> selectedGameObjects = new List<GameObject>();
|
|
CustomAssetRenderObject prevSelectedObject;
|
|
public RTGController rtgController;
|
|
ConvexHullCalculator convexHullCalculator = new ConvexHullCalculator();
|
|
UserInputManager userInputManager;
|
|
Vector3 clickBeginPos;
|
|
float clickLengthThreshold = 5.0f;
|
|
int uiLayer;
|
|
int selectIndex;
|
|
bool lockHandler = false;
|
|
bool inputLockhandler = false;
|
|
|
|
public override void Init()
|
|
{
|
|
myHandler = GetInputHandler();
|
|
rtgController = new RTGController();
|
|
rtgController.onTransformBegin = OnTransformBegin;
|
|
rtgController.onTransformChanged = OnTransformChangedFromRTG;
|
|
uiLayer = LayerMask.NameToLayer("UI");
|
|
userInputManager = GameObject.FindAnyObjectByType<UserInputManager>();
|
|
var statusPanel = GameObject.FindFirstObjectByType<ModePanel>();
|
|
statusPanel.AddController(this);
|
|
|
|
selectIndex = 0;
|
|
}
|
|
|
|
private void OnMousePointerDown()
|
|
{
|
|
clickBeginPos = Input.mousePosition;
|
|
//ui를 선택했을 경우에는 오브젝트 선택을 멈춘다.
|
|
PointerEventData pointerData = new PointerEventData(EventSystem.current)
|
|
{
|
|
position = Input.mousePosition
|
|
};
|
|
List<RaycastResult> raycastResults = new List<RaycastResult>();
|
|
EventSystem.current.RaycastAll(pointerData, raycastResults);
|
|
if (raycastResults.Any(x => x.gameObject.layer == uiLayer))
|
|
{
|
|
lockHandler = true;
|
|
return;
|
|
}
|
|
CanvasManager.instance.GetCanvas<Canvas_DragArea>().panel_draghandler.OnBeginDrag(clickBeginPos);
|
|
}
|
|
private void OnMousePointerUp()
|
|
{
|
|
//rtg 컨트롤러가 조작중일때 락을 건다.
|
|
//rtg 컨트롤러 조작 후 포커스가 바뀌는 것을 방지하기 위한 용도
|
|
if (lockHandler == true)
|
|
{
|
|
lockHandler = false;
|
|
return;
|
|
}
|
|
//ui를 선택했을 경우에는 오브젝트 선택을 멈춘다.
|
|
PointerEventData pointerData = new PointerEventData(EventSystem.current)
|
|
{
|
|
position = Input.mousePosition
|
|
};
|
|
List<RaycastResult> raycastResults = new List<RaycastResult>();
|
|
EventSystem.current.RaycastAll(pointerData, raycastResults);
|
|
if (raycastResults.Any(x => x.gameObject.layer == uiLayer))
|
|
{
|
|
CanvasManager.instance.GetCanvas<Canvas_DragArea>().panel_draghandler.ForceEndDrag();
|
|
return;
|
|
}
|
|
//포인터 업 위치가 포인터 다운 위치에서 크게 벗어났을 경우는 클릭을 무시한다.
|
|
if ((clickBeginPos - Input.mousePosition).magnitude > clickLengthThreshold)
|
|
{
|
|
DeselectAll();
|
|
CanvasManager.instance.GetCanvas<Canvas_DragArea>().panel_draghandler.OnEndDrag(Input.mousePosition);
|
|
return;
|
|
}
|
|
List<CustomAssetRenderObject> raycastedTarget = new List<CustomAssetRenderObject>();
|
|
CustomAssetRenderObject renderObject = null;
|
|
foreach (var result in raycastResults)
|
|
{
|
|
renderObject = result.gameObject.GetComponent<CustomAssetRenderObject>();
|
|
if (renderObject != null)
|
|
{
|
|
raycastedTarget.Add(renderObject);
|
|
}
|
|
}
|
|
if (raycastedTarget.Count > 0)
|
|
{
|
|
//오브젝트가 여러개 겹쳐 있을 경우 뒤의 오브젝트를 순차적으로 선택해주기 위한 용도
|
|
if (selectIndex < raycastedTarget.Count && prevSelectedObject == raycastedTarget[selectIndex])
|
|
{
|
|
selectIndex++;
|
|
}
|
|
if (selectIndex >= raycastedTarget.Count)
|
|
{
|
|
selectIndex = 0;
|
|
}
|
|
renderObject = raycastedTarget[selectIndex];
|
|
//컨트롤이 눌려 있으면 오브젝트 선택을 토글한다. (유니티 기능과 일치)
|
|
if (Input.GetKey(KeyCode.LeftControl))
|
|
{
|
|
if (renderObject.ToggleSelect())
|
|
{
|
|
AddSelection(renderObject);
|
|
}
|
|
else
|
|
{
|
|
RemoveSelection(renderObject);
|
|
}
|
|
}
|
|
//시프트 키가 눌려 있는 경우 다중 선택 기능으로 작용한다.
|
|
else if (Input.GetKey(KeyCode.LeftShift))
|
|
{
|
|
AddSelection(renderObject);
|
|
}
|
|
//그 외는 선택된 아이템을 제외하고 다 비선택해준다.
|
|
else
|
|
{
|
|
RemoveAllSelections();
|
|
AddSelection(renderObject);
|
|
}
|
|
prevSelectedObject = renderObject;
|
|
OnSelect();
|
|
}
|
|
else
|
|
{
|
|
CommandInvoker.instance.Invoke(new ResetGizmoCommand());
|
|
DeselectAll();
|
|
}
|
|
CanvasManager.instance.GetCanvas<Canvas_DragArea>().panel_draghandler.ForceEndDrag();
|
|
}
|
|
public void DeselectAll()
|
|
{
|
|
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.LeftShift))
|
|
{
|
|
return;
|
|
}
|
|
RemoveAllSelections();
|
|
|
|
var canvas_Popup = CanvasManager.instance.GetCanvas<Canvas_Popup>();
|
|
canvas_Popup.panel_dynamicobjectinfo.ResetObjectInfo();
|
|
|
|
ManagerHub.instance.Get<CustomAssetConnector>().OnDeselectAll();
|
|
}
|
|
public void AddSelection(CustomAssetRenderObject item)
|
|
{
|
|
if (selectedRenderObjects.Any(x => x == item))
|
|
{
|
|
return;
|
|
}
|
|
item.Select();
|
|
selectedRenderObjects.Add(item);
|
|
selectedGameObjects.Add(item.gameObject);
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
public void AddSelection(List<CustomAssetRenderObject> items)
|
|
{
|
|
for (int i = 0; i < items.Count; i++)
|
|
{
|
|
CustomAssetRenderObject item = items[i];
|
|
AddSelection(item);
|
|
}
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
public void RemoveAllSelections()
|
|
{
|
|
for (int i = 0; i < selectedRenderObjects.Count; i++)
|
|
{
|
|
selectedRenderObjects[i].Deselect();
|
|
}
|
|
selectedRenderObjects.Clear();
|
|
selectedGameObjects.Clear();
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
|
|
public void RemoveSelection(CustomAssetRenderObject item)
|
|
{
|
|
Debug.Log("RemoveSelection");
|
|
item.Deselect();
|
|
selectedRenderObjects.Remove(item);
|
|
selectedGameObjects.Remove(item.gameObject);
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
private void OnSelect()
|
|
{
|
|
OnSelectObjectFromObjectHandler(selectedRenderObjects);
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
|
|
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>();
|
|
|
|
var connector = ManagerHub.instance.Get<CustomAssetConnector>();
|
|
for (int i = 0; i < objects.Count; i++)
|
|
{
|
|
ConnectedAsset searchAsset = connector.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);
|
|
}
|
|
connector.componentScrollView.OnSelect(selectedItems);
|
|
connector.OnSelectObjects(name, selectedObjects);
|
|
}
|
|
|
|
|
|
public void OnTransformBegin()
|
|
{
|
|
lockHandler = true;
|
|
}
|
|
public void OnTransformChangedFromRTG(List<GameObject> transformObjects)
|
|
{
|
|
OnTransformChanged(transformObjects);
|
|
CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_dynamicobjectinfo.OnTransformChanged(transformObjects);
|
|
CanvasManager.instance.GetCanvas<Canvas_DragArea>().panel_draghandler.ForceEndDrag();
|
|
}
|
|
public void OnTransformChanged(List<GameObject> transformObjects)
|
|
{
|
|
foreach (GameObject gb in transformObjects)
|
|
{
|
|
CustomAssetRenderObject renderObject = gb.GetComponent<CustomAssetRenderObject>();
|
|
if (renderObject != null)
|
|
{
|
|
renderObject.onTransformChanged?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
public void SaveItemsToCopy()
|
|
{
|
|
copyRenderObjects.Clear();
|
|
copyRenderObjects.AddRange(selectedRenderObjects);
|
|
}
|
|
public void ResetGizmoTargetObjects()
|
|
{
|
|
rtgController.SetGizmoTargetObjects(selectedGameObjects);
|
|
}
|
|
public void AlignObjects(int row, int col, float spaceX, float spaceZ, int direction)
|
|
{
|
|
if (selectedRenderObjects.Count <= 1)
|
|
{
|
|
return;
|
|
}
|
|
ManagerHub.instance.Get<CustomAssetConnector>().OrderByHierarchy(selectedRenderObjects);
|
|
List<CustomAssetRenderObject> objectsToAlign = new List<CustomAssetRenderObject>(selectedRenderObjects);
|
|
List<Vector3> originalPos = objectsToAlign.Select(x => x.transform.position).ToList();
|
|
|
|
direction = ((direction % 8) + 8) % 8;
|
|
int primary = direction % 2 == 0 ? col : row;
|
|
Vector3 primaryDir = Vector3.zero;
|
|
Vector3 secondaryDir = Vector3.zero;
|
|
primaryDir = (direction == 0 || direction == 2) ? Vector3.right * spaceX :
|
|
(direction == 4 || direction == 6) ? -Vector3.right * spaceX :
|
|
(direction == 1 || direction == 7) ? Vector3.forward * spaceZ : -Vector3.forward * spaceZ;
|
|
secondaryDir = (direction == 1 || direction == 3) ? Vector3.right * spaceX :
|
|
(direction == 5 || direction == 7) ? -Vector3.right * spaceX :
|
|
(direction == 0 || direction == 6) ? Vector3.forward * spaceZ : -Vector3.forward * spaceZ;
|
|
|
|
ActionCommand command = new ActionCommand(
|
|
() => Align(objectsToAlign, primary, primaryDir, secondaryDir),
|
|
() => UndoAlign(objectsToAlign, originalPos));
|
|
CommandInvoker.instance.Invoke(command);
|
|
}
|
|
|
|
|
|
private void Align(List<CustomAssetRenderObject> objectsToAlign, int primary, Vector3 primaryDir, Vector3 secondaryDir)
|
|
{
|
|
int countP = 0;
|
|
int countS = 0;
|
|
Vector3 referencePoint = objectsToAlign[0].transform.position;
|
|
for (int i = 1; i < objectsToAlign.Count; i++)
|
|
{
|
|
CustomAssetRenderObject renderObject = objectsToAlign[i];
|
|
if (countP < primary - 1 || primary == 0)
|
|
{
|
|
countP++;
|
|
}
|
|
else
|
|
{
|
|
countS++;
|
|
countP = 0;
|
|
}
|
|
renderObject.transform.position = referencePoint + primaryDir * countP + secondaryDir * countS;
|
|
renderObject.onTransformChanged?.Invoke();
|
|
}
|
|
|
|
CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_dynamicobjectinfo.OnTransformChanged(objectsToAlign.Select(renderObject => renderObject.gameObject).ToList());
|
|
}
|
|
|
|
private void UndoAlign(List<CustomAssetRenderObject> objectsToAlign, List<Vector3> originalPos)
|
|
{
|
|
for (int i = 1; i < objectsToAlign.Count; i++)
|
|
{
|
|
CustomAssetRenderObject renderObject = objectsToAlign[i];
|
|
renderObject.transform.position = originalPos[i];
|
|
renderObject.onTransformChanged?.Invoke();
|
|
}
|
|
CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_dynamicobjectinfo.OnTransformChanged(objectsToAlign.Select(renderObject => renderObject.gameObject).ToList());
|
|
}
|
|
InputHandler myHandler;
|
|
|
|
public void StatusEnterEvent()
|
|
{
|
|
userInputManager.SetHandler(myHandler);
|
|
}
|
|
|
|
public void StatusExitEvent()
|
|
{
|
|
userInputManager .RemoveHandler(myHandler);
|
|
}
|
|
|
|
|
|
public InputHandler GetInputHandler()
|
|
{
|
|
var getKeyActions = new Dictionary<KeyCode, Action>();
|
|
var downKeyActions = new Dictionary<KeyCode, Action>();
|
|
var upKeyActions = new Dictionary<KeyCode, Action>();
|
|
|
|
downKeyActions.Add(KeyCode.Mouse0, OnMousePointerDown);
|
|
upKeyActions.Add(KeyCode.Mouse0, OnMousePointerUp);
|
|
downKeyActions.Add(KeyCode.Mouse1, OnMouseRightPointerDown);
|
|
upKeyActions.Add(KeyCode.Mouse1, OnMouseRightPointerUp);
|
|
downKeyActions.Add(KeyCode.W, () => SetGizmoChangedCommand(new ActivateMoveGizmoCommand()));
|
|
downKeyActions.Add(KeyCode.E, () => SetGizmoChangedCommand(new ActivateRotateGizmoCommand()));
|
|
downKeyActions.Add(KeyCode.R, () => SetGizmoChangedCommand(new ActivateScaleGizmoCommand()));
|
|
//downKeyActions.Add(KeyCode.R, () => SetGizmoChangedCommand(new ResetGizmoCommand()));
|
|
downKeyActions.Add(KeyCode.Delete, () => CommandInvoker.instance.Invoke(new RemoveSelectObjectCommand()));
|
|
|
|
var shortcutTable = new Dictionary<KeyCode, Dictionary<KeyCode, Action>>();
|
|
#if UNITY_EDITOR
|
|
shortcutTable.Add(KeyCode.LeftControl, new Dictionary<KeyCode, Action>());
|
|
//shortcutTable[KeyCode.LeftShift].Add(KeyCode.C, SaveItemsToCopy);
|
|
//shortcutTable[KeyCode.LeftShift].Add(KeyCode.V, () => CommandInvoker.instance.Invoke(new CopyObjectCommand()));
|
|
shortcutTable[KeyCode.LeftControl].Add(KeyCode.D, () =>
|
|
{
|
|
if (ManagerHub.instance.Get<RenderObjectHandler>().selectedRenderObjects.Count == 0)
|
|
return;
|
|
CommandInvoker.instance.Invoke(new CopyObjectCommand());
|
|
// CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_toastmessage.ActivateMessage("Copy");
|
|
});
|
|
#else
|
|
shortcutTable.Add(KeyCode.LeftControl, new Dictionary<KeyCode, Action>());
|
|
//shortcutTable[KeyCode.LeftControl].Add(KeyCode.C, SaveItemsToCopy);
|
|
//shortcutTable[KeyCode.LeftControl].Add(KeyCode.V, () => CommandInvoker.instance.Invoke(new CopyObjectCommand()));
|
|
shortcutTable[KeyCode.LeftControl].Add(KeyCode.D, () =>
|
|
{
|
|
if (ManagerHub.instance.Get<RenderObjectHandler>().selectedRenderObjects.Count == 0)
|
|
return;
|
|
CommandInvoker.instance.Invoke(new CopyObjectCommand());
|
|
// CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_toastmessage.ActivateMessage("Copy");
|
|
});
|
|
#endif
|
|
|
|
var handler = new InputHandler(getKeyActions, downKeyActions, upKeyActions, shortcutTable);
|
|
return handler;
|
|
}
|
|
private void OnMouseRightPointerDown()
|
|
{
|
|
inputLockhandler = true;
|
|
}
|
|
private void OnMouseRightPointerUp()
|
|
{
|
|
inputLockhandler = false;
|
|
}
|
|
private void SetGizmoChangedCommand(IIrreversibleCommand command)
|
|
{
|
|
if (!inputLockhandler)
|
|
{
|
|
CommandInvoker.instance.Invoke(command);
|
|
}
|
|
}
|
|
}
|
|
}
|