RotateHandle.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using BansheeEngine;
  2. namespace BansheeEditor
  3. {
  4. public sealed class RotateHandle : DefaultHandle
  5. {
  6. private Quaternion delta;
  7. private HandleSliderDisc xAxis;
  8. private HandleSliderDisc yAxis;
  9. private HandleSliderDisc zAxis;
  10. private HandleSliderDisc freeAxis;
  11. public Quaternion Delta
  12. {
  13. get { return delta; }
  14. }
  15. internal override bool IsDragged()
  16. {
  17. return xAxis.State == HandleSlider.StateType.Active ||
  18. yAxis.State == HandleSlider.StateType.Active ||
  19. zAxis.State == HandleSlider.StateType.Active ||
  20. freeAxis.State == HandleSlider.StateType.Active;
  21. }
  22. public RotateHandle()
  23. {
  24. xAxis = new HandleSliderDisc(this, Vector3.xAxis, 1.0f);
  25. yAxis = new HandleSliderDisc(this, Vector3.yAxis, 1.0f);
  26. zAxis = new HandleSliderDisc(this, Vector3.zAxis, 1.0f);
  27. freeAxis = new HandleSliderDisc(this, Vector3.zAxis, 1.0f);
  28. }
  29. protected override void PreInput()
  30. {
  31. xAxis.Position = position;
  32. yAxis.Position = position;
  33. zAxis.Position = position;
  34. freeAxis.Position = position;
  35. freeAxis.Rotation = EditorApplication.SceneViewCamera.sceneObject.Rotation;
  36. xAxis.SetCutoffPlane(GetXStartAngle(), true);
  37. yAxis.SetCutoffPlane(GetYStartAngle(), true);
  38. zAxis.SetCutoffPlane(GetZStartAngle(), true);
  39. freeAxis.SetCutoffPlane(0.0f, false);
  40. }
  41. protected override void PostInput()
  42. {
  43. delta = Quaternion.identity;
  44. Degree xValue = 0.0f;
  45. Degree yValue = 0.0f;
  46. Degree zValue = 0.0f;
  47. if (Handles.RotateHandleSnapActive)
  48. {
  49. xValue = Handles.SnapValue(xAxis.Delta, Handles.RotateSnapAmount);
  50. yValue = Handles.SnapValue(yAxis.Delta, Handles.RotateSnapAmount);
  51. zValue = Handles.SnapValue(zAxis.Delta, Handles.RotateSnapAmount);
  52. }
  53. else
  54. {
  55. xValue = xAxis.Delta;
  56. yValue = yAxis.Delta;
  57. zValue = zAxis.Delta;
  58. }
  59. delta = Quaternion.FromAxisAngle(GetXDir(), xValue) * delta;
  60. delta = Quaternion.FromAxisAngle(GetYDir(), yValue) * delta;
  61. delta = Quaternion.FromAxisAngle(GetZDir(), zValue) * delta;
  62. if (freeAxis.State == HandleSlider.StateType.Active)
  63. {
  64. Matrix4 cameraToWorld = EditorApplication.SceneViewCamera.ViewMatrixInverse;
  65. Vector3 rotDir = cameraToWorld.MultiplyAffine(new Vector3(-Input.PointerDelta.y, -Input.PointerDelta.x, 0));
  66. delta = Quaternion.FromAxisAngle(rotDir.Normalized, Input.PointerDelta.Magnitude)*delta;
  67. }
  68. }
  69. protected override void Draw()
  70. {
  71. HandleDrawing.SetTransform(Matrix4.TRS(Position, Quaternion.identity, Vector3.one));
  72. float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position);
  73. // Draw arcs
  74. if (xAxis.State == HandleSlider.StateType.Active)
  75. HandleDrawing.SetColor(Color.White);
  76. else if(xAxis.State == HandleSlider.StateType.Hover)
  77. HandleDrawing.SetColor(Color.BansheeOrange);
  78. else
  79. HandleDrawing.SetColor(Color.Red);
  80. HandleDrawing.DrawWireArc(Vector3.zero, GetXDir(), 1.0f, GetXStartAngle(), 180.0f, handleSize);
  81. if (yAxis.State == HandleSlider.StateType.Active)
  82. HandleDrawing.SetColor(Color.White);
  83. else if (yAxis.State == HandleSlider.StateType.Hover)
  84. HandleDrawing.SetColor(Color.BansheeOrange);
  85. else
  86. HandleDrawing.SetColor(Color.Green);
  87. HandleDrawing.DrawWireArc(Vector3.zero, GetYDir(), 1.0f, GetYStartAngle(), 180.0f, handleSize);
  88. if (zAxis.State == HandleSlider.StateType.Active)
  89. HandleDrawing.SetColor(Color.White);
  90. else if (zAxis.State == HandleSlider.StateType.Hover)
  91. HandleDrawing.SetColor(Color.BansheeOrange);
  92. else
  93. HandleDrawing.SetColor(Color.Blue);
  94. HandleDrawing.DrawWireArc(Vector3.zero, GetZDir(), 1.0f, GetZStartAngle(), 180.0f, handleSize);
  95. // Draw active rotation pie
  96. Color gray = new Color(1.0f, 1.0f, 1.0f, 0.3f);
  97. HandleDrawing.SetColor(gray);
  98. if (xAxis.State == HandleSlider.StateType.Active)
  99. HandleDrawing.DrawArc(Vector3.zero, GetXDir(), 1.0f, xAxis.StartAngle, xAxis.Delta, handleSize);
  100. else if (yAxis.State == HandleSlider.StateType.Active)
  101. HandleDrawing.DrawArc(Vector3.zero, GetYDir(), 1.0f, yAxis.StartAngle, yAxis.Delta, handleSize);
  102. else if (zAxis.State == HandleSlider.StateType.Active)
  103. HandleDrawing.DrawArc(Vector3.zero, GetZDir(), 1.0f, zAxis.StartAngle, zAxis.Delta, handleSize);
  104. // Draw free rotate handle
  105. if (freeAxis.State == HandleSlider.StateType.Active)
  106. HandleDrawing.SetColor(Color.White);
  107. else if (freeAxis.State == HandleSlider.StateType.Hover)
  108. HandleDrawing.SetColor(Color.BansheeOrange);
  109. else
  110. HandleDrawing.SetColor(Color.White);
  111. //// Rotate it so it always faces the camera, and move it forward a bit to always render in front
  112. Vector3 freeHandleNormal = EditorApplication.SceneViewCamera.sceneObject.Rotation.Rotate(GetZDir());
  113. Vector3 offset = freeHandleNormal*0.1f;
  114. HandleDrawing.DrawWireDisc(offset, freeHandleNormal, 1.0f, handleSize);
  115. }
  116. private Degree GetXStartAngle()
  117. {
  118. Vector3 xStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, GetXDir());
  119. return PointOnCircleToAngle(GetXDir(), xStartDir);
  120. }
  121. private Degree GetYStartAngle()
  122. {
  123. Vector3 yStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, GetYDir());
  124. return PointOnCircleToAngle(GetYDir(), yStartDir);
  125. }
  126. private Degree GetZStartAngle()
  127. {
  128. Vector3 zStartDir = Vector3.Cross(EditorApplication.SceneViewCamera.sceneObject.Forward, GetZDir());
  129. return PointOnCircleToAngle(GetZDir(), zStartDir);
  130. }
  131. private Vector3 GetXDir()
  132. {
  133. return Vector3.xAxis;
  134. }
  135. private Vector3 GetYDir()
  136. {
  137. return Vector3.yAxis;
  138. }
  139. private Vector3 GetZDir()
  140. {
  141. return Vector3.zAxis;
  142. }
  143. private Degree PointOnCircleToAngle(Vector3 up, Vector3 point)
  144. {
  145. Quaternion rot = Quaternion.FromToRotation(up, Vector3.yAxis);
  146. Matrix4 worldToPlane = Matrix4.TRS(Vector3.zero, rot, Vector3.one);
  147. point = worldToPlane.MultiplyAffine(point);
  148. return (MathEx.Atan2(-point.z, -point.x) + MathEx.Pi) * MathEx.Rad2Deg;
  149. }
  150. }
  151. }