Açıklama Yok
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 14KB

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