285 lines
12 KiB
C#
285 lines
12 KiB
C#
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"));
|
|
}
|
|
}
|