1using System.Collections;
21 private Transform _trs;
23 {
get {
if (_trs ==
null) _trs = gameObject.GetComponent<Transform>();
return _trs; } }
26 {
get {
if (_cam ==
null) _cam = Camera.main;
return _cam; } }
28 private const int MAX_DISTANCE_TO_HANDLE = 15;
30 private static Mesh _HandleLineMesh =
null, _HandleTriangleMesh =
null;
35 private Material HandleOpaqueMaterial
39 return pb_BuiltinResource.GetMaterial(pb_BuiltinResource.mat_HandleOpaque);
43 private Material RotateLineMaterial
47 return pb_BuiltinResource.GetMaterial(pb_BuiltinResource.mat_RotateHandle);
51 private Material HandleTransparentMaterial
55 return pb_BuiltinResource.GetMaterial(pb_BuiltinResource.mat_HandleTransparent);
59 private Mesh HandleLineMesh
63 if (_HandleLineMesh ==
null)
65 _HandleLineMesh =
new Mesh();
66 CreateHandleLineMesh(ref _HandleLineMesh,
Vector3.one);
68 return _HandleLineMesh;
72 private Mesh HandleTriangleMesh
76 if (_HandleTriangleMesh ==
null)
78 _HandleTriangleMesh =
new Mesh();
79 CreateHandleTriangleMesh(ref _HandleTriangleMesh,
Vector3.one);
81 return _HandleTriangleMesh;
87 private Mesh _coneRight, _coneUp, _coneForward;
89 private const float CAP_SIZE = .07f;
95 private Vector2 mouseOrigin = Vector2.zero;
97 private int draggingAxes = 0;
98 private Vector3 scale = Vector3.one;
108 #region Initialization
124 public void SetTRS(Vector3 position, Quaternion rotation, Vector3 scale)
126 trs.position = position;
127 trs.localRotation = rotation;
128 trs.localScale = scale;
130 RebuildGizmoMatrix();
133 #endregion Initialization
151 RebuildGizmoMesh(Vector3.one);
152 RebuildGizmoMatrix();
159 private class DragOrientation
161 public Vector3 origin;
163 public Vector3 mouse;
164 public Vector3 cross;
165 public Vector3 offset;
168 public DragOrientation()
170 origin = Vector3.zero;
172 mouse = Vector3.zero;
173 cross = Vector3.zero;
174 offset = Vector3.zero;
175 plane =
new Plane(Vector3.up, Vector3.zero);
179 private DragOrientation drag =
new DragOrientation();
181 private void Update()
183 if (
isHidden || EventSystem.current.IsPointerOverGameObject())
190 if (Input.GetMouseButtonDown(0) && !Input.GetKey(KeyCode.LeftAlt))
198 if (Input.GetKey(KeyCode.LeftAlt))
199 OnFinishHandleMovement();
203 Color col =
new Color(Mathf.Abs(drag.axis.x), Mathf.Abs(drag.axis.y), Mathf.Abs(drag.axis.z), 1f);
205 Debug.DrawRay(drag.origin, dir * 1f, col, lineTime,
false);
206 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (trs.up * .1f), col, lineTime,
false);
207 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (trs.forward * .1f), col, lineTime,
false);
208 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (trs.right * .1f), col, lineTime,
false);
209 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (-trs.up * .1f), col, lineTime,
false);
210 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (-trs.forward * .1f), col, lineTime,
false);
211 Debug.DrawLine(drag.origin + dir, (drag.origin + dir * .9f) + (-trs.right * .1f), col, lineTime,
false);
213 Debug.DrawLine(drag.origin, drag.origin + drag.mouse,
Color.red, lineTime,
false);
214 Debug.DrawLine(drag.origin, drag.origin + drag.cross,
Color.black, lineTime,
false);
225 if (draggingAxes < 2 && tool !=
Tool.Rotate)
228 valid = pb_HandleUtility.PointOnLine(
new Ray(trs.position, drag.axis), cam.ScreenPointToRay(Input.mousePosition), out a, out b);
232 Ray ray = cam.ScreenPointToRay(Input.mousePosition);
234 if (drag.plane.Raycast(ray, out hit))
236 a = ray.GetPoint(hit);
243 drag.origin = trs.position;
256 mouseOrigin = Input.mousePosition;
257 float sign = pb_HandleUtility.CalcMouseDeltaSignWithAxes(cam, drag.origin, drag.axis, drag.cross, delta);
258 axisAngle += delta.magnitude * sign;
267 if (draggingAxes > 1)
269 v = SetUniformMagnitude(((a - drag.offset) - trs.position));
278 RebuildGizmoMesh(scale);
286 RebuildGizmoMatrix();
291 if (Input.GetMouseButtonUp(0))
293 OnFinishHandleMovement();
297 private float axisAngle = 0f;
303 private Vector3 SetUniformMagnitude(Vector3 a)
305 float max = Mathf.Abs(a.x) > Mathf.Abs(a.y) && Mathf.Abs(a.x) > Mathf.Abs(a.z) ? a.x : Mathf.Abs(a.y) > Mathf.Abs(a.z) ? a.y : a.z;
314 private void OnMouseDown()
324 draggingHandle = CheckHandleActivated(Input.mousePosition, out plane);
326 mouseOrigin = Input.mousePosition;
334 Ray ray = cam.ScreenPointToRay(Input.mousePosition);
339 drag.axis = trs.right;
340 drag.plane.SetNormalAndPosition(trs.right.normalized, trs.position);
346 if (draggingAxes > 1)
347 drag.plane.SetNormalAndPosition(
Vector3.Cross(drag.axis, trs.up).normalized, trs.position);
349 drag.plane.SetNormalAndPosition(trs.up.normalized, trs.position);
356 if (draggingAxes > 1)
357 drag.plane.SetNormalAndPosition(
Vector3.Cross(drag.axis, trs.forward).normalized, trs.position);
359 drag.plane.SetNormalAndPosition(trs.forward.normalized, trs.position);
360 drag.axis += trs.forward;
363 if (draggingAxes < 2)
365 if (pb_HandleUtility.PointOnLine(
new Ray(trs.position, drag.axis), ray, out a, out b))
366 drag.offset = a - trs.position;
370 if (drag.plane.Raycast(ray, out hit))
372 drag.mouse = (ray.GetPoint(hit) - trs.position).normalized;
373 drag.cross =
Vector3.Cross(drag.axis, drag.mouse);
380 if (drag.plane.Raycast(ray, out hit))
382 drag.offset = ray.GetPoint(hit) - trs.position;
383 drag.mouse = (ray.GetPoint(hit) - trs.position).normalized;
384 drag.cross =
Vector3.Cross(drag.axis, drag.mouse);
393 private void OnFinishHandleMovement()
396 RebuildGizmoMatrix();
401 StartCoroutine(SetDraggingFalse());
404 private IEnumerator SetDraggingFalse()
406 yield
return new WaitForEndOfFrame();
414 private Vector2 screenToGUIPoint(Vector2 v)
416 v.y = Screen.height - v.y;
428 private bool CheckHandleActivated(Vector2 mousePosition, out
Axis plane)
432 if (tool ==
Tool.Position || tool ==
Tool.Scale)
437 Vector2 cen = cam.WorldToScreenPoint(trs.position);
440 Vector2 up = cam.WorldToScreenPoint((trs.position + (trs.up + trs.up * CAP_SIZE * 4f) * (sceneHandleSize *
HandleSize)));
443 Vector2 right = cam.WorldToScreenPoint((trs.position + (trs.right + trs.right * CAP_SIZE * 4f) * (sceneHandleSize *
HandleSize)));
446 Vector2 forward = cam.WorldToScreenPoint((trs.position + (trs.forward + trs.forward * CAP_SIZE * 4f) * (sceneHandleSize *
HandleSize)));
452 Vector2 p_right = (cen + ((right - cen) * cameraMask.x) * HANDLE_BOX_SIZE);
453 Vector2 p_up = (cen + ((up - cen) * cameraMask.y) * HANDLE_BOX_SIZE);
454 Vector2 p_forward = (cen + ((forward - cen) * cameraMask.z) * HANDLE_BOX_SIZE);
459 p_up, (p_up+p_forward) - cen,
460 (p_up+p_forward) - cen, p_forward,
465 else if (pb_HandleUtility.PointInPolygon(
new Vector2[] {
467 p_right, (p_right+p_forward)-cen,
468 (p_right+p_forward)-cen, p_forward,
473 else if (pb_HandleUtility.PointInPolygon(
new Vector2[] {
475 p_up, (p_up + p_right) - cen,
476 (p_up + p_right) - cen, p_right,
481 if (pb_HandleUtility.DistancePointLineSegment(mousePosition, cen, up) < MAX_DISTANCE_TO_HANDLE)
483 else if (pb_HandleUtility.DistancePointLineSegment(mousePosition, cen, right) < MAX_DISTANCE_TO_HANDLE)
485 else if (pb_HandleUtility.DistancePointLineSegment(mousePosition, cen, forward) < MAX_DISTANCE_TO_HANDLE)
494 Vector3[][] vertices = pb_HandleMesh.GetRotationVertices(16, 1f);
496 float best = Mathf.Infinity;
501 for (
int i = 0; i < 3; i++)
503 cur = cam.WorldToScreenPoint(vertices[i][0]);
505 for (
int n = 0; n < vertices[i].Length - 1; n++)
508 cur = cam.WorldToScreenPoint(handleMatrix.MultiplyPoint3x4(vertices[i][n + 1]));
510 float dist = pb_HandleUtility.DistancePointLineSegment(mousePosition, prev, cur);
512 if (dist < best && dist < MAX_DISTANCE_TO_HANDLE)
514 Vector3 viewDir = (handleMatrix.MultiplyPoint3x4((vertices[i][n] + vertices[i][n + 1]) * .5f) - cam.transform.position).normalized;
515 Vector3 nrm = transform.TransformDirection(vertices[i][n]).normalized;
517 if (
Vector3.Dot(nrm, viewDir) > .5f)
540 if (best < MAX_DISTANCE_TO_HANDLE + .1f)
553 private Matrix4x4 handleMatrix;
555 private void OnRenderObject()
557 if (isHidden || Camera.current != cam)
564 HandleOpaqueMaterial.SetPass(0);
565 Graphics.DrawMeshNow(HandleLineMesh, handleMatrix);
566 Graphics.DrawMeshNow(HandleTriangleMesh, handleMatrix, 1);
568 HandleTransparentMaterial.SetPass(0);
569 Graphics.DrawMeshNow(HandleTriangleMesh, handleMatrix, 0);
573 RotateLineMaterial.SetPass(0);
574 Graphics.DrawMeshNow(HandleLineMesh, handleMatrix);
579 private void RebuildGizmoMatrix()
581 float handleSize = pb_HandleUtility.GetHandleSize(trs.position);
582 Matrix4x4 scale = Matrix4x4.Scale(
Vector3.one * handleSize * HandleSize);
584 handleMatrix = transform.localToWorldMatrix * scale;
587 private void RebuildGizmoMesh(Vector3 scale)
589 if (_HandleLineMesh ==
null)
590 _HandleLineMesh =
new Mesh();
592 if (_HandleTriangleMesh ==
null)
593 _HandleTriangleMesh =
new Mesh();
595 CreateHandleLineMesh(ref _HandleLineMesh, scale);
596 CreateHandleTriangleMesh(ref _HandleTriangleMesh, scale);
601 #region Set Functionality
605 if (this.tool != tool)
608 RebuildGizmoMesh(Vector3.one);
610 if (onHandleTypeChanged !=
null)
611 onHandleTypeChanged();
622 draggingHandle =
false;
623 this.isHidden = isHidden;
625 if (onHandleTypeChanged !=
null)
626 onHandleTypeChanged();
631 return this.isHidden;
634 #endregion Set Functionality
636 #region Mesh Generation
638 private const float HANDLE_BOX_SIZE = .25f;
640 private void CreateHandleLineMesh(ref Mesh mesh, Vector3 scale)
646 pb_HandleMesh.CreatePositionLineMesh(ref mesh, trs, scale, cam, HANDLE_BOX_SIZE);
650 pb_HandleMesh.CreateRotateMesh(ref mesh, 48, 1f);
658 private void CreateHandleTriangleMesh(ref Mesh mesh, Vector3 scale)
660 if (tool ==
Tool.Position)
661 pb_HandleMesh.CreateTriangleMesh(ref mesh, trs, scale, cam, ConeMesh, HANDLE_BOX_SIZE, CAP_SIZE);
662 else if (tool ==
Tool.Scale)
663 pb_HandleMesh.CreateTriangleMesh(ref mesh, trs, scale, cam, CubeMesh, HANDLE_BOX_SIZE, CAP_SIZE);
666 #endregion Mesh Generation
static float GetHandleSize(Vector3 position)
static bool PointInPolygon(Vector2[] polygon, Vector2 point)
static Vector3 DirectionMask(Transform target, Vector3 rayDirection)
static void AddOnCameraMoveDelegate(OnCameraMoveEvent del)
Callback onHandleTypeChanged
OnHandleFinishEvent OnHandleFinish
OnHandleMoveEvent OnHandleMove
pb_Transform GetTransform()
delegate void OnHandleBeginEvent(pb_Transform transform)
static float rotationSnapValue
delegate void OnHandleMoveEvent(pb_Transform transform)
static float scaleSnapValue
void SetTRS(Vector3 position, Quaternion rotation, Vector3 scale)
delegate void OnHandleFinishEvent()
void SetIsHidden(bool isHidden)
static float positionSnapValue
OnHandleBeginEvent OnHandleBegin