Files
XCEngine/参考/TransformGizmo/Scripts/DirectController.cs
2026-03-29 01:36:53 +08:00

284 lines
8.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class DirectController
{
private RuntimeTranslateGizmo translateGizmo;
private RuntimeRotateGizmo rotateGizmo;
private SelectDetector selectDetector;
private GameObject targetObject;
private Material outlineMaterial;
private Color orangeOutline = new Color(1, 0.5f, 0, 1);
private Color blueOutline = new Color(0, 0, 1, 1);
private enum GizmoState { TRANSLATE, ROTATE }
private GizmoState gizmoState = GizmoState.TRANSLATE;
public void Initialize(SelectDetector selectDetector)
{
//OutLine Shader Initialize
Shader outlineShader = Shader.Find("Custom/Outline");
outlineMaterial = new Material(outlineShader);
//SelectDetector Initialize
this.selectDetector = selectDetector;
}
public void InitializeGizmo()
{
//Gizmo Initialize
translateGizmo = new RuntimeTranslateGizmo();
rotateGizmo = new RuntimeRotateGizmo();
translateGizmo.Initialize();
rotateGizmo.Initialize();
selectDetector.AddGizmos(translateGizmo.gizmo);
selectDetector.AddGizmos(rotateGizmo.gizmo);
}
public void Update()
{
//Object Select Update
//Select by cursor when the cursor is not on ui panels.
if (Input.GetMouseButtonDown(0))
{
SelectUpdateByCursor(selectDetector.detectedObject);
}
//Gizmo Select Update
if (targetObject)
{
GizmoSelectUpdate();
}
//Gizmo Update
translateGizmo.Update();
rotateGizmo.Update();
}
private void SelectUpdateByCursor(GameObject selectedObject)
{
//Select
if (selectedObject != null)
{
//The First Select
if (targetObject == null)
{
//Select the TopMost Parent GameObject
targetObject = GetTopmostParent(selectedObject);
AddOutlines(targetObject, blueOutline);
EnableTargetGizmo();
}
//The Second Select
else
{
if(selectedObject != targetObject)
{
GameObject parent = GetTopmostParent(selectedObject);
if (parent == targetObject)
{
//Select Child of the TopMost Parent GameObject(Selected the TopMost Parent GameObject before)
RemoveOutlines(targetObject);
targetObject = selectedObject;
AddOutLine(targetObject, orangeOutline);
EnableTargetGizmo();
}
else if (parent == GetTopmostParent(targetObject))
{
//Select Other Child of the TopMost Parent GameObject(Selected one child of the TopMost Parent GameObject before)
RemoveOutLine(targetObject);
targetObject = selectedObject;
AddOutLine(targetObject, orangeOutline);
EnableTargetGizmo();
}
else
{
//Select Other TopMost Parent GameObject
RemoveOutlines(targetObject);
targetObject = parent;
AddOutlines(targetObject, blueOutline);
EnableTargetGizmo();
}
}
else
{
RemoveOutlines(targetObject);
AddOutLine(targetObject, orangeOutline);
}
}
}
//UnSelect
else if (selectedObject == null && selectDetector.detectedGizmo == null)
{
if (targetObject)
{
RemoveOutlines(targetObject);
targetObject = null;
}
if (translateGizmo.enabled)
{
translateGizmo.DisableGizmo();
}
if (rotateGizmo.enabled)
{
rotateGizmo.DisableGizmo();
}
}
}
private void GizmoSelectUpdate()
{
//Translate
if (Input.GetKeyDown(KeyCode.W))
{
ChangeGizmoToTranslate();
}
if (translateGizmo.enabled)
{
if (Input.GetMouseButtonDown(0))
{
GameObject selectedGizmo = selectDetector.detectedGizmo;
if (selectedGizmo != null)
{
translateGizmo.OnSelect(selectedGizmo.name);
}
}
else if (Input.GetMouseButtonUp(0))
{
translateGizmo.OnUnSelect();
}
}
//Rotate
if (Input.GetKeyDown(KeyCode.E))
{
ChangeGizmoToRotate();
}
if (rotateGizmo.enabled)
{
GameObject selectedGizmo = selectDetector.detectedGizmo;
if (selectedGizmo != null)
{
rotateGizmo.SphereRenderUpdate(selectedGizmo.name);
if (Input.GetMouseButtonDown(0))
{
rotateGizmo.OnSelect(selectedGizmo.name);
}
}
else { rotateGizmo.SphereRenderUpdate(""); }
if (Input.GetMouseButtonUp(0))
{
rotateGizmo.OnUnSelect();
}
}
}
private void EnableTargetGizmo()
{
if (targetObject == null) { return; }
switch (gizmoState)
{
case GizmoState.TRANSLATE:
translateGizmo.EnableGizmo(targetObject);
break;
case GizmoState.ROTATE:
rotateGizmo.EnableGizmo(targetObject);
break;
}
}
private GameObject GetTopmostParent(GameObject gameObject)
{
GameObject current = gameObject;
while (current.transform.parent != null && !current.transform.parent.gameObject.name.Equals("Factory"))
{
current = current.transform.parent.gameObject;
}
return current;
}
private void AddOutLine(GameObject gameObject, Color color)
{
Renderer renderer = gameObject.GetComponent<Renderer>();
if (renderer != null)
{
outlineMaterial.SetColor("_OutlineColor", color);
List<Material> materials = renderer.materials.ToList<Material>();
if(!materials.Contains(outlineMaterial))
{
materials.Add(outlineMaterial);
renderer.materials = materials.ToArray();
}
}
}
private void RemoveOutLine(GameObject gameObject)
{
Renderer renderer = gameObject.GetComponent<Renderer>();
if (renderer != null)
{
List<Material> materials = renderer.materials.ToList<Material>();
foreach (var material in materials)
{
if (material.shader.name == outlineMaterial.shader.name)
{
materials.Remove(material);
break;
}
}
renderer.materials = materials.ToArray();
}
}
private void AddOutlines(GameObject gameObject, Color color)
{
foreach (Transform child_transform in gameObject.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
AddOutLine(child, color);
}
}
private void RemoveOutlines(GameObject gameObject)
{
foreach (Transform child_transform in gameObject.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
RemoveOutLine(child);
}
}
private void ChangeGizmoToTranslate()
{
gizmoState = GizmoState.TRANSLATE;
if (!translateGizmo.enabled)
{
EnableTargetGizmo();
}
if (rotateGizmo.enabled)
{
rotateGizmo.DisableGizmo();
}
}
private void ChangeGizmoToRotate()
{
gizmoState = GizmoState.ROTATE;
if (!rotateGizmo.enabled)
{
EnableTargetGizmo();
}
if (translateGizmo.enabled)
{
translateGizmo.DisableGizmo();
}
}
}