DefaultHandleManager.cs 9.4 KB

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