ObjectSelection.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System;
  5. using System.Linq;
  6. using System.Collections.Generic;
  7. namespace O3DWB
  8. {
  9. [Serializable]
  10. public class ObjectSelection : ScriptableObject
  11. {
  12. #region Private Variables
  13. [SerializeField]
  14. private SerializableGameObjectHashSet _selectedObjects = new SerializableGameObjectHashSet();
  15. [SerializeField]
  16. private InteractableMirror _mirror;
  17. [SerializeField]
  18. private ObjectSelectionSettings _settings;
  19. [SerializeField]
  20. private ObjectSelectionPrefabCreationSettings _prefabCreationSettings;
  21. [SerializeField]
  22. private ObjectOnSurfaceProjectSettings _objectOnSurfaceProjectSettings;
  23. [SerializeField]
  24. private ObjectSelectionRenderSettings _renderSettings;
  25. [SerializeField]
  26. private ObjectGrabSettings _selectionGrabSettings;
  27. [SerializeField]
  28. private ObjectSelectionExtrudeGizmo _duplicateGizmo;
  29. [SerializeField]
  30. private ObjectSelectionShape _selectionShape = new ObjectSelectionShape();
  31. [SerializeField]
  32. private ObjectSelectionGizmos _objectSelectionGizmos;
  33. [SerializeField]
  34. private GameObject _firstSelectedGameObject;
  35. [SerializeField]
  36. private GameObject _lastSelectedGameObject;
  37. private ObjectVertexSnapSession _objectVertexSnapSession = new ObjectVertexSnapSession();
  38. private ObjectVertexSnapSessionRenderer _objectVertexSnapSessionRenderer = new ObjectVertexSnapSessionRenderer();
  39. [SerializeField]
  40. private ObjectVertexSnapSessionRenderSettings _objectVertexSnapSessionRenderSettings;
  41. private ObjectSelectionSnapSession _selectionGridSnapSession = new ObjectSelectionSnapSession();
  42. private ObjectSelectionObject2ObjectSnapSession _object2ObjectSnapSession = new ObjectSelectionObject2ObjectSnapSession();
  43. private ObjectGrabSession _selectionGrabSession = new ObjectGrabSession();
  44. [SerializeField]
  45. private bool _wasInitialized = false;
  46. #endregion
  47. #region Private Properties
  48. private ObjectSelectionExtrudeGizmo DuplicateGizmo
  49. {
  50. get
  51. {
  52. if (_duplicateGizmo == null) _duplicateGizmo = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectSelectionExtrudeGizmo>();
  53. return _duplicateGizmo;
  54. }
  55. }
  56. private ObjectSelectionShape SelectionShape { get { return _selectionShape; } }
  57. #endregion
  58. #region Public Properties
  59. public ObjectVertexSnapSessionRenderSettings ObjectVertexSnapSessionRenderSettings
  60. {
  61. get
  62. {
  63. if (_objectVertexSnapSessionRenderSettings == null) _objectVertexSnapSessionRenderSettings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectVertexSnapSessionRenderSettings>();
  64. return _objectVertexSnapSessionRenderSettings;
  65. }
  66. }
  67. public InteractableMirror Mirror
  68. {
  69. get
  70. {
  71. if (_mirror == null) _mirror = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<InteractableMirror>();
  72. return _mirror;
  73. }
  74. }
  75. public InteractableMirrorView MirrorView { get { return Mirror.View; } }
  76. public InteractableMirrorSettings MirrorSettings { get { return Mirror.Settings; } }
  77. public InteractableMirrorRenderSettings MirrorRenderSettings { get { return Mirror.RenderSettings; } }
  78. public ObjectOnSurfaceProjectSettings ObjectOnSurfaceProjectSettings
  79. {
  80. get
  81. {
  82. if (_objectOnSurfaceProjectSettings == null) _objectOnSurfaceProjectSettings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectOnSurfaceProjectSettings>();
  83. return _objectOnSurfaceProjectSettings;
  84. }
  85. }
  86. public ObjectSelectionGizmos ObjectSelectionGizmos
  87. {
  88. get
  89. {
  90. if (_objectSelectionGizmos == null) _objectSelectionGizmos = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectSelectionGizmos>();
  91. return _objectSelectionGizmos;
  92. }
  93. }
  94. public int NumberOfSelectedObjects { get { return _selectedObjects.Count; } }
  95. public ObjectSelectionSettings Settings
  96. {
  97. get
  98. {
  99. if (_settings == null) _settings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectSelectionSettings>();
  100. return _settings;
  101. }
  102. }
  103. public ObjectSelectionPrefabCreationSettings PrefabCreationSettings
  104. {
  105. get
  106. {
  107. if (_prefabCreationSettings == null) _prefabCreationSettings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectSelectionPrefabCreationSettings>();
  108. return _prefabCreationSettings;
  109. }
  110. }
  111. public ObjectSelectionRenderSettings RenderSettings
  112. {
  113. get
  114. {
  115. if (_renderSettings == null) _renderSettings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectSelectionRenderSettings>();
  116. return _renderSettings;
  117. }
  118. }
  119. public ObjectGrabSettings SelectionGrabSettings
  120. {
  121. get
  122. {
  123. if (_selectionGrabSettings == null) _selectionGrabSettings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectGrabSettings>();
  124. return _selectionGrabSettings;
  125. }
  126. }
  127. public RectangleShapeRenderSettings RectangleSelectionShapeRenderSettings { get { return SelectionShape.RectangleShapeRenderSettings; } }
  128. public EllipseShapeRenderSettings EllipseSelectionShapeRenderSettings { get { return SelectionShape.EllipseShapeRenderSettings; } }
  129. #endregion
  130. #region Public Static Functions
  131. public static ObjectSelection Get()
  132. {
  133. if (Octave3DWorldBuilder.ActiveInstance == null) return null;
  134. return Octave3DWorldBuilder.ActiveInstance.ObjectSelection;
  135. }
  136. #endregion
  137. #region Public Methods
  138. public void RenderGizmos()
  139. {
  140. if (_objectVertexSnapSession.IsActive) _objectVertexSnapSessionRenderer.RenderGizmos(_objectVertexSnapSession, ObjectVertexSnapSessionRenderSettings);
  141. SelectionShape.RenderGizmos();
  142. _selectionGridSnapSession.RenderGizmos();
  143. _selectionGrabSession.RenderGizmos();
  144. IObjectSelectionRenderer objectSelectionRenderer = ObjectSelectionRendererFactory.Create();
  145. objectSelectionRenderer.Render(GetAllSelectedGameObjects());
  146. if (Mirror.IsActive)
  147. {
  148. Mirror.RenderGizmos();
  149. List<GameObject> topLevelParentsInSelection = GameObjectExtensions.GetParents(_selectedObjects.HashSet);
  150. Mirror.RenderMirroredEntityOrientedBoxes(GameObjectExtensions.GetHierarchyWorldOrientedBoxes(topLevelParentsInSelection));
  151. }
  152. }
  153. public void RenderHandles()
  154. {
  155. if(_selectionGrabSession.IsActive)
  156. {
  157. var labelStyle = new GUIStyle();
  158. labelStyle.normal.textColor = Color.white;
  159. Handles.BeginGUI();
  160. Rect labelRect = new Rect(2.0f, 0.0f, 1000, 20.0f);
  161. GUI.Label(labelRect, "[Selection Grab]");
  162. Handles.EndGUI();
  163. }
  164. else if(_object2ObjectSnapSession.IsActive)
  165. {
  166. var labelStyle = new GUIStyle();
  167. labelStyle.normal.textColor = Color.white;
  168. Rect labelRect = new Rect(2.0f, 0.0f, 1000, 20.0f);
  169. Handles.BeginGUI();
  170. GUI.Label(labelRect, "[Object2Object Snap]");
  171. Handles.EndGUI();
  172. }
  173. if (!_selectionGridSnapSession.IsActive && !_selectionGrabSession.IsActive && !_object2ObjectSnapSession.IsActive && !_objectVertexSnapSession.IsActive)
  174. {
  175. ObjectSelectionGizmos.RenderHandles(_selectedObjects.HashSet);
  176. }
  177. }
  178. public GameObject GetFirstSelectedGameObject()
  179. {
  180. if(_firstSelectedGameObject == null)
  181. {
  182. var selectedObjectsList = new List<GameObject>(_selectedObjects.HashSet);
  183. if (selectedObjectsList.Count != 0) _firstSelectedGameObject = selectedObjectsList[0];
  184. }
  185. return _firstSelectedGameObject;
  186. }
  187. public GameObject GetLastSelectedGameObject()
  188. {
  189. if (_lastSelectedGameObject == null)
  190. {
  191. var selectedObjectsList = new List<GameObject>(_selectedObjects.HashSet);
  192. if (selectedObjectsList.Count != 0) _lastSelectedGameObject = selectedObjectsList[selectedObjectsList.Count - 1];
  193. }
  194. return _lastSelectedGameObject;
  195. }
  196. public Vector3 GetWorldCenter()
  197. {
  198. if (NumberOfSelectedObjects == 0) return Vector3.zero;
  199. else
  200. {
  201. Vector3 objectCenterSum = Vector3.zero;
  202. foreach (GameObject selectedObject in _selectedObjects.HashSet)
  203. {
  204. OrientedBox worldOrientedBox = selectedObject.GetWorldOrientedBox();
  205. if (worldOrientedBox.IsValid()) objectCenterSum += worldOrientedBox.Center;
  206. else objectCenterSum += selectedObject.transform.position;
  207. }
  208. return objectCenterSum / NumberOfSelectedObjects;
  209. }
  210. }
  211. public Box GetWorldBox()
  212. {
  213. if (NumberOfSelectedObjects == 0) return Box.GetInvalid();
  214. else
  215. {
  216. Box selectionWorldBox = Box.GetInvalid();
  217. foreach (GameObject selectedObject in _selectedObjects.HashSet)
  218. {
  219. Box objectWorldBox = selectedObject.GetWorldBox();
  220. if (!objectWorldBox.IsValid()) continue;
  221. if (selectionWorldBox.IsValid()) selectionWorldBox.Encapsulate(objectWorldBox);
  222. else selectionWorldBox = objectWorldBox;
  223. }
  224. return selectionWorldBox;
  225. }
  226. }
  227. public void Clear()
  228. {
  229. _selectedObjects.Clear();
  230. _firstSelectedGameObject = null;
  231. _lastSelectedGameObject = null;
  232. SceneView.RepaintAll();
  233. }
  234. public void AddGameObjectToSelection(GameObject gameObject)
  235. {
  236. if(CanGameObjectBeSelected(gameObject))
  237. {
  238. _selectedObjects.Add(gameObject.gameObject);
  239. _lastSelectedGameObject = gameObject.gameObject;
  240. if (NumberOfSelectedObjects == 1) _firstSelectedGameObject = _lastSelectedGameObject;
  241. }
  242. }
  243. public void AddGameObjectCollectionToSelection(IEnumerable<GameObject> gameObjects)
  244. {
  245. foreach (GameObject gameObject in gameObjects)
  246. {
  247. AddGameObjectToSelection(gameObject);
  248. }
  249. }
  250. public void AddEntireGameObjectHierarchyToSelection(GameObject gameObjectInHierarchy)
  251. {
  252. if (!CanGameObjectBeSelected(gameObjectInHierarchy)) return;
  253. GameObject root = Octave3DWorldBuilder.ActiveInstance.GetRoot(gameObjectInHierarchy);
  254. List<GameObject> allChildrenIncludingSelf = root.GetAllChildrenIncludingSelf();
  255. AddGameObjectCollectionToSelection(allChildrenIncludingSelf);
  256. }
  257. public void AddEntireGameObjectHierarchyToSelection(IEnumerable<GameObject> gameObjectsInDifferentHierarchies)
  258. {
  259. foreach (GameObject gameObject in gameObjectsInDifferentHierarchies)
  260. {
  261. AddEntireGameObjectHierarchyToSelection(gameObject);
  262. }
  263. }
  264. public void RemoveGameObjectFromSelection(GameObject gameObject)
  265. {
  266. _selectedObjects.Remove(gameObject);
  267. _firstSelectedGameObject = null;
  268. _lastSelectedGameObject = null;
  269. }
  270. public void RemoveGameObjectCollectionFromSelection(IEnumerable<GameObject> gameObjects)
  271. {
  272. foreach (GameObject gameObject in gameObjects)
  273. {
  274. RemoveGameObjectFromSelection(gameObject);
  275. }
  276. }
  277. public void RemoveEntireGameObjectHierarchyFromSelection(GameObject gameObject)
  278. {
  279. GameObject root = Octave3DWorldBuilder.ActiveInstance.GetRoot(gameObject);
  280. List<GameObject> allChildrenIncludingSelf = root.GetAllChildrenIncludingSelf();
  281. RemoveGameObjectCollectionFromSelection(allChildrenIncludingSelf);
  282. }
  283. public void RemoveEntireGameObjectHierarchyFromSelection(IEnumerable<GameObject> gameObjectsInDifferentHierarchies)
  284. {
  285. foreach (GameObject gameObject in gameObjectsInDifferentHierarchies)
  286. {
  287. RemoveEntireGameObjectHierarchyFromSelection(gameObject);
  288. }
  289. }
  290. public bool IsGameObjectSelected(GameObject gameObject)
  291. {
  292. return _selectedObjects.Contains(gameObject);
  293. }
  294. public bool IsSameAs(GameObject gameObject)
  295. {
  296. return NumberOfSelectedObjects == 1 && IsGameObjectSelected(gameObject);
  297. }
  298. public bool IsSameAs(List<GameObject> gameObjects)
  299. {
  300. if(gameObjects.Count != NumberOfSelectedObjects) return false;
  301. foreach (GameObject gameObject in gameObjects)
  302. {
  303. if (!_selectedObjects.Contains(gameObject)) return false;
  304. }
  305. return true;
  306. }
  307. public void RemoveNullObjects()
  308. {
  309. _selectedObjects.RemoveWhere(item => item == null);
  310. }
  311. public void HandleRepaintEvent(Event e)
  312. {
  313. RemoveNullObjects();
  314. if (!AllShortcutCombos.Instance.ActivateObjectVertexSnapSession_Selection.IsActive()) _objectVertexSnapSession.End();
  315. if (Mirror.IsInteractionSessionActive)
  316. {
  317. Mirror.HandleRepaintEvent(e);
  318. return;
  319. }
  320. if (_selectionGridSnapSession.IsActive && !AllShortcutCombos.Instance.SelectionGridSnap.IsActive()) _selectionGridSnapSession.End();
  321. }
  322. public void HandleMouseMoveEvent(Event e)
  323. {
  324. if (Mirror.IsInteractionSessionActive)
  325. {
  326. e.DisableInSceneView();
  327. Mirror.HandleMouseMoveEvent(e);
  328. return;
  329. }
  330. if (_objectVertexSnapSession.IsActive)
  331. {
  332. e.DisableInSceneView();
  333. _objectVertexSnapSession.UpdateForMouseMovement();
  334. return;
  335. }
  336. SelectionShape.HandleMouseMoveEvent(e);
  337. _selectionGridSnapSession.UpdateForMouseMovement();
  338. if (_selectionGrabSession.IsActive)
  339. {
  340. _selectionGrabSession.Update();
  341. ObjectSelectionGizmos.OnObjectSelectionUpdated();
  342. }
  343. if(_object2ObjectSnapSession.IsActive)
  344. {
  345. _object2ObjectSnapSession.UpdateOnMouseMove();
  346. ObjectSelectionGizmos.OnObjectSelectionUpdated();
  347. }
  348. }
  349. public void HandleMouseDragEvent(Event e)
  350. {
  351. if(_selectionGridSnapSession.IsActive)
  352. {
  353. _selectionGridSnapSession.UpdateForMouseMovement();
  354. }
  355. else
  356. if(_selectionGrabSession.IsActive)
  357. {
  358. _selectionGrabSession.Update();
  359. ObjectSelectionGizmos.OnObjectSelectionUpdated();
  360. }
  361. else
  362. if (_objectVertexSnapSession.IsActive)
  363. {
  364. e.DisableInSceneView();
  365. _objectVertexSnapSession.UpdateForMouseMovement();
  366. ObjectSelectionGizmos.OnObjectSelectionUpdated();
  367. return;
  368. }
  369. else
  370. {
  371. SelectionShape.HandleMouseDragEvent(e);
  372. var mouseDragSelectionUpdateOperation = ObjectSelectionUpdateOperationFactory.Create(ObjectSelectionUpdateOperationType.MouseDrag);
  373. mouseDragSelectionUpdateOperation.Perform();
  374. }
  375. SceneView.RepaintAll();
  376. }
  377. public void HandleMouseButtonDownEvent(Event e)
  378. {
  379. if (_object2ObjectSnapSession.IsActive && AllShortcutCombos.Instance.EndSelectionObject2ObjectSnap.IsActive())
  380. {
  381. e.DisableInSceneView();
  382. _object2ObjectSnapSession.End();
  383. return;
  384. }
  385. if (_selectionGridSnapSession.IsActive || _selectionGrabSession.IsActive || _object2ObjectSnapSession.IsActive || _objectVertexSnapSession.IsActive) return;
  386. if (AllShortcutCombos.Instance.SnapXZGridToCursorPickPointOnLeftClick_Selection.IsActive() && e.InvolvesLeftMouseButton())
  387. {
  388. e.DisableInSceneView();
  389. ObjectSnapping.Get().SnapXZGridToCursorPickPoint(e.clickCount == 2);
  390. return;
  391. }
  392. if (Mirror.IsInteractionSessionActive && e.InvolvesLeftMouseButton())
  393. {
  394. e.DisableInSceneView();
  395. Mirror.EndInteractionSession();
  396. return;
  397. }
  398. if(e.InvolvesLeftMouseButton() && NumberOfSelectedObjects != 0 &&
  399. !SelectionShape.IsVisible() && AllShortcutCombos.Instance.ReplacePrefabsForSelectedObjects_Scene.IsActive() &&
  400. !Mirror.IsInteractionSessionActive)
  401. {
  402. e.DisableInSceneView();
  403. UndoEx.RecordForToolAction(this);
  404. List<GameObject> newObjects = ObjectSelectionActions.ReplaceSelectedObjectsPrefabOnMouseClick();
  405. if (newObjects.Count != 0) AddGameObjectCollectionToSelection(newObjects);
  406. return;
  407. }
  408. SelectionShape.HandleMouseButtonDownEvent(e);
  409. if (CanPerformClickSelectionUpdateOperation())
  410. {
  411. var clickSelectionUpdateOperation = ObjectSelectionUpdateOperationFactory.Create(ObjectSelectionUpdateOperationType.Click);
  412. clickSelectionUpdateOperation.Perform();
  413. SceneView.RepaintAll();
  414. }
  415. }
  416. public void ReplaceSelectedObjectsWithPrefab(Prefab prefab)
  417. {
  418. if (prefab == null || prefab.UnityPrefab == null || NumberOfSelectedObjects == 0) return;
  419. UndoEx.RecordForToolAction(this);
  420. ObjectSelectionActions.ReplaceSelectedObjectsWithPrefab(prefab.UnityPrefab);
  421. }
  422. public void HandleMouseButtonUpEvent(Event e)
  423. {
  424. SelectionShape.HandleMouseButtonUpEvent(e);
  425. }
  426. public void HandleExecuteCommandEvent(Event e)
  427. {
  428. if(e.IsDuplicateSelectionCommand())
  429. {
  430. e.DisableInSceneView();
  431. UndoEx.RecordForToolAction(this);
  432. ObjectSelectionActions.DuplicateSelection();
  433. }
  434. }
  435. public void HandleKeyboardButtonDownEvent(Event e)
  436. {
  437. if (AllShortcutCombos.Instance.ActivateObjectVertexSnapSession_Placement.IsActive() &&
  438. !_object2ObjectSnapSession.IsActive && !_selectionGrabSession.IsActive && !SelectionShape.IsVisible())
  439. {
  440. e.DisableInSceneView();
  441. _objectVertexSnapSession.Begin(GetAllSelectedGameObjects());
  442. return;
  443. }
  444. if(!_object2ObjectSnapSession.IsActive)
  445. {
  446. if (AllShortcutCombos.Instance.GrabSelection.IsActive() && NumberOfSelectedObjects != 0)
  447. {
  448. if (_selectionGrabSession.IsActive) _selectionGrabSession.End();
  449. else
  450. {
  451. _selectionGrabSession.Settings = SelectionGrabSettings;
  452. _selectionGrabSession.Begin(new List<GameObject>(_selectedObjects.HashSet));
  453. }
  454. }
  455. }
  456. if(!_selectionGrabSession.IsActive)
  457. {
  458. if (AllShortcutCombos.Instance.ToggleSelectionObject2ObjectSnap.IsActive() && NumberOfSelectedObjects != 0)
  459. {
  460. if (_object2ObjectSnapSession.IsActive) _object2ObjectSnapSession.End();
  461. else _object2ObjectSnapSession.Begin();
  462. }
  463. }
  464. if(_object2ObjectSnapSession.IsActive)
  465. {
  466. if (AllShortcutCombos.Instance.SelectionRotateWorldX.IsActive()) Rotate(Settings.XRotationStep, Vector3.right);
  467. else if (AllShortcutCombos.Instance.SelectionRotateWorldY.IsActive()) Rotate(Settings.YRotationStep, Vector3.up);
  468. else if (AllShortcutCombos.Instance.SelectionRotateWorldZ.IsActive()) Rotate(Settings.ZRotationStep, Vector3.forward);
  469. else if (AllShortcutCombos.Instance.SetRotationToIdentity.IsActive()) SetWorldRotation(Quaternion.identity);
  470. return;
  471. }
  472. if (_selectionGrabSession.IsActive || _selectionGridSnapSession.IsActive || _object2ObjectSnapSession.IsActive) return;
  473. // Note: Don't disable this event if it's CTRL or CMD because transform
  474. // handle snapping will no longer work.
  475. if (e.keyCode != KeyCode.LeftControl && e.keyCode != KeyCode.LeftCommand &&
  476. e.keyCode != KeyCode.RightControl && e.keyCode != KeyCode.RightCommand) e.DisableInSceneView();
  477. if (Mirror.IsInteractionSessionActive)
  478. {
  479. Mirror.HandleKeyboardButtonDownEvent(e);
  480. return;
  481. }
  482. if(Mirror.IsActive && AllShortcutCombos.Instance.MirrorSelectedObjects.IsActive())
  483. {
  484. List<GameObject> selectedRoots = Octave3DWorldBuilder.ActiveInstance.GetRoots(GetAllSelectedGameObjects());
  485. ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(Mirror.MirrorGameObjectHierarchies(selectedRoots), ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.Selection);
  486. return;
  487. }
  488. if (AllShortcutCombos.Instance.DeleteSelectedObjects.IsActive())
  489. {
  490. UndoEx.RecordForToolAction(this);
  491. ObjectErase.EraseObjectHierarchiesInObjectCollection(ObjectSelection.Get().GetAllSelectedGameObjects());
  492. }
  493. else
  494. if (AllShortcutCombos.Instance.SelectAllObjectsWithSamePrefabAsCurrentSelection.IsActive())
  495. {
  496. UndoEx.RecordForToolAction(this);
  497. ObjectSelectionActions.SelectAllObjectsWithSamePrefabAsCurrentSelection();
  498. _objectSelectionGizmos.OnObjectSelectionUpdated();
  499. }
  500. else
  501. if (AllShortcutCombos.Instance.ActivateMoveGizmo.IsActive())
  502. {
  503. UndoEx.RecordForToolAction(_objectSelectionGizmos);
  504. _objectSelectionGizmos.ActiveGizmoType = GizmoType.Move;
  505. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  506. }
  507. else
  508. if (AllShortcutCombos.Instance.ActivateRotationGizmo.IsActive())
  509. {
  510. UndoEx.RecordForToolAction(_objectSelectionGizmos);
  511. _objectSelectionGizmos.ActiveGizmoType = GizmoType.Rotate;
  512. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  513. }
  514. else
  515. if (AllShortcutCombos.Instance.ActivateScaleGizmo.IsActive())
  516. {
  517. UndoEx.RecordForToolAction(_objectSelectionGizmos);
  518. _objectSelectionGizmos.ActiveGizmoType = GizmoType.Scale;
  519. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  520. }
  521. else
  522. if(AllShortcutCombos.Instance.ActivateObjectSelectionExtrudeGizmo.IsActive())
  523. {
  524. UndoEx.RecordForToolAction(_objectSelectionGizmos);
  525. _objectSelectionGizmos.ActiveGizmoType = GizmoType.Duplicate;
  526. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  527. }
  528. else
  529. if (AllShortcutCombos.Instance.ProjectSelectedObjects.IsActive()) ProjectSelectionOnProjectionSurface();
  530. else if (AllShortcutCombos.Instance.SelectionGridSnap.IsActive()) _selectionGridSnapSession.Begin();
  531. else if (AllShortcutCombos.Instance.SetRotationToIdentity.IsActive()) SetWorldRotation(Quaternion.identity);
  532. else if (AllShortcutCombos.Instance.SelectionRotateWorldX.IsActive()) Rotate(Settings.XRotationStep, Vector3.right);
  533. else if (AllShortcutCombos.Instance.SelectionRotateWorldY.IsActive()) Rotate(Settings.YRotationStep, Vector3.up);
  534. else if (AllShortcutCombos.Instance.SelectionRotateWorldZ.IsActive()) Rotate(Settings.ZRotationStep, Vector3.forward);
  535. }
  536. public void HandleKeyboardButtonUpEvent(Event e)
  537. {
  538. if (!AllShortcutCombos.Instance.ActivateObjectVertexSnapSession_Selection.IsActive()) _objectVertexSnapSession.End();
  539. }
  540. private void SetWorldRotation(Quaternion rotation)
  541. {
  542. var selectedParents = GameObjectExtensions.GetParents(_selectedObjects.HashSet);
  543. GameObjectExtensions.RecordObjectTransformsForUndo(selectedParents);
  544. foreach (var parent in selectedParents) parent.transform.rotation = rotation;
  545. }
  546. private void Rotate(float angle, Vector3 axis)
  547. {
  548. var selectedParents = GameObjectExtensions.GetParents(_selectedObjects.HashSet);
  549. GameObjectExtensions.RecordObjectTransformsForUndo(selectedParents);
  550. if (Settings.RotateAroundSelectionCenter)
  551. {
  552. Vector3 selectionCenter = GetWorldCenter();
  553. foreach (var parent in selectedParents)
  554. {
  555. parent.RotateHierarchyBoxAroundPoint(angle, axis, selectionCenter);
  556. }
  557. }
  558. else
  559. {
  560. foreach (var parent in selectedParents)
  561. {
  562. Box worldAABB = parent.GetHierarchyWorldBox();
  563. if (worldAABB.IsValid()) parent.RotateHierarchyBoxAroundPoint(angle, axis, worldAABB.Center);
  564. }
  565. }
  566. }
  567. public void HandleMouseScrollWheelEvent(Event e)
  568. {
  569. if (CanAdjustSelectionShapeSizeForMouseScrollWheel())
  570. {
  571. e.DisableInSceneView();
  572. AdjustSelectionShapeSizeForMouseWheelScroll(e);
  573. }
  574. }
  575. public List<GameObject> GetAllSelectedGameObjects()
  576. {
  577. return new List<GameObject>(_selectedObjects.HashSet);
  578. }
  579. public List<GameObject> GetAllGameObjectsOverlappedBySelectionShape()
  580. {
  581. if (SelectionShape.IsVisible())
  582. {
  583. List<GameObject> overlappedObjects = SelectionShape.GetOverlappedGameObjects();
  584. overlappedObjects.RemoveAll(item => !CanGameObjectBeSelected(item));
  585. return overlappedObjects;
  586. }
  587. else return new List<GameObject>();
  588. }
  589. public void RemoveNullGameObjectEntries()
  590. {
  591. _selectedObjects.RemoveNullEntries();
  592. }
  593. public MouseCursorRayHit GetObjectPickedByCursor()
  594. {
  595. MouseCursor.Instance.PushObjectPickMaskFlags(MouseCursorObjectPickFlags.ObjectTerrain);
  596. MouseCursorRayHit cursorRayHit = MouseCursor.Instance.GetRayHit();
  597. MouseCursor.Instance.PopObjectPickMaskFlags();
  598. return cursorRayHit;
  599. }
  600. public void ProjectSelectionOnProjectionSurface()
  601. {
  602. if (NumberOfSelectedObjects == 0) return;
  603. if(!ObjectOnSurfaceProjectSettings.ProjectOnGrid)
  604. {
  605. GameObject projectionSurface = ObjectOnSurfaceProjectSettings.ProjectionSurface;
  606. if (projectionSurface == null) return;
  607. Vector3 projectionDirection = ObjectOnSurfaceProjectSettings.GetProjectionDirectionVector();
  608. GameObjectExtensions.EmbedAllObjectsInSurface(new List<GameObject>(_selectedObjects.HashSet), projectionDirection, projectionSurface);
  609. _objectSelectionGizmos.OnObjectSelectionUpdated();
  610. }
  611. else
  612. {
  613. Vector3 projectionDirection = ObjectOnSurfaceProjectSettings.GetProjectionDirectionVector();
  614. GameObjectExtensions.ProjectAllObjectsOnPlane(new List<GameObject>(_selectedObjects.HashSet), projectionDirection, ObjectSnapping.Get().XZSnapGrid.Plane);
  615. _objectSelectionGizmos.OnObjectSelectionUpdated();
  616. }
  617. }
  618. #endregion
  619. #region Private Methods
  620. private static bool CanGameObjectBeSelected(GameObject gameObject)
  621. {
  622. return ObjectQueries.CanGameObjectBeInteractedWith(gameObject);
  623. }
  624. private bool CanPerformClickSelectionUpdateOperation()
  625. {
  626. // Click operations can only be performed when the selection mode is not set to
  627. // 'Paint'. This is because the 'Paint' mode works better (i.e. behaves in a more
  628. // intuitive way) if we ignore clicks.
  629. return _settings.SelectionMode != ObjectSelectionMode.Paint;
  630. }
  631. private bool CanAdjustSelectionShapeSizeForMouseScrollWheel()
  632. {
  633. return _settings.SelectionMode == ObjectSelectionMode.Paint && SelectionShape.IsVisible() &&
  634. AllShortcutCombos.Instance.EnableScrollWheelSizeAdjustmentForSelectionShape.IsActive();
  635. }
  636. private void AdjustSelectionShapeSizeForMouseWheelScroll(Event e)
  637. {
  638. ObjectSelectionPaintModeSettings paintModeSettings = _settings.PaintModeSettings;
  639. int sizeAdjustAmount = (int)(-e.delta.y * paintModeSettings.ScrollWheelShapeSizeAdjustmentSpeed);
  640. UndoEx.RecordForToolAction(this);
  641. paintModeSettings.SelectionShapeWidthInPixels += sizeAdjustAmount;
  642. paintModeSettings.SelectionShapeHeightInPixels += sizeAdjustAmount;
  643. SceneView.RepaintAll();
  644. }
  645. private void OnEnable()
  646. {
  647. if(!_wasInitialized)
  648. {
  649. _selectionShape.EllipseShapeRenderSettings.FillColor = new Color(0.0f, 1.0f, 0.0f, 0.2f);
  650. _selectionShape.EllipseShapeRenderSettings.BorderLineColor = Color.green;
  651. _selectionShape.RectangleShapeRenderSettings.FillColor = new Color(0.0f, 1.0f, 0.0f, 0.2f);
  652. _selectionShape.RectangleShapeRenderSettings.BorderLineColor = Color.green;
  653. _wasInitialized = true;
  654. }
  655. }
  656. #endregion
  657. }
  658. }
  659. #endif