DefaultHandleManager.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System.Collections.Generic;
  2. using BansheeEngine;
  3. namespace BansheeEditor
  4. {
  5. /// <summary>
  6. /// Manages the default set of built-in handles like move, rotate and scale. Handles switching between the three handle
  7. /// types, as well as switching between coordinate and pivot modes, while tracking and updating active scene object
  8. /// selection. Essentially it detects which handles need to be displayed and where, and then forwards the data
  9. /// to the specific handle for processing.
  10. /// </summary>
  11. internal sealed class DefaultHandleManager : Handle
  12. {
  13. /// <summary>
  14. /// Representation of a scene object currently being modified by a handle.
  15. /// </summary>
  16. private struct HandledObject
  17. {
  18. /// <summary>
  19. /// Creates a new scene object representation by recording the current object transform.
  20. /// </summary>
  21. /// <param name="so">Scene object that is being modified by a handle.</param>
  22. public HandledObject(SceneObject so)
  23. {
  24. this.so = so;
  25. initialPosition = so.LocalPosition;
  26. initialRotation = so.LocalRotation;
  27. initialScale = so.LocalScale;
  28. }
  29. public SceneObject so;
  30. public Vector3 initialPosition;
  31. public Quaternion initialRotation;
  32. public Vector3 initialScale;
  33. }
  34. private SceneViewTool activeHandleType = SceneViewTool.View;
  35. private DefaultHandle activeHandle;
  36. private HandledObject[] activeSelection;
  37. private bool isDragged;
  38. private Vector3 initialHandlePosition;
  39. private Quaternion initialHandleRotation;
  40. /// <inheritdoc/>
  41. protected internal override void PreInput()
  42. {
  43. SceneObject[] selectedSceneObjects = Selection.SceneObjects;
  44. if (selectedSceneObjects.Length == 0)
  45. {
  46. if (activeHandle != null)
  47. {
  48. activeHandle.Destroy();
  49. activeHandle = null;
  50. }
  51. }
  52. else
  53. {
  54. if (activeHandleType != EditorApplication.ActiveSceneTool || activeHandle == null)
  55. {
  56. if (activeHandle != null)
  57. {
  58. activeHandle.Destroy();
  59. activeHandle = null;
  60. }
  61. switch (EditorApplication.ActiveSceneTool)
  62. {
  63. case SceneViewTool.Move:
  64. activeHandle = new MoveHandle();
  65. break;
  66. case SceneViewTool.Rotate:
  67. activeHandle = new RotateHandle();
  68. break;
  69. case SceneViewTool.Scale:
  70. activeHandle = new ScaleHandle();
  71. break;
  72. }
  73. activeHandleType = EditorApplication.ActiveSceneTool;
  74. }
  75. }
  76. if (activeHandle != null)
  77. {
  78. Quaternion rotation;
  79. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  80. rotation = Quaternion.Identity;
  81. else
  82. rotation = selectedSceneObjects[0].Rotation; // We don't average rotation in case of multi-selection
  83. Vector3 position;
  84. if (EditorApplication.ActivePivotMode == HandlePivotMode.Pivot)
  85. position = selectedSceneObjects[0].Position; // Just take pivot from the first one, no averaging
  86. else
  87. {
  88. List<SceneObject> flatenedHierarchy = new List<SceneObject>();
  89. foreach (var so in selectedSceneObjects)
  90. flatenedHierarchy.AddRange(EditorUtility.FlattenHierarchy(so));
  91. AABox selectionBounds = EditorUtility.CalculateBounds(flatenedHierarchy.ToArray());
  92. position = selectionBounds.Center;
  93. }
  94. activeHandle.Position = position;
  95. activeHandle.Rotation = rotation;
  96. activeHandle.PreInput();
  97. }
  98. }
  99. /// <inheritdoc/>
  100. protected internal override void PostInput()
  101. {
  102. if (activeHandle != null)
  103. {
  104. if (activeHandle.IsDragged())
  105. {
  106. if (!isDragged)
  107. {
  108. isDragged = true;
  109. SceneObject[] selectedSceneObjects = Selection.SceneObjects;
  110. activeSelection = new HandledObject[selectedSceneObjects.Length];
  111. for (int i = 0; i < selectedSceneObjects.Length; i++)
  112. activeSelection[i] = new HandledObject(selectedSceneObjects[i]);
  113. initialHandlePosition = activeHandle.Position;
  114. initialHandleRotation = activeHandle.Rotation;
  115. }
  116. }
  117. else
  118. {
  119. isDragged = false;
  120. activeSelection = null;
  121. }
  122. activeHandle.PostInput();
  123. if (activeHandle.IsDragged())
  124. {
  125. switch (activeHandleType)
  126. {
  127. case SceneViewTool.Move:
  128. MoveHandle moveHandle = (MoveHandle) activeHandle;
  129. foreach (var selectedObj in activeSelection)
  130. selectedObj.so.LocalPosition = selectedObj.initialPosition + moveHandle.Delta;
  131. break;
  132. case SceneViewTool.Rotate:
  133. {
  134. RotateHandle rotateHandle = (RotateHandle) activeHandle;
  135. // Make sure we transform relative to the handle position
  136. SceneObject temporarySO = new SceneObject("Temp");
  137. temporarySO.Position = initialHandlePosition;
  138. temporarySO.LocalRotation = initialHandleRotation;
  139. SceneObject[] originalParents = new SceneObject[activeSelection.Length];
  140. for (int i = 0; i < activeSelection.Length; i++)
  141. {
  142. originalParents[i] = activeSelection[i].so.Parent;
  143. activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition;
  144. activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation;
  145. activeSelection[i].so.Parent = temporarySO;
  146. }
  147. temporarySO.LocalRotation *= rotateHandle.Delta;
  148. for (int i = 0; i < activeSelection.Length; i++)
  149. activeSelection[i].so.Parent = originalParents[i];
  150. temporarySO.Destroy();
  151. }
  152. break;
  153. case SceneViewTool.Scale:
  154. {
  155. ScaleHandle scaleHandle = (ScaleHandle) activeHandle;
  156. // Make sure we transform relative to the handle position
  157. SceneObject temporarySO = new SceneObject("Temp");
  158. temporarySO.Position = activeHandle.Position;
  159. SceneObject[] originalParents = new SceneObject[activeSelection.Length];
  160. for (int i = 0; i < activeSelection.Length; i++)
  161. {
  162. originalParents[i] = activeSelection[i].so.Parent;
  163. activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition;
  164. activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation;
  165. activeSelection[i].so.LocalScale = activeSelection[i].initialScale;
  166. activeSelection[i].so.Parent = temporarySO;
  167. }
  168. temporarySO.LocalScale += scaleHandle.Delta;
  169. for (int i = 0; i < activeSelection.Length; i++)
  170. activeSelection[i].so.Parent = originalParents[i];
  171. temporarySO.Destroy();
  172. }
  173. break;
  174. }
  175. EditorApplication.SetSceneDirty();
  176. }
  177. }
  178. else
  179. {
  180. isDragged = false;
  181. activeSelection = null;
  182. }
  183. }
  184. /// <inheritdoc/>
  185. protected internal override void Draw()
  186. {
  187. if (activeHandle != null)
  188. activeHandle.Draw();
  189. }
  190. }
  191. }