ObjectEraser.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace O3DWB
  7. {
  8. [Serializable]
  9. public class ObjectEraser : ScriptableObject
  10. {
  11. #region Private Variables
  12. [SerializeField]
  13. private ObjectEraserSettings _settings;
  14. [SerializeField]
  15. private ObjectMask _eraseMask = new ObjectMask();
  16. [SerializeField]
  17. private Object2DMassEraseShape _mass2DEraseShape = new Object2DMassEraseShape();
  18. [SerializeField]
  19. private Object3DMassEraseShape _mass3DEraseShape = new Object3DMassEraseShape();
  20. private DateTime _lastEraseOperationTime = System.DateTime.Now;
  21. [SerializeField]
  22. private bool _wasInitialized = false;
  23. #endregion
  24. #region Public Properties
  25. public ObjectMask EraseMask { get { return _eraseMask; } }
  26. public ObjectEraserSettings Settings
  27. {
  28. get
  29. {
  30. if (_settings == null) _settings = Octave3DWorldBuilder.ActiveInstance.CreateScriptableObject<ObjectEraserSettings>();
  31. return _settings;
  32. }
  33. }
  34. public EllipseShapeRenderSettings Circle2DMassEraseShapeRenderSettings { get { return _mass2DEraseShape.CircleShapeRenderSettings; } }
  35. public XZOrientedEllipseShapeRenderSettings Circle3DMassEraseShapeRenderSettings { get { return _mass3DEraseShape.CircleShapeRenderSettings; } }
  36. #endregion
  37. #region Public Static Functions
  38. public static ObjectEraser Get()
  39. {
  40. return Octave3DWorldBuilder.ActiveInstance.ObjectEraser;
  41. }
  42. #endregion
  43. #region Public Methods
  44. public void RenderGizmos()
  45. {
  46. if (Settings.EraseMode == ObjectEraseMode.ObjectMass2D) _mass2DEraseShape.RenderGizmos();
  47. else if (Settings.EraseMode == ObjectEraseMode.ObjectMass3D) _mass3DEraseShape.RenderGizmos();
  48. }
  49. public void HandleMouseMoveEvent(Event e)
  50. {
  51. if (Settings.EraseMode == ObjectEraseMode.ObjectMass2D)
  52. {
  53. e.DisableInSceneView();
  54. _mass2DEraseShape.HandleMouseMoveEvent(e);
  55. }
  56. else if (Settings.EraseMode == ObjectEraseMode.ObjectMass3D)
  57. {
  58. e.DisableInSceneView();
  59. _mass3DEraseShape.HandleMouseMoveEvent(e);
  60. }
  61. }
  62. public void HandleMouseDragEvent(Event e)
  63. {
  64. if (!e.InvolvesLeftMouseButton()) return;
  65. if (Settings.EraseMode == ObjectEraseMode.ObjectMass2D) _mass2DEraseShape.HandleMouseDragEvent(e);
  66. else if (Settings.EraseMode == ObjectEraseMode.ObjectMass3D) _mass3DEraseShape.HandleMouseDragEvent(e);
  67. AnalyzeEventAndPerformEraseOperationIfNecessary(e);
  68. e.DisableInSceneView();
  69. }
  70. public void HandleMouseButtonDownEvent(Event e)
  71. {
  72. AnalyzeEventAndPerformEraseOperationIfNecessary(e);
  73. }
  74. public void HandleMouseButtonUpEvent(Event e)
  75. {
  76. }
  77. public void HandleMouseScrollWheelEvent(Event e)
  78. {
  79. if (CanAdjustMassEraseShapeSizeForMouseScrollWheel())
  80. {
  81. e.DisableInSceneView();
  82. AdjustMassEraseShapeSizeForMouseWheelScroll(e);
  83. }
  84. }
  85. public List<GameObject> GetGameObjectsForMassEraseOperation()
  86. {
  87. if (Settings.EraseMode == ObjectEraseMode.ObjectMass2D) return FilterObjectsWhichCanBeErased(_mass2DEraseShape.GetOverlappedGameObjectsForEraseOperation());
  88. else if (Settings.EraseMode == ObjectEraseMode.ObjectMass3D) return FilterObjectsWhichCanBeErased(_mass3DEraseShape.GetOverlappedGameObjectsForEraseOperation());
  89. else return new List<GameObject>();
  90. }
  91. public List<GameObject> FilterObjectsWhichCanBeErased(List<GameObject> gameObjectsToErase)
  92. {
  93. if (gameObjectsToErase.Count == 0) return new List<GameObject>();
  94. // If we don't need to erase only mesh objects, no filtering is required, so we will just return the original list
  95. if (!Settings.EraseOnlyMeshObjects) return gameObjectsToErase;
  96. // Ensure we only erase mesh objects
  97. var gameObjectsWhichCanBeErased = new List<GameObject>(gameObjectsToErase.Count);
  98. foreach(GameObject gameObject in gameObjectsToErase)
  99. {
  100. if (!gameObject.HasMesh() && (gameObject.HasLight() || gameObject.HasParticleSystem())) continue;
  101. gameObjectsWhichCanBeErased.Add(gameObject);
  102. }
  103. return gameObjectsWhichCanBeErased;
  104. }
  105. public MouseCursorRayHit GetMouseCursorRayHit()
  106. {
  107. MouseCursor.Instance.PushObjectPickMaskFlags(MouseCursorObjectPickFlags.ObjectTerrain);
  108. MouseCursorRayHit cursorRayHit = MouseCursor.Instance.GetRayHit();
  109. MouseCursor.Instance.PopObjectPickMaskFlags();
  110. return cursorRayHit;
  111. }
  112. #endregion
  113. #region Private Methods
  114. private bool EnoughTimeHasPassedForNewEraseOperation(DateTime currentTime)
  115. {
  116. return ((currentTime - _lastEraseOperationTime).TotalSeconds >= _settings.EraseDelayInSeconds);
  117. }
  118. private void AdjustMassEraseShapeSizeForMouseWheelScroll(Event e)
  119. {
  120. if (Settings.EraseMode == ObjectEraseMode.ObjectMass2D) AdjustMass2DEraseShapeSizeForMouseWheelScroll(e);
  121. else
  122. if (Settings.EraseMode == ObjectEraseMode.ObjectMass3D) AdjustMass3DEraseShapeSizeForMouseWheelScroll(e);
  123. }
  124. private void AdjustMass2DEraseShapeSizeForMouseWheelScroll(Event e)
  125. {
  126. Object2DMassEraseSettings mass2DEraseSettings = _settings.Mass2DEraseSettings;
  127. int sizeAdjustAmount = (int)(-e.delta.y * mass2DEraseSettings.ScrollWheelCircleRadiusAdjustmentSpeed);
  128. UndoEx.RecordForToolAction(mass2DEraseSettings);
  129. mass2DEraseSettings.CircleShapeRadius += sizeAdjustAmount;
  130. SceneView.RepaintAll();
  131. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  132. }
  133. private void AdjustMass3DEraseShapeSizeForMouseWheelScroll(Event e)
  134. {
  135. Object3DMassEraseSettings mass3DEraseSettings = _settings.Mass3DEraseSettings;
  136. int sizeAdjustAmount = (int)(-e.delta.y * mass3DEraseSettings.ScrollWheelCircleRadiusAdjustmentSpeed);
  137. UndoEx.RecordForToolAction(mass3DEraseSettings);
  138. mass3DEraseSettings.CircleShapeRadius += sizeAdjustAmount;
  139. SceneView.RepaintAll();
  140. Octave3DWorldBuilder.ActiveInstance.Inspector.EditorWindow.Repaint();
  141. }
  142. private void AnalyzeEventAndPerformEraseOperationIfNecessary(Event e)
  143. {
  144. DateTime currentTime = DateTime.Now;
  145. if (e.InvolvesLeftMouseButton() && EnoughTimeHasPassedForNewEraseOperation(currentTime))
  146. {
  147. e.DisableInSceneView();
  148. PerformEraseOperation(currentTime);
  149. }
  150. }
  151. private void PerformEraseOperation(DateTime currentTime)
  152. {
  153. PerformNecessaryUndoRecordingsBeforeEraseOperation();
  154. ObjectEraseOperationFactory.Create(_settings.EraseMode).Perform();
  155. _lastEraseOperationTime = currentTime;
  156. }
  157. private void PerformNecessaryUndoRecordingsBeforeEraseOperation()
  158. {
  159. // Note: We have to increment the current group, because otherwise the previous records will be overridden
  160. // by the new one and we would not be able to properly restore the states on Undo. For example, this
  161. // can result in loosing the object selection information.
  162. UndoEx.IncrementCurrentGroup();
  163. UndoEx.RecordForToolAction(ObjectSelection.Get());
  164. }
  165. private bool CanAdjustMassEraseShapeSizeForMouseScrollWheel()
  166. {
  167. return IsAnyMassEraseShapeVisible() && AllShortcutCombos.Instance.EnableScrollWheelSizeAdjustmentForMassEraseShape.IsActive();
  168. }
  169. private bool IsAnyMassEraseShapeVisible()
  170. {
  171. return _mass2DEraseShape.IsVisible() || _mass3DEraseShape.IsVisible();
  172. }
  173. private void OnEnable()
  174. {
  175. if(!_wasInitialized)
  176. {
  177. InitializeMassEraseShapes();
  178. _wasInitialized = true;
  179. }
  180. }
  181. private void InitializeMassEraseShapes()
  182. {
  183. InitializeMass2DEraseShape();
  184. InitializeMass3DEraseShape();
  185. }
  186. private void InitializeMass2DEraseShape()
  187. {
  188. _mass2DEraseShape.CircleShapeRenderSettings.BorderLineColor = Color.red;
  189. _mass2DEraseShape.CircleShapeRenderSettings.FillColor = new Color(1.0f, 0.0f, 0.0f, 0.4f);
  190. }
  191. private void InitializeMass3DEraseShape()
  192. {
  193. _mass3DEraseShape.CircleShapeRenderSettings.BorderLineColor = Color.red;
  194. }
  195. #endregion
  196. }
  197. }
  198. #endif