337 lines
15 KiB
C#
337 lines
15 KiB
C#
|
|
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;
|
||
|
|
}
|
||
|
|
}
|