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("Materials/Red"); greenMaterial = Resources.Load("Materials/Green"); blueMaterial = Resources.Load("Materials/Blue"); //Prefab Initialize prefab = Resources.Load(prefabPath); if (prefab != null) { gizmo = Object.Instantiate(prefab) as GameObject; } HideBeindCamera(); //Component Initialize translateX = gizmo.GetComponent().Find("TranslateX").gameObject; translateY = gizmo.GetComponent().Find("TranslateY").gameObject; translateZ = gizmo.GetComponent().Find("TranslateZ").gameObject; translatePlaneX = gizmo.GetComponent().Find("TranslatePlaneX").gameObject; translatePlaneY = gizmo.GetComponent().Find("TranslatePlaneY").gameObject; translatePlaneZ = gizmo.GetComponent().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 { "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().localScale /= scaleRate; //Translate Plane Update Vector3 viewPosition = Camera.main.ScreenToWorldPoint(screenCenterPosition); Vector3 viewDirection = viewPosition - gizmo.GetComponent().position; Vector3 viewLocalDirection = gizmo.GetComponent().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().localPosition = Vector3.zero; translatePlaneX.GetComponent().localPosition += directionY * Vector3.up * translatePlaneOffset; translatePlaneX.GetComponent().localPosition += directionZ * Vector3.forward * translatePlaneOffset; translatePlaneY.GetComponent().localPosition = Vector3.zero; translatePlaneY.GetComponent().localPosition += directionX * Vector3.right * translatePlaneOffset; translatePlaneY.GetComponent().localPosition += directionZ * Vector3.forward * translatePlaneOffset; translatePlaneZ.GetComponent().localPosition = Vector3.zero; translatePlaneZ.GetComponent().localPosition += directionX * Vector3.right * translatePlaneOffset; translatePlaneZ.GetComponent().localPosition += directionY * Vector3.up * translatePlaneOffset; } protected override void FollowUpdate() { if (target == null) { return; } //Rotation Follow Vector3 targetPosition = target.GetComponent().position; if (targetPosition != lastTargetPosition) { gizmo.GetComponent().position = targetPosition; } else { target.GetComponent().position = gizmo.GetComponent().position; } lastTargetPosition = targetPosition; //Rotation Follow gizmo.GetComponent().rotation = target.GetComponent().rotation; } public override void EnableGizmo(GameObject target) { base.EnableGizmo(target); lastTargetPosition = target.GetComponent().position; } public override void OnSelect(string handleName) { if (!handleNames.Contains(handleName)) { return; } Vector3 gizmoPosition = gizmo.GetComponent().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().right; break; case "TranslateY": translateSelectState = TranslateSelectState.Y; gizmoEndPosition = gizmoPosition + 10 * gizmo.GetComponent().up; break; case "TranslateZ": translateSelectState = TranslateSelectState.Z; gizmoEndPosition = gizmoPosition + 10 * gizmo.GetComponent().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().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().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().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().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().position = targetPosition; break; case TranslateSelectState.PlaneY: targetPosition = GetIntersectionPlaneAndLine(Axis.Y, viewPosition, dragRayDirection).Value; gizmo.GetComponent().position = targetPosition; break; case TranslateSelectState.PlaneZ: targetPosition = GetIntersectionPlaneAndLine(Axis.Z, viewPosition, dragRayDirection).Value; gizmo.GetComponent().position = targetPosition; break; } } } protected override void ChangeRenderOnSelect() { switch(translateSelectState) { case TranslateSelectState.X: translateX.GetComponent().material = yellowMaterial; translateY.GetComponent().material = whiteMaterial; translateZ.GetComponent().material = whiteMaterial; translatePlaneX.SetActive(false); translatePlaneY.SetActive(false); translatePlaneZ.SetActive(false); break; case TranslateSelectState.Y: translateX.GetComponent().material = whiteMaterial; translateY.GetComponent().material = yellowMaterial; translateZ.GetComponent().material = whiteMaterial; translatePlaneX.SetActive(false); translatePlaneY.SetActive(false); translatePlaneZ.SetActive(false); break; case TranslateSelectState.Z: translateX.GetComponent().material = whiteMaterial; translateY.GetComponent().material = whiteMaterial; translateZ.GetComponent().material = yellowMaterial; translatePlaneX.SetActive(false); translatePlaneY.SetActive(false); translatePlaneZ.SetActive(false); break; case TranslateSelectState.PlaneX: translateX.GetComponent().material = whiteMaterial; translateY.GetComponent().material = yellowMaterial; translateZ.GetComponent().material = yellowMaterial; translatePlaneX.GetComponent().material = yellowMaterial; translatePlaneY.SetActive(false); translatePlaneZ.SetActive(false); break; case TranslateSelectState.PlaneY: translateX.GetComponent().material = yellowMaterial; translateY.GetComponent().material = whiteMaterial; translateZ.GetComponent().material = yellowMaterial; translatePlaneX.SetActive(false); translatePlaneY.GetComponent().material = yellowMaterial; translatePlaneZ.SetActive(false); break; case TranslateSelectState.PlaneZ: translateX.GetComponent().material = yellowMaterial; translateY.GetComponent().material = yellowMaterial; translateZ.GetComponent().material = whiteMaterial; translatePlaneX.SetActive(false); translatePlaneY.SetActive(false); translatePlaneZ.GetComponent().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().material = redMaterial; translateY.GetComponent().material = greenMaterial; translateZ.GetComponent().material = blueMaterial; translatePlaneX.GetComponent().material = redMaterial; translatePlaneY.GetComponent().material = greenMaterial; translatePlaneZ.GetComponent().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; } }