chore: sync workspace state

This commit is contained in:
2026-03-29 01:36:53 +08:00
parent eb5de3e3d4
commit e5cb79f3ce
4935 changed files with 35593 additions and 360696 deletions

View File

@@ -0,0 +1,283 @@
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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 019a98c1111d28a42ab5ebc611903c4f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RuntimeGizmo
{
public GameObject gizmo;
protected GameObject prefab;
public bool enabled = false;
protected GameObject target;
protected List<string> handleNames;
protected float scaleRate = 1.0f;
public virtual void Initialize() { }
public virtual List<GameObject> RegisterObjectsToSelectDetector() { return null; } //这样可以让Gizmo的指定组件可以使用TransformGizmo的操纵
public virtual void Update() { }
protected virtual void RenderUpdate()
{
//Gizmo Scale Update
Vector3 cameraPosition = Camera.main.transform.position;
Vector3 gizmoPosition = gizmo.transform.position;
float distance = (cameraPosition - gizmoPosition).magnitude;
gizmo.GetComponent<Transform>().localScale = new Vector3(distance, distance, distance);
}
protected virtual void FollowUpdate() { }
protected void HideBeindCamera()
{
if (gizmo.activeSelf) { gizmo.SetActive(false); }
gizmo.GetComponent<Transform>().position = Camera.main.transform.position - Camera.main.transform.forward * 10;
}
public virtual void EnableGizmo(GameObject target)
{
enabled = true;
this.target = target;
if (!gizmo.activeSelf) { gizmo.SetActive(true); }
gizmo.GetComponent<Transform>().position = target.transform.position;
gizmo.GetComponent<Transform>().rotation = target.transform.rotation;
}
public virtual void DisableGizmo()
{
enabled = false;
this.target = null;
HideBeindCamera();
}
public virtual void OnSelect(string handleName) { }
public virtual void OnUnSelect() { }
protected virtual void OnSelecting() { }
protected virtual void ChangeRenderOnSelect() { }
protected virtual void ChangeRenderOnUnSelect() { }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5457f7831add57d4c931055617ae1e43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,284 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UIElements;
public class RuntimeRotateGizmo : RuntimeTransformGizmo
{
private string prefabPath = "Prefabs/RotateGizmo";
private GameObject rotatePlane;
private GameObject rotatePlaneHandle;
private GameObject rotateXYZ;
private GameObject rotateX;
private GameObject rotateY;
private GameObject rotateZ;
private GameObject rotateSphere;
enum RotateSelectState { X, Y, Z, Plane, Sphere, UnSelected }
RotateSelectState rotateSelectState;
//Offset
private float XYZOffsetOnSelect;
private Vector2 sphereOffsetOnSelect;
//Rate
private float XYZRotateRate = 0.1f;
private float planeRotateRate = 0.1f;
private float sphereRotateRate = 0.1f;
private Quaternion rotationOnSelect;
private Vector3 viewLocalDirectionX;
private Vector3 viewLocalDirectionY;
private Vector3 viewLocalDirectionZ;
private Quaternion lastTargetRotation;
public override void Initialize()
{
//Base Initialize
base.Initialize();
//Material Initialize
redMaterial = Resources.Load<Material>("Materials/RotateRed");
greenMaterial = Resources.Load<Material>("Materials/RotateGreen");
blueMaterial = Resources.Load<Material>("Materials/RotateBlue");
////Prefab Initialize
prefab = Resources.Load<GameObject>(prefabPath);
if (prefab != null)
{
gizmo = Object.Instantiate(prefab) as GameObject;
}
HideBeindCamera();
//Component Initialize
rotatePlane = gizmo.GetComponent<Transform>().Find("RotatePlane").gameObject;
rotatePlaneHandle = rotatePlane.GetComponent<Transform>().Find("RotatePlaneHandle").gameObject;
rotateXYZ = gizmo.GetComponent<Transform>().Find("RotateXYZ").gameObject;
rotateX = rotateXYZ.GetComponent<Transform>().Find("RotateX").gameObject;
rotateY = rotateXYZ.GetComponent<Transform>().Find("RotateY").gameObject;
rotateZ = rotateXYZ.GetComponent<Transform>().Find("RotateZ").gameObject;
rotateSphere = gizmo.GetComponent<Transform>().Find("RotateSphere").gameObject;
//Other Initialzie
rotateSelectState = RotateSelectState.UnSelected;
rotateSphere.GetComponent<MeshRenderer>().material.SetFloat("_AlphaScale", 0.2f);
scaleRate = 160.0f;
handleNames = new List<string> { "RotatePlaneHandle", "RotatePlaneDetect", "RotateXDetect", "RotateX", "RotateYDetect", "RotateY", "RotateZDetect", "RotateZ", "RotateSphere" };
}
public override void Update()
{
//hide
if(enabled)
{
//Render Update
RenderUpdate();
//Follow Update
FollowUpdate();
//Interaction Update
if (rotateSelectState != RotateSelectState.UnSelected)
{
OnSelecting();
}
}
else
{
HideBeindCamera();
}
}
protected override void RenderUpdate()
{
//Base Update
base.RenderUpdate();
gizmo.GetComponent<Transform>().localScale /= scaleRate;
//Rotate Plane Update
Vector3 viewDirection = -Camera.main.transform.forward;
Quaternion rotatePlaneRotation = Quaternion.LookRotation(viewDirection, Vector3.up);
rotatePlane.GetComponent<Transform>().rotation = rotatePlaneRotation;
//Clip Plane Update
Vector3 normalizedNormal = viewDirection.normalized;
Vector3 targetPosition = gizmo.GetComponent<Transform>().position;
float D = -Vector3.Dot(targetPosition, normalizedNormal);
Vector4 clipPlane = new Vector4(normalizedNormal.x, normalizedNormal.y, normalizedNormal.z, D);
redMaterial.SetVector("_ClipPlane", clipPlane);
greenMaterial.SetVector("_ClipPlane", clipPlane);
blueMaterial.SetVector("_ClipPlane", clipPlane);
}
public override void EnableGizmo(GameObject target)
{
base.EnableGizmo(target);
lastTargetRotation = target.GetComponent<Transform>().rotation;
}
protected override void FollowUpdate()
{
if (target == null) { return; }
//Position Follow
gizmo.GetComponent<Transform>().position = target.GetComponent<Transform>().position;
target.GetComponent<Transform>().rotation = gizmo.GetComponent<Transform>().rotation;
//Rotation Follow
Quaternion targetRotation = target.GetComponent<Transform>().rotation;
if (targetRotation != lastTargetRotation)
{
gizmo.GetComponent<Transform>().rotation = targetRotation;
}
else
{
target.GetComponent<Transform>().rotation = gizmo.GetComponent<Transform>().rotation;
}
lastTargetRotation = targetRotation;
}
public override void OnSelect(string handleName)
{
if (!handleNames.Contains(handleName)) { return; }
rotationOnSelect = gizmo.GetComponent<Transform>().rotation;
Vector3 gizmoPosition = gizmo.GetComponent<Transform>().position;
Vector2 mousePositionOnSelect = Input.mousePosition;
gizmoXYZScreenStart = Camera.main.WorldToScreenPoint(gizmoPosition);
if (handleName.Contains("X") || handleName.Contains("Y") || handleName.Contains("Z")) //RotateX RotateY RotateZ
{
Vector3 gizmoEndPosition = new Vector3();
switch (handleName)
{
case "RotateX":
case "RotateXDetect":
rotateSelectState = RotateSelectState.X;
gizmoEndPosition = gizmoPosition + gizmo.GetComponent<Transform>().right;
break;
case "RotateY":
case "RotateYDetect":
rotateSelectState = RotateSelectState.Y;
gizmoEndPosition = gizmoPosition + gizmo.GetComponent<Transform>().up;
break;
case "RotateZ":
case "RotateZDetect":
rotateSelectState = RotateSelectState.Z;
gizmoEndPosition = gizmoPosition + gizmo.GetComponent<Transform>().forward;
break;
}
Vector2 gizmoXYZScreenEnd = Camera.main.WorldToScreenPoint(gizmoEndPosition);
gizmoXYZScreenDirection = (gizmoXYZScreenEnd - gizmoXYZScreenStart).normalized;
Vector2 gizmoXYZXcreenVerticalDirection = new Vector2(gizmoXYZScreenDirection.y, -gizmoXYZScreenDirection.x);
Vector2 mouseVector = mousePositionOnSelect - gizmoXYZScreenStart;
XYZOffsetOnSelect = Vector2.Dot(mouseVector, gizmoXYZXcreenVerticalDirection);
}
else if (handleName == "RotatePlaneDetect" || handleName == "RotatePlaneHandle")
{
rotateSelectState = RotateSelectState.Plane;
gizmoXYZScreenDirection = (mousePositionOnSelect - gizmoXYZScreenStart).normalized;
XYZOffsetOnSelect = 0.0f;
Vector3 viewDirectionZ = Camera.main.transform.forward;
viewLocalDirectionZ = (gizmo.GetComponent<Transform>().worldToLocalMatrix * viewDirectionZ).normalized;
}
else if(handleName == "RotateSphere")
{
rotateSelectState = RotateSelectState.Sphere;
sphereOffsetOnSelect = mousePositionOnSelect - gizmoXYZScreenStart;
Vector3 viewDirectionX = Camera.main.transform.right;
viewLocalDirectionX = (gizmo.GetComponent<Transform>().worldToLocalMatrix * viewDirectionX).normalized;
Vector3 viewDirectionY = Camera.main.transform.up;
viewLocalDirectionY = (gizmo.GetComponent<Transform>().worldToLocalMatrix * viewDirectionY).normalized;
}
ChangeRenderOnSelect();
}
public override void OnUnSelect()
{
if (rotateSelectState == RotateSelectState.UnSelected) { return; }
rotateSelectState = RotateSelectState.UnSelected;
//Render
ChangeRenderOnUnSelect();
}
protected override void OnSelecting()
{
Vector3 gizmoPosition = gizmo.GetComponent<Transform>().position;
Vector2 mousePosition = Input.mousePosition;
Vector2 mouseVector = mousePosition - gizmoXYZScreenStart;
if (rotateSelectState <= RotateSelectState.Plane)
{
//Rotate 90 degrees clockwise
Vector2 gizmoXYZScreenVerticalDirection = new Vector2(gizmoXYZScreenDirection.y, -gizmoXYZScreenDirection.x);
float dragDistance = Vector2.Dot(mouseVector, gizmoXYZScreenVerticalDirection) - XYZOffsetOnSelect;
switch (rotateSelectState)
{
case RotateSelectState.X:
gizmo.GetComponent<Transform>().rotation = rotationOnSelect * Quaternion.Euler(-Vector3.right * dragDistance * XYZRotateRate);
break;
case RotateSelectState.Y:
gizmo.GetComponent<Transform>().rotation = rotationOnSelect * Quaternion.Euler(-Vector3.up * dragDistance * XYZRotateRate);
break;
case RotateSelectState.Z:
gizmo.GetComponent<Transform>().rotation = rotationOnSelect * Quaternion.Euler(-Vector3.forward * dragDistance * XYZRotateRate);
break;
case RotateSelectState.Plane:
gizmo.GetComponent<Transform>().rotation = rotationOnSelect * Quaternion.Euler(-viewLocalDirectionZ * dragDistance * planeRotateRate);
break;
}
}
else if (rotateSelectState == RotateSelectState.Sphere)
{
Vector2 dragVector = mouseVector - sphereOffsetOnSelect;
gizmo.GetComponent<Transform>().rotation = rotationOnSelect * Quaternion.Euler(-viewLocalDirectionY * dragVector.x * sphereRotateRate);
gizmo.GetComponent<Transform>().rotation = gizmo.transform.rotation * Quaternion.Euler(viewLocalDirectionX * dragVector.y * sphereRotateRate);
}
}
protected override void ChangeRenderOnSelect()
{
switch (rotateSelectState)
{
case RotateSelectState.X:
rotatePlaneHandle.SetActive(false);
rotateX.GetComponent<MeshRenderer>().material = yellowMaterial;
break;
case RotateSelectState.Y:
rotatePlaneHandle.SetActive(false);
rotateY.GetComponent<MeshRenderer>().material = yellowMaterial;
break;
case RotateSelectState.Z:
rotatePlaneHandle.SetActive(false);
rotateZ.GetComponent<MeshRenderer>().material = yellowMaterial;
break;
case RotateSelectState.Plane:
rotateX.GetComponent<MeshRenderer>().material = whiteMaterial;
rotateY.GetComponent<MeshRenderer>().material = whiteMaterial;
rotateZ.GetComponent<MeshRenderer>().material = whiteMaterial;
rotatePlaneHandle.GetComponent<MeshRenderer>().material = yellowMaterial;
break;
case RotateSelectState.Sphere:
rotateSphere.GetComponent<MeshRenderer>().material.SetFloat("_AlphaScale", 0.4f);
rotateSphere.SetActive(true);
rotatePlaneHandle.GetComponent<MeshRenderer>().material = whiteMaterial;
break;
}
}
protected override void ChangeRenderOnUnSelect()
{
rotatePlaneHandle.SetActive(true);
rotateX.SetActive(true);
rotateY.SetActive(true);
rotateZ.SetActive(true);
rotatePlaneHandle.GetComponent<MeshRenderer>().material = whiteMaterial;
rotateX.GetComponent<MeshRenderer>().material = redMaterial;
rotateY.GetComponent<MeshRenderer>().material = greenMaterial;
rotateZ.GetComponent<MeshRenderer>().material = blueMaterial;
rotateSphere.GetComponent<MeshRenderer>().material.SetFloat("_AlphaScale", 0.2f);
}
public void SphereRenderUpdate(string handleName)
{
if (rotateSelectState != RotateSelectState.UnSelected) { return; }
rotateSphere.SetActive(handleName.Equals("RotateSphere"));
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df5ef9b135776ed44bdf6f431703cc5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class RuntimeTransformGizmo : RuntimeGizmo
{
protected Material redMaterial;
protected Material greenMaterial;
protected Material blueMaterial;
protected Material yellowMaterial;
protected Material whiteMaterial;
//the vector projected by Gizmo XYZ axis on the screen
protected Vector2 gizmoXYZScreenStart;
protected Vector2 gizmoXYZScreenDirection;
protected enum Axis { X, Y, Z }
public override void Initialize()
{
//Material Initialize
yellowMaterial = Resources.Load<Material>("Materials/Yellow");
whiteMaterial = Resources.Load<Material>("Materials/White");
}
public override void Update() { }
protected override void RenderUpdate()
{
base.RenderUpdate();
}
protected override void FollowUpdate() { }
public override void EnableGizmo(GameObject target)
{
base.EnableGizmo(target);
}
public override void DisableGizmo()
{
base.DisableGizmo();
}
public override void OnSelect(string handleName) { }
public override void OnUnSelect() { }
protected override void OnSelecting() { }
protected override void ChangeRenderOnSelect() { }
protected override void ChangeRenderOnUnSelect() { }
protected Vector3? GetIntersectionPlaneAndLine(Axis axis, Vector3 lineStart, Vector3 lineDirection)
{
Vector4 plane = GetPlane(axis);
Vector3 planeNormal = new Vector3(plane.x, plane.y, plane.z);
Vector3? intersectionPoint = GetIntersectionPlaneAndLine(planeNormal, plane.w, lineStart, lineDirection);
return intersectionPoint;
}
protected Vector3? GetIntersectionPlaneAndLine(Vector3 planeNormal, float d, Vector3 lineStart, Vector3 lineDirection)
{
// Plane: Ax + By + Cz + D = 0
// Line: P(t) = P0 + tD
float a = planeNormal.x;
float b = planeNormal.y;
float c = planeNormal.z;
float dx = lineDirection.x;
float dy = lineDirection.y;
float dz = lineDirection.z;
float denominator = a * dx + b * dy + c * dz;
if (Math.Abs(denominator) < 0.0001f) return null;
float t = -(a * lineStart.x + b * lineStart.y + c * lineStart.z + d) / denominator;
Vector3 intersectionPoint = lineStart + t * lineDirection;
return intersectionPoint;
}
protected Vector4 GetPlane(Axis axis)
{
Vector4 plane = new Vector4();
Vector3 normal = new Vector3();
switch (axis)
{
case Axis.X:
normal = gizmo.GetComponent<Transform>().right;
break;
case Axis.Y:
normal = gizmo.GetComponent<Transform>().up;
break;
case Axis.Z:
normal = gizmo.GetComponent<Transform>().forward;
break;
}
plane.x = normal.x;
plane.y = normal.y;
plane.z = normal.z;
Vector3 position = gizmo.GetComponent<Transform>().position;
plane.w = -Vector3.Dot(position,normal);
return plane;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f10630399e8d77e46960c12087ee2b69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,336 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RuntimeTranslateGizmo : RuntimeTransformGizmo
{
private string prefabPath = "Prefabs/TranslateGizmo";
private GameObject translateX;
private GameObject translateY;
private GameObject translateZ;
private GameObject translatePlaneX;
private GameObject translatePlaneY;
private GameObject translatePlaneZ;
private float translatePlaneOffset = 0.15f;
private Vector3 screenCenterPosition;
enum TranslateSelectState { X, Y, Z, PlaneX, PlaneY, PlaneZ, UnSelected }
TranslateSelectState translateSelectState;
private float XYZOffsetOnSelect;
private Vector2 gizmoPlaneOffset;
private Vector3 lastTargetPosition;
public override void Initialize()
{
//Base Initialize
base.Initialize();
//Material Initialize
redMaterial = Resources.Load<Material>("Materials/Red");
greenMaterial = Resources.Load<Material>("Materials/Green");
blueMaterial = Resources.Load<Material>("Materials/Blue");
//Prefab Initialize
prefab = Resources.Load<GameObject>(prefabPath);
if (prefab != null)
{
gizmo = Object.Instantiate(prefab) as GameObject;
}
HideBeindCamera();
//Component Initialize
translateX = gizmo.GetComponent<Transform>().Find("TranslateX").gameObject;
translateY = gizmo.GetComponent<Transform>().Find("TranslateY").gameObject;
translateZ = gizmo.GetComponent<Transform>().Find("TranslateZ").gameObject;
translatePlaneX = gizmo.GetComponent<Transform>().Find("TranslatePlaneX").gameObject;
translatePlaneY = gizmo.GetComponent<Transform>().Find("TranslatePlaneY").gameObject;
translatePlaneZ = gizmo.GetComponent<Transform>().Find("TranslatePlaneZ").gameObject;
//Other Initialzie
translateSelectState = TranslateSelectState.UnSelected;
screenCenterPosition = new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, 0);
scaleRate = 6.0f;
handleNames = new List<string> { "TranslateX", "TranslateY", "TranslateZ", "TranslatePlaneX", "TranslatePlaneY", "TranslatePlaneZ" };
}
public override void Update()
{
//hide
if (enabled && target)
{
//Render Update
RenderUpdate();
//Follow Update
FollowUpdate();
//Interaction Update
if (translateSelectState != TranslateSelectState.UnSelected)
{
OnSelecting();
}
}
else
{
HideBeindCamera();
}
}
protected override void RenderUpdate()
{
//Base Update
base.RenderUpdate();
gizmo.GetComponent<Transform>().localScale /= scaleRate;
//Translate Plane Update
Vector3 viewPosition = Camera.main.ScreenToWorldPoint(screenCenterPosition);
Vector3 viewDirection = viewPosition - gizmo.GetComponent<Transform>().position;
Vector3 viewLocalDirection = gizmo.GetComponent<Transform>().worldToLocalMatrix.MultiplyVector(viewDirection);
int directionX = viewLocalDirection.x > 0 ? 1 : -1;
int directionY = viewLocalDirection.y > 0 ? 1 : -1;
int directionZ = viewLocalDirection.z > 0 ? 1 : -1;
translatePlaneX.GetComponent<Transform>().localPosition = Vector3.zero;
translatePlaneX.GetComponent<Transform>().localPosition += directionY * Vector3.up * translatePlaneOffset;
translatePlaneX.GetComponent<Transform>().localPosition += directionZ * Vector3.forward * translatePlaneOffset;
translatePlaneY.GetComponent<Transform>().localPosition = Vector3.zero;
translatePlaneY.GetComponent<Transform>().localPosition += directionX * Vector3.right * translatePlaneOffset;
translatePlaneY.GetComponent<Transform>().localPosition += directionZ * Vector3.forward * translatePlaneOffset;
translatePlaneZ.GetComponent<Transform>().localPosition = Vector3.zero;
translatePlaneZ.GetComponent<Transform>().localPosition += directionX * Vector3.right * translatePlaneOffset;
translatePlaneZ.GetComponent<Transform>().localPosition += directionY * Vector3.up * translatePlaneOffset;
}
protected override void FollowUpdate()
{
if (target == null) { return; }
//Rotation Follow
Vector3 targetPosition = target.GetComponent<Transform>().position;
if (targetPosition != lastTargetPosition)
{
gizmo.GetComponent<Transform>().position = targetPosition;
}
else
{
target.GetComponent<Transform>().position = gizmo.GetComponent<Transform>().position;
}
lastTargetPosition = targetPosition;
//Rotation Follow
gizmo.GetComponent<Transform>().rotation = target.GetComponent<Transform>().rotation;
}
public override void EnableGizmo(GameObject target)
{
base.EnableGizmo(target);
lastTargetPosition = target.GetComponent<Transform>().position;
}
public override void OnSelect(string handleName)
{
if (!handleNames.Contains(handleName)) { return; }
Vector3 gizmoPosition = gizmo.GetComponent<Transform>().position;
Vector2 mousePositionOnSelect = Input.mousePosition;
gizmoXYZScreenStart = Camera.main.WorldToScreenPoint(gizmoPosition);
if (!handleName.Contains("Plane"))
{
Vector3 gizmoEndPosition = new Vector3();
switch (handleName)
{
case "TranslateX":
translateSelectState = TranslateSelectState.X;
gizmoEndPosition = gizmoPosition + 10 * gizmo.GetComponent<Transform>().right;
break;
case "TranslateY":
translateSelectState = TranslateSelectState.Y;
gizmoEndPosition = gizmoPosition + 10 * gizmo.GetComponent<Transform>().up;
break;
case "TranslateZ":
translateSelectState = TranslateSelectState.Z;
gizmoEndPosition = gizmoPosition + 10 * gizmo.GetComponent<Transform>().forward;
break;
}
Vector2 gizmoXYZScreenEnd = Camera.main.WorldToScreenPoint(gizmoEndPosition);
gizmoXYZScreenDirection = (gizmoXYZScreenEnd - gizmoXYZScreenStart).normalized;
XYZOffsetOnSelect = Vector2.Dot(mousePositionOnSelect - gizmoXYZScreenStart, gizmoXYZScreenDirection);
}
else
{
switch (handleName)
{
case "TranslatePlaneX":
translateSelectState = TranslateSelectState.PlaneX;
break;
case "TranslatePlaneY":
translateSelectState = TranslateSelectState.PlaneY;
break;
case "TranslatePlaneZ":
translateSelectState = TranslateSelectState.PlaneZ;
break;
}
gizmoPlaneOffset = new Vector2(mousePositionOnSelect.x - gizmoXYZScreenStart.x, mousePositionOnSelect.y - gizmoXYZScreenStart.y);
}
ChangeRenderOnSelect();
}
public override void OnUnSelect()
{
if (translateSelectState == TranslateSelectState.UnSelected) { return; }
translateSelectState = TranslateSelectState.UnSelected;
//Render
ChangeRenderOnUnSelect();
}
protected override void OnSelecting()
{
Vector2 mousePosition = Input.mousePosition;
Vector3 targetPosition = new Vector3();
Vector3 gizmoPosition = gizmo.GetComponent<Transform>().position;
Vector3 viewPosition = Camera.main.ScreenToWorldPoint(screenCenterPosition);
//Translate XYZ Axis
if (translateSelectState <= TranslateSelectState.Z)
{
float dragDistance = Vector2.Dot(mousePosition - gizmoXYZScreenStart, gizmoXYZScreenDirection) - XYZOffsetOnSelect;
Vector2 dragScreenPosition = gizmoXYZScreenStart + gizmoXYZScreenDirection * dragDistance;
Vector3 dragRayDirection = Camera.main.ScreenPointToRay(dragScreenPosition).direction;
switch (translateSelectState)
{
case TranslateSelectState.X:
Vector3? intersectionXY = GetIntersectionPlaneAndLine(Axis.Y, viewPosition, dragRayDirection);
Vector3? intersectionXZ = GetIntersectionPlaneAndLine(Axis.Z, viewPosition, dragRayDirection);
targetPosition = GetMediaPoint(intersectionXY, intersectionXZ).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
case TranslateSelectState.Y:
Vector3? intersectionYX = GetIntersectionPlaneAndLine(Axis.X, viewPosition, dragRayDirection);
Vector3? intersectionYZ = GetIntersectionPlaneAndLine(Axis.Z, viewPosition, dragRayDirection);
targetPosition = GetMediaPoint(intersectionYX, intersectionYZ).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
case TranslateSelectState.Z:
Vector3? intersectionZX = GetIntersectionPlaneAndLine(Axis.X, viewPosition, dragRayDirection);
Vector3? intersectionZY = GetIntersectionPlaneAndLine(Axis.Y, viewPosition, dragRayDirection);
targetPosition = GetMediaPoint(intersectionZX, intersectionZY).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
}
}
//Translate XYZ Plane
else
{
Vector2 dragScreenPosition = mousePosition - gizmoPlaneOffset;
Vector3 dragRayDirection = Camera.main.ScreenPointToRay(dragScreenPosition).direction;
switch (translateSelectState)
{
case TranslateSelectState.PlaneX:
targetPosition = GetIntersectionPlaneAndLine(Axis.X, viewPosition, dragRayDirection).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
case TranslateSelectState.PlaneY:
targetPosition = GetIntersectionPlaneAndLine(Axis.Y, viewPosition, dragRayDirection).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
case TranslateSelectState.PlaneZ:
targetPosition = GetIntersectionPlaneAndLine(Axis.Z, viewPosition, dragRayDirection).Value;
gizmo.GetComponent<Transform>().position = targetPosition;
break;
}
}
}
protected override void ChangeRenderOnSelect()
{
switch(translateSelectState)
{
case TranslateSelectState.X:
translateX.GetComponent<MeshRenderer>().material = yellowMaterial;
translateY.GetComponent<MeshRenderer>().material = whiteMaterial;
translateZ.GetComponent<MeshRenderer>().material = whiteMaterial;
translatePlaneX.SetActive(false);
translatePlaneY.SetActive(false);
translatePlaneZ.SetActive(false);
break;
case TranslateSelectState.Y:
translateX.GetComponent<MeshRenderer>().material = whiteMaterial;
translateY.GetComponent<MeshRenderer>().material = yellowMaterial;
translateZ.GetComponent<MeshRenderer>().material = whiteMaterial;
translatePlaneX.SetActive(false);
translatePlaneY.SetActive(false);
translatePlaneZ.SetActive(false);
break;
case TranslateSelectState.Z:
translateX.GetComponent<MeshRenderer>().material = whiteMaterial;
translateY.GetComponent<MeshRenderer>().material = whiteMaterial;
translateZ.GetComponent<MeshRenderer>().material = yellowMaterial;
translatePlaneX.SetActive(false);
translatePlaneY.SetActive(false);
translatePlaneZ.SetActive(false);
break;
case TranslateSelectState.PlaneX:
translateX.GetComponent<MeshRenderer>().material = whiteMaterial;
translateY.GetComponent<MeshRenderer>().material = yellowMaterial;
translateZ.GetComponent<MeshRenderer>().material = yellowMaterial;
translatePlaneX.GetComponent<MeshRenderer>().material = yellowMaterial;
translatePlaneY.SetActive(false);
translatePlaneZ.SetActive(false);
break;
case TranslateSelectState.PlaneY:
translateX.GetComponent<MeshRenderer>().material = yellowMaterial;
translateY.GetComponent<MeshRenderer>().material = whiteMaterial;
translateZ.GetComponent<MeshRenderer>().material = yellowMaterial;
translatePlaneX.SetActive(false);
translatePlaneY.GetComponent<MeshRenderer>().material = yellowMaterial;
translatePlaneZ.SetActive(false);
break;
case TranslateSelectState.PlaneZ:
translateX.GetComponent<MeshRenderer>().material = yellowMaterial;
translateY.GetComponent<MeshRenderer>().material = yellowMaterial;
translateZ.GetComponent<MeshRenderer>().material = whiteMaterial;
translatePlaneX.SetActive(false);
translatePlaneY.SetActive(false);
translatePlaneZ.GetComponent<MeshRenderer>().material = yellowMaterial;
break;
}
}
protected override void ChangeRenderOnUnSelect()
{
translateX.SetActive(true);
translateY.SetActive(true);
translateZ.SetActive(true);
translatePlaneX.SetActive(true);
translatePlaneY.SetActive(true);
translatePlaneZ.SetActive(true);
translateX.GetComponent<MeshRenderer>().material = redMaterial;
translateY.GetComponent<MeshRenderer>().material = greenMaterial;
translateZ.GetComponent<MeshRenderer>().material = blueMaterial;
translatePlaneX.GetComponent<MeshRenderer>().material = redMaterial;
translatePlaneY.GetComponent<MeshRenderer>().material = greenMaterial;
translatePlaneZ.GetComponent<MeshRenderer>().material = blueMaterial;
}
private Vector3? GetMediaPoint(Vector3? point1, Vector3? point2)
{
if (point1 != null && point2 != null)
{
return (point1 + point2) / 2;
}
else if (point1 != null && point2 == null)
{
return point1;
}
else if (point2 != null && point1 == null)
{
return point2;
}
return null;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bcaa98f6cda37fd4b9e03e8b053b58dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,327 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Security.Cryptography;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;
public class SelectDetector
{
//GameObject
public GameObject detectedObject;
private List<GameObject> objects;
private List<int> objectIds;
private Shader objectEncodeShader;
private Material objectEncodeMaterial;
private Dictionary<int, Material> objectEncodeMaterials;
//Gizmo
public GameObject detectedGizmo;
private List<GameObject> gizmos;
private List<int> gizmoIds;
private Shader gizmoEncodeShader;
private Material gizmoEncodeMaterial;
private Dictionary<int,Material> gizmoEncodeMaterials;
private CommandBuffer encodeCmdBuffer;
private Camera selectCamera;
private GameObject cameraObject;
private Texture2D encodeTexture2d;
private RenderTexture encodeTexture;
private bool isCursorOnPanels = false;
public void Initialize()
{
//Encode CommandBuffer Initialize
encodeCmdBuffer = new CommandBuffer();
//Object Encode Material Initialize
objectEncodeShader = Shader.Find("Custom/ObjectSelectEncode");
objectEncodeMaterial = new Material(objectEncodeShader);
objectEncodeMaterial.SetColor("_ID", IntToRGBA(-1));
//Gizmo Encode Material Initialize
gizmoEncodeShader = Shader.Find("Custom/GizmoSelectEncode");
gizmoEncodeMaterial = new Material(gizmoEncodeShader);
gizmoEncodeMaterial.SetColor("_ID", IntToRGBA(-1));
//Encode Texture Initialize
encodeTexture = new RenderTexture(Screen.width, Screen.height, 24);
encodeTexture2d = new Texture2D(1, 1, TextureFormat.ARGB32, false);
//Camera Initialize
cameraObject = new GameObject();
cameraObject.name = "SelectDetector";
cameraObject.GetComponent<Transform>().parent = GameObject.Find("Main Camera").GetComponent<Transform>();
cameraObject.GetComponent<Transform>().localPosition = Vector3.zero;
cameraObject.GetComponent<Transform>().rotation = Quaternion.identity;
selectCamera = cameraObject.AddComponent<Camera>();
selectCamera.targetTexture = encodeTexture;
selectCamera.GetComponent<Transform>().position = Camera.main.transform.position;
selectCamera.GetComponent<Transform>().rotation = Camera.main.transform.rotation;
//List Initialize
objects = new List<GameObject>();
objectIds = new List<int>();
objectEncodeMaterials = new Dictionary<int, Material>();
gizmos = new List<GameObject>();
gizmoIds = new List<int>();
gizmoEncodeMaterials = new Dictionary<int, Material>();
}
public void InitializeScene()
{
//Original GameObjects Initialize
foreach (GameObject root in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects())
{
foreach (Transform child_transform in root.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
objects.Add(child);
objectIds.Add(child.GetInstanceID());
}
}
}
public void Update()
{
if (isCursorOnPanels) { return; }
//Select Camera Update
//selectCamera.GetComponent<Transform>().position = Camera.main.transform.position;
//selectCamera.GetComponent<Transform>().rotation = Camera.main.transform.rotation;
selectCamera.RemoveAllCommandBuffers();
//Encode CommandBuffer Update
encodeCmdBuffer.Clear();
encodeCmdBuffer.ClearRenderTarget(true, true, Color.white);
//Add Object Render Command
for (int i = 0; i < objects.Count; i++)
{
GameObject tmpObject = objects[i];
if (tmpObject == null) { continue; }
if (tmpObject.activeSelf == false) { continue; }
MeshRenderer tmpRenderer = tmpObject.GetComponent<MeshRenderer>();
if (tmpRenderer != null)
{
int tmpId = tmpObject.GetInstanceID();
Material tempMaterial = objectEncodeMaterials[tmpId];
encodeCmdBuffer.DrawRenderer(tmpRenderer, tempMaterial);
}
}
//Add Gizmo Render Command
for (int i = 0; i < gizmos.Count; i++)
{
GameObject tmpGizmo = gizmos[i];
MeshRenderer tmpRenderer = tmpGizmo.GetComponent<MeshRenderer>();
if (tmpRenderer != null)
{
int tmpId = tmpGizmo.GetInstanceID();
Material tmpMaterial = gizmoEncodeMaterials[tmpId];
encodeCmdBuffer.DrawRenderer(tmpRenderer, tmpMaterial);
}
}
selectCamera.AddCommandBuffer(CameraEvent.AfterEverything, encodeCmdBuffer);
//Detected Object&Gizmo Update
Vector2 input = Input.mousePosition;
int inputX = (int)input.x;
int inputY = (int)input.y;
int clampInputX = Mathf.Clamp(inputX, 0, encodeTexture.width - 1);
int clampInputY = Mathf.Clamp(inputY, 0, encodeTexture.height - 1);
RenderTexture.active = encodeTexture;
encodeTexture2d.ReadPixels(new Rect(clampInputX, clampInputY, 1, 1), 0, 0);
encodeTexture2d.Apply();
Color color = encodeTexture2d.GetPixel(0, 0);
int id = RGBAToInt(color);
detectedObject = FindObjectByID(id);
detectedGizmo = FindGizmoByID(id);
}
//Object Add&Remove&Find
public void AddObjects(GameObject root_object)
{
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
AddObject(child);
}
}
public void RemoveObjects(GameObject root_object)
{
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
RemoveObject(child);
}
}
public void AddObjects(List<GameObject> objects)
{
foreach(GameObject obj in objects)
{
AddObject(obj);
}
}
public void RemoveObjects(List<GameObject> objects)
{
foreach(GameObject obj in objects)
{
RemoveObject(obj);
}
}
public void AddObject(GameObject p_object)
{
if(p_object == null) { return; }
objects.Add(p_object);
int id = p_object.GetInstanceID();
objectIds.Add(id);
//Encode Material
Material encodeMaterial = new Material(objectEncodeMaterial);
encodeMaterial.SetColor("_ID", IntToRGBA(id));
objectEncodeMaterials.Add(id, encodeMaterial);
}
public void RemoveObject(GameObject p_object)
{
if (p_object == null) { return; }
if (!objects.Contains(p_object)) { return; }
objects.Remove(p_object);
int id = p_object.GetInstanceID();
objectIds.Remove(id);
objectEncodeMaterials.Remove(id);
}
private GameObject FindObjectByID(int id)
{
for (int i = 0; i < objects.Count; i++)
{
if (objectIds[i] == id)
{
return objects[i];
}
}
return null;
}
//Gizmo Add&Remove&Find
public void AddGizmos(GameObject root_object)
{
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
AddGizmo(child);
}
}
public void RemoveGizmos(GameObject root_object)
{
foreach (Transform child_transform in root_object.GetComponentsInChildren<Transform>(true))
{
GameObject child = child_transform.gameObject;
RemoveGizmo(child);
}
}
public void AddGizmos(List<GameObject> objects)
{
foreach(GameObject gameObject in objects)
{
AddGizmo(gameObject);
}
}
public void RemoveGizmos(List<GameObject> objects)
{
foreach(GameObject gameObject in objects)
{
RemoveGizmo(gameObject);
}
}
public void AddGizmo(GameObject p_gizmo)
{
if (p_gizmo == null) { return; }
gizmos.Add(p_gizmo);
int id = p_gizmo.GetInstanceID();
gizmoIds.Add(id);
//Encode Material
Material encodeMaterial = new Material(gizmoEncodeMaterial);
encodeMaterial.SetColor("_ID", IntToRGBA(id));
gizmoEncodeMaterials.Add(id, encodeMaterial);
}
public void RemoveGizmo(GameObject p_gizmo)
{
if (p_gizmo == null) { return; }
if (!gizmos.Contains(p_gizmo)) { return; }
gizmos.Remove(p_gizmo);
int id = p_gizmo.GetInstanceID();
gizmoIds.Remove(id);
gizmoEncodeMaterials.Remove(id);
}
private GameObject FindGizmoByID(int id)
{
for (int i = 0; i < gizmos.Count; i++)
{
if (gizmoIds[i] == id)
{
return gizmos[i];
}
}
return null;
}
//Tool
private Color IntToRGBA(int value)
{
byte red = (byte)((value >> 24) & 0xFF);
byte green = (byte)((value >> 16) & 0xFF);
byte blue = (byte)((value >> 8) & 0xFF);
byte alpha = (byte)(value & 0xFF);
return new Color32(red, green, blue, alpha);
}
private int RGBAToInt(Color32 color)
{
int result = (color.r << 24) |
(color.g << 16) |
(color.b << 8) |
color.a;
return result;
}
private int RGBAToInt(Color color)
{
Color32 color32 = new Color32((byte)(color.r * 255),
(byte)(color.g * 255),
(byte)(color.b * 255),
(byte)(color.a * 255));
return RGBAToInt(color32);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be973e2bc332fca4a9cb18ab3197b72b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: