DefaultHandleManager.cs 11 KB

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