No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PaintableSceneViewGrid.cs 15KB

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