A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.IO;
4using UnityEngine;
5using UnityEngine.Tilemaps;
6
7namespace UnityEditor.Tilemaps
8{
9 /// <summary> This class is in charge of drag'n'drops of Tile assets on scene view </summary>
10 internal class TileDragAndDropManager : ScriptableSingleton<TileDragAndDropManager>
11 {
12 private bool m_RegisteredEventHandlers;
13 private Dictionary<Vector2Int, TileDragAndDropHoverData> m_HoverData;
14
15 [SerializeField]
16 private string m_LastUserTileAssetPath;
17
18 [InitializeOnLoadMethod]
19 static void Initialize()
20 {
21 instance.RegisterEventHandlers();
22 }
23
24 void OnEnable()
25 {
26 RegisterEventHandlers();
27 }
28
29 void RegisterEventHandlers()
30 {
31 if (m_RegisteredEventHandlers)
32 return;
33
34 SceneView.duringSceneGui += DuringSceneGui;
35 m_RegisteredEventHandlers = true;
36 }
37
38 void OnDisable()
39 {
40 SceneView.duringSceneGui -= DuringSceneGui;
41 m_RegisteredEventHandlers = false;
42 }
43
44 private void DuringSceneGui(SceneView sceneView)
45 {
46 Event evt = Event.current;
47 if (evt.type != EventType.DragUpdated && evt.type != EventType.DragPerform && evt.type != EventType.DragExited && evt.type != EventType.Repaint)
48 return;
49
50 Grid activeGrid = GetActiveGrid();
51 if (activeGrid == null || DragAndDrop.objectReferences.Length == 0)
52 return;
53
54 Vector3 localMouse = GridEditorUtility.ScreenToLocal(activeGrid.transform, evt.mousePosition);
55 Vector3Int mouseGridPosition = activeGrid.LocalToCell(localMouse);
56
57 switch (evt.type)
58 {
59 //TODO: Cache this
60 case EventType.DragUpdated:
61 DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
62 List<TileBase> tiles = TileDragAndDrop.GetValidTiles(DragAndDrop.objectReferences);
63 instance.m_HoverData = TileDragAndDrop.CreateHoverData(null, null, tiles, null, activeGrid.cellLayout);
64 if (instance.m_HoverData.Count > 0)
65 {
66 Event.current.Use();
67 GUI.changed = true;
68 }
69 break;
70 case EventType.DragPerform:
71 if (instance.m_HoverData.Count > 0)
72 {
73 DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
74 var tileSheet = TileDragAndDrop.ConvertToTileSheet(instance.m_HoverData);
75 Tilemap tilemap = GetOrCreateActiveTilemap();
76 tilemap.ClearAllEditorPreviewTiles();
77 int i = 0;
78 foreach (KeyValuePair<Vector2Int, TileDragAndDropHoverData> item in instance.m_HoverData)
79 {
80 Vector3Int position = new Vector3Int(mouseGridPosition.x + item.Key.x, mouseGridPosition.y + item.Key.y, 0);
81 tilemap.SetTile(position, tileSheet[i++]);
82 tilemap.SetTransformMatrix(position, Matrix4x4.TRS(
83 item.Value.hasOffset ? item.Value.positionOffset - tilemap.tileAnchor : Vector3.zero
84 , Quaternion.identity
85 , Vector3.one));
86 }
87 instance.m_HoverData = null;
88 GUI.changed = true;
89 Event.current.Use();
90 }
91 break;
92 case EventType.Repaint:
93 if (instance.m_HoverData != null)
94 {
95 DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
96
97 var map = Selection.activeGameObject.GetComponentInParent<Tilemap>();
98 var hasMap = map != null;
99 if (hasMap)
100 {
101 map.ClearAllEditorPreviewTiles();
102 foreach (KeyValuePair<Vector2Int, TileDragAndDropHoverData> item in instance.m_HoverData)
103 {
104 var gridPos = mouseGridPosition + new Vector3Int(item.Key.x, item.Key.y, 0);
105 if (item.Value.hoverObject is TileBase tile)
106 {
107 map.SetEditorPreviewTile(gridPos, tile);
108 }
109 }
110 }
111 }
112 break;
113 }
114
115 if (instance.m_HoverData != null && (
116 Event.current.type == EventType.DragExited ||
117 Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape))
118 {
119 if (instance.m_HoverData.Count > 0)
120 {
121 Tilemap map = Selection.activeGameObject.GetComponentInParent<Tilemap>();
122 if (map != null)
123 map.ClearAllEditorPreviewTiles();
124
125 Event.current.Use();
126 }
127
128 instance.m_HoverData = null;
129 }
130 }
131
132 internal static string GetDefaultTileAssetDirectoryPath()
133 {
134 var path = instance.m_LastUserTileAssetPath;
135 if (String.IsNullOrEmpty(path))
136 {
137 path = ProjectBrowser.s_LastInteractedProjectBrowser != null
138 ? ProjectBrowser.s_LastInteractedProjectBrowser.GetActiveFolderPath()
139 : "Assets";
140 }
141 return path;
142 }
143
144 internal static void SetUserTileAssetDirectoryPath(string path)
145 {
146 var directoryPath = String.Empty;
147 if (!String.IsNullOrEmpty(path))
148 {
149 // UUM-29240: UnityGetDirectoryName clips off last directory if path is not a file path
150 if (String.IsNullOrEmpty(FileUtil.GetPathExtension(path))
151 && !path.EndsWith("/") // MacOS
152 && !File.Exists(path))
153 {
154 path = FileUtil.CombinePaths(path, "");
155 }
156 directoryPath = FileUtil.UnityGetDirectoryName(path);
157 }
158 instance.m_LastUserTileAssetPath = directoryPath;
159 }
160
161 static Tilemap GetOrCreateActiveTilemap()
162 {
163 if (Selection.activeGameObject != null)
164 {
165 Tilemap tilemap = Selection.activeGameObject.GetComponentInParent<Tilemap>();
166 if (tilemap == null)
167 {
168 Grid grid = Selection.activeGameObject.GetComponentInParent<Grid>();
169 tilemap = CreateNewTilemap(grid);
170 }
171 return tilemap;
172 }
173 return null;
174 }
175
176 static Tilemap CreateNewTilemap(Grid grid)
177 {
178 GameObject go = new GameObject("Tilemap");
179 go.transform.SetParent(grid.gameObject.transform);
180 Tilemap map = go.AddComponent<Tilemap>();
181 go.AddComponent<TilemapRenderer>();
182 return map;
183 }
184
185 static Grid GetActiveGrid()
186 {
187 if (Selection.activeGameObject != null)
188 {
189 return Selection.activeGameObject.GetComponentInParent<Grid>();
190 }
191 return null;
192 }
193 }
194}