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