SceneViewGridManager.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace UnityEditor.Tilemaps
  4. {
  5. /// <summary> This class is in charge of handling Grid component based grid in the scene view (rendering, snapping).
  6. /// It will hide global scene view grid when it has something to render</summary>
  7. internal class SceneViewGridManager : ScriptableSingleton<SceneViewGridManager>
  8. {
  9. internal static readonly PrefColor sceneViewGridComponentGizmo = new PrefColor("Scene/Grid Component", 255.0f / 255.0f, 255.0f / 255.0f, 255.0f / 255.0f, 25.5f / 255.0f);
  10. private static Mesh s_GridProxyMesh;
  11. private static Material s_GridProxyMaterial;
  12. private static int s_LastGridProxyHash;
  13. [SerializeField]
  14. private GridLayout m_ActiveGridProxy;
  15. private Dictionary<SceneView, bool> m_SceneViewShowGridMap;
  16. private bool m_RegisteredEventHandlers;
  17. private bool active { get { return m_ActiveGridProxy != null; } }
  18. internal GridLayout activeGridProxy { get { return m_ActiveGridProxy; } }
  19. [InitializeOnLoadMethod]
  20. private static void Initialize()
  21. {
  22. instance.RegisterEventHandlers();
  23. }
  24. private void OnEnable()
  25. {
  26. m_SceneViewShowGridMap = new Dictionary<SceneView, bool>();
  27. RegisterEventHandlers();
  28. }
  29. private void RegisterEventHandlers()
  30. {
  31. if (m_RegisteredEventHandlers)
  32. return;
  33. SceneView.duringSceneGui += OnSceneGuiDelegate;
  34. Selection.selectionChanged += UpdateCache;
  35. EditorApplication.hierarchyChanged += UpdateCache;
  36. UnityEditor.EditorTools.ToolManager.activeToolChanged += ActiveToolChanged;
  37. EditorApplication.quitting += EditorQuitting;
  38. GridPaintingState.brushChanged += OnBrushChanged;
  39. GridPaintingState.scenePaintTargetChanged += OnScenePaintTargetChanged;
  40. GridSnapping.snapPosition = OnSnapPosition;
  41. GridSnapping.activeFunc = GetActive;
  42. m_RegisteredEventHandlers = true;
  43. }
  44. private void OnBrushChanged(GridBrushBase brush)
  45. {
  46. UpdateCache();
  47. }
  48. private void ActiveToolChanged()
  49. {
  50. UpdateCache();
  51. }
  52. private void OnScenePaintTargetChanged(GameObject scenePaintTarget)
  53. {
  54. UpdateCache();
  55. }
  56. private void OnDisable()
  57. {
  58. FlushCachedGridProxy();
  59. RestoreSceneViewShowGrid();
  60. SceneView.duringSceneGui -= OnSceneGuiDelegate;
  61. Selection.selectionChanged -= UpdateCache;
  62. EditorApplication.hierarchyChanged -= UpdateCache;
  63. EditorApplication.quitting -= EditorQuitting;
  64. UnityEditor.EditorTools.ToolManager.activeToolChanged -= ActiveToolChanged;
  65. GridPaintingState.brushChanged -= OnBrushChanged;
  66. GridPaintingState.scenePaintTargetChanged -= OnScenePaintTargetChanged;
  67. GridSnapping.snapPosition = null;
  68. GridSnapping.activeFunc = null;
  69. m_RegisteredEventHandlers = false;
  70. }
  71. private void UpdateCache()
  72. {
  73. GridLayout gridProxy;
  74. if (PaintableGrid.InGridEditMode())
  75. gridProxy = GridPaintingState.scenePaintTarget != null ? GridPaintingState.scenePaintTarget.GetComponentInParent<GridLayout>() : null;
  76. else
  77. gridProxy = Selection.activeGameObject != null ? Selection.activeGameObject.GetComponentInParent<GridLayout>() : null;
  78. if (gridProxy != m_ActiveGridProxy)
  79. {
  80. if (m_ActiveGridProxy == null)
  81. {
  82. // Disable SceneView grid if there is now a GridProxy. Store user settings to be restored.
  83. StoreSceneViewShowGrid(false);
  84. }
  85. else if (gridProxy == null)
  86. {
  87. RestoreSceneViewShowGrid();
  88. }
  89. m_ActiveGridProxy = gridProxy;
  90. FlushCachedGridProxy();
  91. SceneView.RepaintAll();
  92. }
  93. }
  94. private void EditorQuitting()
  95. {
  96. if (NeedsRestoreSceneViewShowGrid())
  97. {
  98. RestoreSceneViewShowGrid();
  99. // SceneView.showGrid is part of default window preferences
  100. WindowLayout.SaveDefaultWindowPreferences();
  101. }
  102. }
  103. private void OnSceneGuiDelegate(SceneView sceneView)
  104. {
  105. if (active)
  106. DrawGrid(activeGridProxy);
  107. }
  108. private static int GenerateHash(GridLayout layout, Color color)
  109. {
  110. int hash = 0x7ed55d16;
  111. hash ^= layout.cellSize.GetHashCode();
  112. hash ^= layout.cellLayout.GetHashCode() << 23;
  113. hash ^= (layout.cellGap.GetHashCode() << 4) + 0x165667b1;
  114. hash ^= layout.cellSwizzle.GetHashCode() << 7;
  115. hash ^= color.GetHashCode();
  116. return hash;
  117. }
  118. private static void DrawGrid(GridLayout gridLayout)
  119. {
  120. int gridHash = GenerateHash(gridLayout, sceneViewGridComponentGizmo.Color);
  121. if (s_LastGridProxyHash != gridHash)
  122. {
  123. FlushCachedGridProxy();
  124. s_LastGridProxyHash = gridHash;
  125. }
  126. GridEditorUtility.DrawGridGizmo(gridLayout, gridLayout.transform, sceneViewGridComponentGizmo.Color, ref s_GridProxyMesh, ref s_GridProxyMaterial);
  127. }
  128. private bool NeedsRestoreSceneViewShowGrid()
  129. {
  130. return m_SceneViewShowGridMap.Count > 0;
  131. }
  132. private void StoreSceneViewShowGrid(bool value)
  133. {
  134. m_SceneViewShowGridMap.Clear();
  135. foreach (SceneView sceneView in SceneView.sceneViews)
  136. {
  137. m_SceneViewShowGridMap.Add(sceneView, sceneView.showGrid);
  138. sceneView.showGrid = value;
  139. }
  140. }
  141. private void RestoreSceneViewShowGrid()
  142. {
  143. foreach (var item in m_SceneViewShowGridMap)
  144. {
  145. var sceneView = item.Key;
  146. if (sceneView != null)
  147. sceneView.showGrid = item.Value;
  148. }
  149. m_SceneViewShowGridMap.Clear();
  150. }
  151. private bool GetActive()
  152. {
  153. return active;
  154. }
  155. internal Vector3 OnSnapPosition(Vector3 position)
  156. {
  157. Vector3 result = position;
  158. if (active && (EditorSnapSettings.hotkeyActive || EditorSnapSettings.gridSnapActive))
  159. {
  160. // This will automatically prefer the Grid
  161. Vector3 local = activeGridProxy.WorldToLocal(position);
  162. Vector3 interpolatedCell = activeGridProxy.LocalToCellInterpolated(local);
  163. Vector3 inverse = Vector3.one;
  164. inverse.x = Mathf.Approximately(EditorSnapSettings.move.x, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.x;
  165. inverse.y = Mathf.Approximately(EditorSnapSettings.move.y, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.y;
  166. inverse.z = Mathf.Approximately(EditorSnapSettings.move.z, 0.0f) ? 1.0f : 1.0f / EditorSnapSettings.move.z;
  167. Vector3 roundedCell = new Vector3(
  168. Mathf.Round(inverse.x * interpolatedCell.x) / inverse.x,
  169. Mathf.Round(inverse.y * interpolatedCell.y) / inverse.y,
  170. Mathf.Round(inverse.z * interpolatedCell.z) / inverse.z
  171. );
  172. local = activeGridProxy.CellToLocalInterpolated(roundedCell);
  173. result = activeGridProxy.LocalToWorld(local);
  174. }
  175. return result;
  176. }
  177. internal static void FlushCachedGridProxy()
  178. {
  179. if (s_GridProxyMesh == null)
  180. return;
  181. DestroyImmediate(s_GridProxyMesh);
  182. s_GridProxyMesh = null;
  183. s_GridProxyMaterial = null;
  184. }
  185. }
  186. }