DefaultHandleManager.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. Quaternion rotation;
  84. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  85. rotation = Quaternion.Identity;
  86. else
  87. rotation = selectedSceneObjects[0].Rotation; // We don't average rotation in case of multi-selection
  88. Vector3 position;
  89. if (EditorApplication.ActivePivotMode == HandlePivotMode.Pivot)
  90. position = selectedSceneObjects[0].Position; // Just take pivot from the first one, no averaging
  91. else
  92. {
  93. List<SceneObject> flatenedHierarchy = new List<SceneObject>();
  94. foreach (var so in selectedSceneObjects)
  95. flatenedHierarchy.AddRange(EditorUtility.FlattenHierarchy(so));
  96. AABox selectionBounds = EditorUtility.CalculateBounds(flatenedHierarchy.ToArray());
  97. position = selectionBounds.Center;
  98. }
  99. activeHandle.Position = position;
  100. activeHandle.Rotation = rotation;
  101. activeHandle.PreInput();
  102. }
  103. }
  104. /// <inheritdoc/>
  105. protected internal override void PostInput()
  106. {
  107. if (activeHandle != null)
  108. {
  109. if (activeHandle.IsDragged())
  110. {
  111. if (!isDragged)
  112. {
  113. isDragged = true;
  114. SceneObject[] selectedSceneObjects = Selection.SceneObjects;
  115. activeSelection = new HandledObject[selectedSceneObjects.Length];
  116. for (int i = 0; i < selectedSceneObjects.Length; i++)
  117. activeSelection[i] = new HandledObject(selectedSceneObjects[i]);
  118. initialHandlePosition = activeHandle.Position;
  119. initialHandleRotation = activeHandle.Rotation;
  120. }
  121. }
  122. else
  123. {
  124. isDragged = false;
  125. activeSelection = null;
  126. }
  127. activeHandle.PostInput();
  128. if (activeHandle.IsDragged())
  129. {
  130. switch (activeHandleType)
  131. {
  132. case SceneViewTool.Move:
  133. MoveHandle moveHandle = (MoveHandle) activeHandle;
  134. foreach (var selectedObj in activeSelection)
  135. selectedObj.so.LocalPosition = selectedObj.initialPosition + moveHandle.Delta;
  136. break;
  137. case SceneViewTool.Rotate:
  138. {
  139. RotateHandle rotateHandle = (RotateHandle) activeHandle;
  140. // Make sure we transform relative to the handle position
  141. SceneObject temporarySO = new SceneObject("Temp");
  142. temporarySO.Position = initialHandlePosition;
  143. temporarySO.LocalRotation = initialHandleRotation;
  144. SceneObject[] originalParents = new SceneObject[activeSelection.Length];
  145. for (int i = 0; i < activeSelection.Length; i++)
  146. {
  147. originalParents[i] = activeSelection[i].so.Parent;
  148. activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition;
  149. activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation;
  150. activeSelection[i].so.Parent = temporarySO;
  151. }
  152. temporarySO.LocalRotation *= rotateHandle.Delta;
  153. for (int i = 0; i < activeSelection.Length; i++)
  154. activeSelection[i].so.Parent = originalParents[i];
  155. temporarySO.Destroy();
  156. }
  157. break;
  158. case SceneViewTool.Scale:
  159. {
  160. ScaleHandle scaleHandle = (ScaleHandle) activeHandle;
  161. // Make sure we transform relative to the handle position
  162. SceneObject temporarySO = new SceneObject("Temp");
  163. temporarySO.Position = activeHandle.Position;
  164. SceneObject[] originalParents = new SceneObject[activeSelection.Length];
  165. for (int i = 0; i < activeSelection.Length; i++)
  166. {
  167. originalParents[i] = activeSelection[i].so.Parent;
  168. activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition;
  169. activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation;
  170. activeSelection[i].so.LocalScale = activeSelection[i].initialScale;
  171. activeSelection[i].so.Parent = temporarySO;
  172. }
  173. temporarySO.LocalScale += scaleHandle.Delta;
  174. for (int i = 0; i < activeSelection.Length; i++)
  175. activeSelection[i].so.Parent = originalParents[i];
  176. temporarySO.Destroy();
  177. }
  178. break;
  179. }
  180. EditorApplication.SetSceneDirty();
  181. }
  182. }
  183. else
  184. {
  185. isDragged = false;
  186. activeSelection = null;
  187. }
  188. }
  189. /// <inheritdoc/>
  190. protected internal override void Draw()
  191. {
  192. if (activeHandle != null)
  193. activeHandle.Draw();
  194. }
  195. }
  196. /** @} */
  197. }