A game about forced loneliness, made by TACStudios
at master 15 kB view raw
1using System; 2using UnityEngine; 3using UnityEngine.Tilemaps; 4using UnityEngine.UIElements; 5 6namespace UnityEditor.Tilemaps 7{ 8 internal class PaintableSceneViewGrid : PaintableGrid 9 { 10 private Transform gridTransform { get { return grid != null ? grid.transform : null; } } 11 private Grid grid { get { return brushTarget != null ? brushTarget.GetComponentInParent<Grid>() : (Selection.activeGameObject != null ? Selection.activeGameObject.GetComponentInParent<Grid>() : null); } } 12 private GridBrushBase gridBrush { get { return GridPaintingState.gridBrush; } } 13 private SceneView activeSceneView; 14 private int sceneViewTransformHash; 15 16 private GameObject brushTarget 17 { 18 get { return GridPaintingState.scenePaintTarget; } 19 } 20 21 public Tilemap tilemap 22 { 23 get 24 { 25 if (brushTarget != null) 26 { 27 return brushTarget.GetComponent<Tilemap>(); 28 } 29 return null; 30 } 31 } 32 33 public Action<GameObject> onEdited; 34 35 protected override void OnEnable() 36 { 37 base.OnEnable(); 38 SceneView.duringSceneGui += OnSceneGUI; 39 Undo.undoRedoPerformed += UndoRedoPerformed; 40 GridSelection.gridSelectionChanged += OnGridSelectionChanged; 41 } 42 43 protected override void OnDisable() 44 { 45 SceneView.duringSceneGui -= OnSceneGUI; 46 Undo.undoRedoPerformed -= UndoRedoPerformed; 47 GridSelection.gridSelectionChanged -= OnGridSelectionChanged; 48 base.OnDisable(); 49 } 50 51 private void OnGridSelectionChanged() 52 { 53 SceneView.RepaintAll(); 54 } 55 56 private Rect GetSceneViewPositionRect(SceneView sceneView) 57 { 58 return new Rect(0, 0, sceneView.position.width, sceneView.position.height); 59 } 60 61 public void OnSceneGUI(SceneView sceneView) 62 { 63 HandleMouseEnterLeave(sceneView); 64 65 CallOnSceneGUI(); 66 67 // Case 1093801: Handle only the currently active scene view 68 if (sceneView != activeSceneView) 69 return; 70 71 // Case 1077400: SceneView camera transform changes may update the mouse grid position even though the mouse position has not changed 72 var currentSceneViewTransformHash = sceneView.camera.transform.localToWorldMatrix.GetHashCode(); 73 UpdateMouseGridPosition(currentSceneViewTransformHash != sceneViewTransformHash); 74 sceneViewTransformHash = currentSceneViewTransformHash; 75 76 var dot = 1.0f; 77 var gridView = GetGridView(); 78 if (gridView != null) 79 { 80 dot = Math.Abs(Vector3.Dot(sceneView.camera.transform.forward, Grid.Swizzle(gridView.cellSwizzle, gridView.transform.forward))); 81 } 82 83 // Case 1021655: Validate that grid is not totally parallel to view (+-5 degrees), otherwise tiles could be accidentally painted on large positions 84 if (dot > 0.1f) 85 { 86 base.OnGUI(); 87 if (InGridEditMode()) 88 { 89 if ((grid != null) && (GridPaintingState.activeGrid == this || GridSelection.active)) 90 { 91 CallOnPaintSceneGUI(); 92 } 93 if (Event.current.type == EventType.Repaint) 94 EditorGUIUtility.AddCursorRect(GetSceneViewPositionRect(sceneView), MouseCursor.CustomCursor); 95 } 96 } 97 } 98 99 private void HandleMouseEnterLeave(SceneView sceneView) 100 { 101 if (GridPaintingState.isEditing) 102 { 103 if (Event.current.type == EventType.MouseEnterWindow) 104 { 105 OnMouseEnter(sceneView); 106 } 107 else if (Event.current.type == EventType.MouseLeaveWindow) 108 { 109 OnMouseLeave(); 110 } 111 // Case 1043365: When docked, the docking area is considered part of the window and MouseEnter/LeaveWindow events are not considered when entering the docking area 112 else if (sceneView.docked) 113 { 114 var guiPoint = Event.current.mousePosition; 115 var sceneViewPosition = GetSceneViewPositionRect(sceneView); 116 if (sceneViewPosition.Contains(guiPoint)) 117 { 118 if (GridPaintingState.activeGrid != this && EditorWindow.mouseOverWindow == sceneView) 119 { 120 OnMouseEnter(sceneView); 121 } 122 } 123 else if (activeSceneView == sceneView) 124 { 125 if (GridPaintingState.activeGrid == this) 126 { 127 OnMouseLeave(); 128 } 129 } 130 } 131 } 132 } 133 134 private void OnMouseEnter(SceneView sceneView) 135 { 136 if (GridPaintingState.activeBrushEditor != null) 137 GridPaintingState.activeBrushEditor.OnMouseEnter(); 138 activeSceneView = sceneView; 139 GridPaintingState.AddActiveGrid(this); 140 UpdateMouseGridPosition(true); 141 ResetPreviousMousePositionToCurrentPosition(); 142 } 143 144 private void OnMouseLeave() 145 { 146 if (GridPaintingState.activeBrushEditor != null) 147 GridPaintingState.activeBrushEditor.OnMouseLeave(); 148 GridPaintingState.RemoveActiveGrid(this); 149 activeSceneView = null; 150 } 151 152 private void UndoRedoPerformed() 153 { 154 RefreshAllTiles(); 155 } 156 157 private void RefreshAllTiles() 158 { 159 if (tilemap != null) 160 tilemap.RefreshAllTiles(); 161 } 162 163 protected override void RegisterUndo() 164 { 165 if (GridPaintingState.activeBrushEditor != null) 166 { 167 GridPaintingState.activeBrushEditor.RegisterUndo(brushTarget, EditTypeToBrushTool(EditorTools.ToolManager.activeToolType)); 168 } 169 } 170 171 protected override void Paint(Vector3Int position) 172 { 173 if (grid != null) 174 gridBrush.Paint(grid, brushTarget, position); 175 } 176 177 protected override void Erase(Vector3Int position) 178 { 179 if (grid != null) 180 gridBrush.Erase(grid, brushTarget, position); 181 } 182 183 protected override void BoxFill(BoundsInt position) 184 { 185 if (grid != null) 186 gridBrush.BoxFill(grid, brushTarget, position); 187 } 188 189 protected override void BoxErase(BoundsInt position) 190 { 191 if (grid != null) 192 gridBrush.BoxErase(grid, brushTarget, position); 193 } 194 195 protected override void FloodFill(Vector3Int position) 196 { 197 if (grid != null) 198 gridBrush.FloodFill(grid, brushTarget, position); 199 } 200 201 protected override void PickBrush(BoundsInt position, Vector3Int pickStart) 202 { 203 if (grid != null) 204 gridBrush.Pick(grid, brushTarget, position, pickStart); 205 } 206 207 protected override void Select(BoundsInt position) 208 { 209 if (grid != null) 210 { 211 GridSelection.Select(brushTarget, position); 212 gridBrush.Select(grid, brushTarget, position); 213 } 214 } 215 216 protected override void Move(BoundsInt from, BoundsInt to) 217 { 218 if (grid != null) 219 gridBrush.Move(grid, brushTarget, from, to); 220 } 221 222 protected override void MoveStart(BoundsInt position) 223 { 224 if (grid != null) 225 gridBrush.MoveStart(grid, brushTarget, position); 226 } 227 228 protected override void MoveEnd(BoundsInt position) 229 { 230 if (grid != null) 231 gridBrush.MoveEnd(grid, brushTarget, position); 232 } 233 234 protected override bool CustomTool(bool isToolHotControl, TilemapEditorTool tool, Vector3Int position) 235 { 236 var executed = false; 237 if (grid != null) 238 { 239 executed = tool.HandleTool(isToolHotControl, grid, brushTarget, position); 240 } 241 return executed; 242 } 243 244 protected override void OnEditStart() 245 { 246 if (GridPaintingState.activeBrushEditor != null && grid != null) 247 GridPaintingState.activeBrushEditor.OnEditStart(grid, brushTarget); 248 onEdited?.Invoke(brushTarget); 249 } 250 251 protected override void OnEditEnd() 252 { 253 if (GridPaintingState.activeBrushEditor != null && grid != null) 254 GridPaintingState.activeBrushEditor.OnEditEnd(grid, brushTarget); 255 } 256 257 protected override void ClearGridSelection() 258 { 259 GridSelection.Clear(); 260 } 261 262 public override bool isActive => grid != null; 263 264 public override Rect rectPosition => activeSceneView != null ? activeSceneView.rootVisualElement.worldBound : Rect.zero; 265 266 public override VisualElement windowRoot => activeSceneView != null ? activeSceneView.rootVisualElement.GetRoot() : null; 267 268 public override void Repaint() 269 { 270 SceneView.RepaintAll(); 271 } 272 273 protected override bool ValidateFloodFillPosition(Vector3Int position) 274 { 275 return true; 276 } 277 278 protected override Vector2Int ScreenToGrid(Vector2 screenPosition, float zPosition) 279 { 280 if (tilemap != null) 281 { 282 var transform = tilemap.transform; 283 var plane = new Plane(GetGridForward(tilemap), transform.position); 284 var screenLocal = GridEditorUtility.ScreenToLocal(transform, screenPosition, plane); 285 if (GridPaintingState.gridBrushMousePositionAtZ) 286 screenLocal.z = zPosition; 287 var cell = LocalToGrid(tilemap, screenLocal); 288 return new Vector2Int(cell.x, cell.y); 289 } 290 if (grid != null) 291 { 292 var screenLocal = GridEditorUtility.ScreenToLocal(gridTransform, screenPosition, GetGridPlane(grid)); 293 if (GridPaintingState.gridBrushMousePositionAtZ) 294 screenLocal.z = zPosition; 295 var cell = LocalToGrid(grid, screenLocal); 296 return new Vector2Int(cell.x, cell.y); 297 } 298 return Vector2Int.zero; 299 } 300 301 protected override bool PickingIsDefaultTool() 302 { 303 return false; 304 } 305 306 protected override bool CanPickOutsideEditMode() 307 { 308 return false; 309 } 310 311 protected override GridLayout.CellLayout CellLayout() 312 { 313 return grid.cellLayout; 314 } 315 316 Vector3Int LocalToGrid(GridLayout gridLayout, Vector3 local) 317 { 318 return gridLayout.LocalToCell(local); 319 } 320 321 private Vector3 GetGridForward(GridLayout gridLayout) 322 { 323 switch (gridLayout.cellSwizzle) 324 { 325 case GridLayout.CellSwizzle.XYZ: 326 return gridLayout.transform.forward * -1f; 327 case GridLayout.CellSwizzle.XZY: 328 return gridLayout.transform.up * -1f; 329 case GridLayout.CellSwizzle.YXZ: 330 return gridLayout.transform.forward; 331 case GridLayout.CellSwizzle.YZX: 332 return gridLayout.transform.up; 333 case GridLayout.CellSwizzle.ZXY: 334 return gridLayout.transform.right; 335 case GridLayout.CellSwizzle.ZYX: 336 return gridLayout.transform.right * -1f; 337 } 338 return gridLayout.transform.forward * -1f; 339 } 340 341 private Plane GetGridPlane(Grid planeForGrid) 342 { 343 return new Plane(GetGridForward(planeForGrid), planeForGrid.transform.position); 344 } 345 346 private GridLayout GetGridView() 347 { 348 if (tilemap != null) 349 return tilemap; 350 if (grid != null) 351 return grid; 352 return null; 353 } 354 355 void CallOnPaintSceneGUI() 356 { 357 bool hasSelection = GridSelection.active && GridSelection.target == brushTarget; 358 if (!hasSelection && GridPaintingState.activeGrid != this) 359 return; 360 361 RectInt rect = new RectInt(mouseGridPosition, new Vector2Int(1, 1)); 362 363 if (m_MarqueeStart.HasValue) 364 rect = GridEditorUtility.GetMarqueeRect(mouseGridPosition, m_MarqueeStart.Value); 365 else if (hasSelection) 366 rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); 367 368 var layoutGrid = tilemap != null ? tilemap.layoutGrid : grid as GridLayout; 369 BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); 370 if (GridPaintingState.activeBrushEditor != null) 371 { 372 GridPaintingState.activeBrushEditor.OnPaintSceneGUI(layoutGrid, brushTarget, brushBounds 373 , EditTypeToBrushTool(EditorTools.ToolManager.activeToolType), m_MarqueeStart.HasValue || executing); 374 } 375 else // Fallback when user hasn't defined custom editor 376 { 377 GridBrushEditorBase.OnPaintSceneGUIInternal(layoutGrid, brushTarget, brushBounds 378 , EditTypeToBrushTool(EditorTools.ToolManager.activeToolType), m_MarqueeStart.HasValue || executing); 379 } 380 } 381 382 void CallOnSceneGUI() 383 { 384 var gridLayout = tilemap != null ? tilemap : grid as GridLayout; 385 bool hasSelection = GridSelection.active && GridSelection.target == brushTarget; 386 if (GridPaintingState.activeBrushEditor != null) 387 { 388 GridPaintingState.activeBrushEditor.OnSceneGUI(gridLayout, brushTarget); 389 if (hasSelection) 390 { 391 GridPaintingState.activeBrushEditor.OnSelectionSceneGUI(gridLayout, brushTarget); 392 } 393 } 394 395 if (hasSelection) 396 { 397 RectInt rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); 398 BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); 399 GridBrushEditorBase.OnSceneGUIInternal(gridLayout, brushTarget, brushBounds 400 , EditTypeToBrushTool(EditorTools.ToolManager.activeToolType), m_MarqueeStart.HasValue || executing); 401 } 402 } 403 } 404}