A game about forced loneliness, made by TACStudios
1using UnityEngine;
2using UnityEngine.Tilemaps;
3
4namespace UnityEditor.Tilemaps
5{
6 static class GameObjectCreation
7 {
8 private static class Styles
9 {
10 public static readonly string rectangularCreateUndo = L10n.Tr("Create Tilemap");
11 public static readonly string pointTopHexagonCreateUndo = L10n.Tr("Hexagonal Point Top Tilemap");
12 public static readonly string flatTopHexagonCreateUndo = L10n.Tr("Hexagonal Flat Top Tilemap");
13 public static readonly string isometricCreateUndo = L10n.Tr("Isometric Tilemap");
14 public static readonly string isometricZAsYCreateUndo = L10n.Tr("Isometric Z As Y Tilemap");
15 public static readonly string copyFromTilePaletteUndo = L10n.Tr("Tilemap with Tile Palette Settings");
16
17 public static readonly string modifyExistingGridTitle = L10n.Tr("Modify existing Grid");
18 public static readonly string modifyExistingGridMessage = L10n.Tr("Creating the Tilemap will modify the existing selected Grid. Continue?");
19 public static readonly string continueText = L10n.Tr("Continue");
20 public static readonly string cancelText = L10n.Tr("Cancel");
21 }
22
23 enum TilemapMenuPriority : int
24 {
25 Rectangular = 3,
26 HexagonalFlatTop,
27 HexagonalPointTop,
28 Isometric,
29 IsometricZasY
30 }
31
32 internal static bool showDialog = true;
33
34 internal static string[] CreateTilemapTargetsNames = new[]
35 {
36 "From Tile Palette"
37 , "Rectangular Tilemap"
38 , "Hexagonal Point Top Tilemap"
39 , "Hexagonal Flat Top Tilemap"
40 , "Isometric Tilemap"
41 , "Isometric Z As Y Tilemap"
42 };
43
44 internal static void CreateTilemapTargets(int index)
45 {
46 switch (index)
47 {
48 case 1:
49 CreateRectangularTilemap();
50 break;
51 case 2:
52 CreateHexagonalPointTopTilemap();
53 break;
54 case 3:
55 CreateHexagonalFlatTopTilemap();
56 break;
57 case 4:
58 CreateIsometricTilemap();
59 break;
60 case 5:
61 CreateIsometricZAsYTilemap();
62 break;
63 case 0:
64 {
65 var palette = GridPaintingState.palette;
66 if (palette == null)
67 return;
68
69 var grid = palette.GetComponentInChildren<Grid>();
70 if (grid == null)
71 return;
72
73 var newSize = grid.cellSize;
74 var paletteAsset = GridPaletteUtility.GetGridPaletteFromPaletteAsset(palette);
75 if (paletteAsset != null && paletteAsset.cellSizing == GridPalette.CellSizing.Automatic)
76 {
77 newSize = GridPaletteUtility.CalculateAutoCellSize(grid, grid.cellSize);
78 }
79
80 GameObject newGameObject = null;
81 switch (grid.cellLayout)
82 {
83 case GridLayout.CellLayout.Rectangle:
84 newGameObject = CreateRectangularTilemapInternal(Styles.copyFromTilePaletteUndo);
85 break;
86 case GridLayout.CellLayout.Hexagon:
87 newGameObject = CreateHexagonalTilemapInternal(grid.cellSwizzle,
88 Styles.copyFromTilePaletteUndo, newSize);
89 break;
90 case GridLayout.CellLayout.Isometric:
91 newGameObject = CreateIsometricTilemapInternal(GridLayout.CellLayout.Isometric, Styles.copyFromTilePaletteUndo);
92 break;
93 case GridLayout.CellLayout.IsometricZAsY:
94 newGameObject = CreateIsometricTilemapInternal(GridLayout.CellLayout.IsometricZAsY, Styles.copyFromTilePaletteUndo);
95 break;
96 }
97 if (newGameObject == null)
98 return;
99
100 var newGrid = newGameObject.GetComponentInChildren<Grid>();
101 if (newGrid == null)
102 return;
103
104 var tilemap = palette.GetComponentInChildren<Tilemap>();
105 var newTilemaps = newGameObject.GetComponentsInChildren<Tilemap>();
106 // Get last new Tilemap child if there are multiple Tilemaps
107 var newTilemap = newTilemaps != null && newTilemaps.Length > 0 ? newTilemaps[^1] : null;
108
109 var tilemapRenderer = palette.GetComponentInChildren<TilemapRenderer>();
110 var newTilemapRenderer = newTilemap != null ? newTilemap.GetComponent<TilemapRenderer>() : null;
111
112 Undo.RecordObjects(new Object[] {newGrid, newTilemap, newTilemapRenderer}, Styles.copyFromTilePaletteUndo);
113
114 if (tilemap != null && newTilemap != null)
115 {
116 newTilemap.animationFrameRate = tilemap.animationFrameRate;
117 newTilemap.color = tilemap.color;
118 newTilemap.tileAnchor = tilemap.tileAnchor;
119 newTilemap.orientation = tilemap.orientation;
120 newTilemap.orientationMatrix = tilemap.orientationMatrix;
121 }
122
123 if (tilemapRenderer != null && newTilemapRenderer != null)
124 {
125 newTilemapRenderer.mode = tilemapRenderer.mode;
126 newTilemapRenderer.chunkSize = tilemapRenderer.chunkSize;
127 newTilemapRenderer.chunkCullingBounds = tilemapRenderer.chunkCullingBounds;
128 newTilemapRenderer.detectChunkCullingBounds = tilemapRenderer.detectChunkCullingBounds;
129 newTilemapRenderer.sortOrder = tilemapRenderer.sortOrder;
130 newTilemapRenderer.maskInteraction = tilemapRenderer.maskInteraction;
131 newTilemapRenderer.sortingOrder = tilemapRenderer.sortingOrder;
132 newTilemapRenderer.sortingLayerID = tilemapRenderer.sortingLayerID;
133 }
134
135 newGrid.cellSwizzle = grid.cellSwizzle;
136 if (newGrid.cellLayout != GridLayout.CellLayout.Hexagon)
137 newGrid.cellGap = grid.cellGap;
138 newGrid.cellSize = newSize;
139 }
140 break;
141 }
142 }
143
144 [MenuItem("GameObject/2D Object/Tilemap/Rectangular", priority = (int)TilemapMenuPriority.Rectangular)]
145 internal static void CreateRectangularTilemap()
146 {
147 CreateRectangularTilemapInternal(Styles.rectangularCreateUndo);
148 }
149
150 [MenuItem("GameObject/2D Object/Tilemap/Hexagonal Flat Top", priority = (int)TilemapMenuPriority.HexagonalFlatTop)]
151 internal static void CreateHexagonalFlatTopTilemap()
152 {
153 CreateHexagonalTilemapInternal(GridLayout.CellSwizzle.YXZ, Styles.flatTopHexagonCreateUndo, new Vector3(0.8659766f, 1, 1));
154 }
155
156 [MenuItem("GameObject/2D Object/Tilemap/Hexagonal Point Top", priority = (int)TilemapMenuPriority.HexagonalPointTop)]
157 internal static void CreateHexagonalPointTopTilemap()
158 {
159 CreateHexagonalTilemapInternal(GridLayout.CellSwizzle.XYZ, Styles.pointTopHexagonCreateUndo, new Vector3(0.8659766f, 1, 1));
160 }
161
162 [MenuItem("GameObject/2D Object/Tilemap/Isometric", priority = (int)TilemapMenuPriority.Isometric)]
163 internal static void CreateIsometricTilemap()
164 {
165 CreateIsometricTilemapInternal(GridLayout.CellLayout.Isometric, Styles.isometricCreateUndo);
166 }
167
168 [MenuItem("GameObject/2D Object/Tilemap/Isometric Z as Y", priority = (int)TilemapMenuPriority.IsometricZasY)]
169 internal static void CreateIsometricZAsYTilemap()
170 {
171 CreateIsometricTilemapInternal(GridLayout.CellLayout.IsometricZAsY, Styles.isometricZAsYCreateUndo);
172 }
173
174 private static GameObject CreateIsometricTilemapInternal(GridLayout.CellLayout isometricLayout, string undoMessage)
175 {
176 var valid = FindOrCreateRootGridAndValidate(isometricLayout, false, GridLayout.CellSwizzle.XYZ, true, new Vector3(1.0f, 0.5f, 1.0f), out var root);
177 if (!valid)
178 return null;
179
180 var uniqueName = GameObjectUtility.GetUniqueNameForSibling(root.transform, "Tilemap");
181 var tilemapGO = ObjectFactory.CreateGameObject(uniqueName, typeof(Tilemap), typeof(TilemapRenderer));
182 tilemapGO.transform.SetParent(root.transform);
183 tilemapGO.transform.position = Vector3.zero;
184
185 var grid = root.GetComponent<Grid>();
186 // Case 1071703: Do not reset cell size if adding a new Tilemap to an existing Grid of the same layout
187 if (isometricLayout != grid.cellLayout)
188 {
189 Undo.RecordObject(grid, undoMessage);
190 grid.cellLayout = isometricLayout;
191 grid.cellSize = new Vector3(1.0f, 0.5f, 1.0f);
192 }
193
194 var tilemapRenderer = tilemapGO.GetComponent<TilemapRenderer>();
195 tilemapRenderer.sortOrder = TilemapRenderer.SortOrder.TopRight;
196
197 GridPaintingState.FlushCache();
198 Selection.activeObject = tilemapGO;
199 Undo.RegisterCreatedObjectUndo(tilemapGO, undoMessage);
200 return root;
201 }
202
203 private static GameObject CreateHexagonalTilemapInternal(GridLayout.CellSwizzle swizzle, string undoMessage, Vector3 cellSize)
204 {
205 var valid = FindOrCreateRootGridAndValidate(Grid.CellLayout.Hexagon, true, swizzle, true, cellSize, out var root);
206 if (!valid)
207 return null;
208
209 var uniqueName = GameObjectUtility.GetUniqueNameForSibling(root.transform, "Tilemap");
210 var tilemapGO = ObjectFactory.CreateGameObject(uniqueName, typeof(Tilemap), typeof(TilemapRenderer));
211 tilemapGO.transform.SetParent(root.transform);
212 tilemapGO.transform.position = Vector3.zero;
213
214 var grid = root.GetComponent<Grid>();
215 Undo.RecordObject(grid, undoMessage);
216 grid.cellLayout = Grid.CellLayout.Hexagon;
217 grid.cellSwizzle = swizzle;
218 grid.cellSize = cellSize;
219 var tilemap = tilemapGO.GetComponent<Tilemap>();
220 tilemap.tileAnchor = Vector3.zero;
221
222 GridPaintingState.FlushCache();
223 Selection.activeObject = tilemapGO;
224 Undo.RegisterCreatedObjectUndo(tilemapGO, undoMessage);
225 return root;
226 }
227
228 private static GameObject CreateRectangularTilemapInternal(string undoMessage)
229 {
230 var valid = FindOrCreateRootGridAndValidate(Grid.CellLayout.Rectangle, false, GridLayout.CellSwizzle.XYZ, false, Vector3.one, out var root);
231 if (!valid)
232 return null;
233
234 var uniqueName = GameObjectUtility.GetUniqueNameForSibling(root.transform, "Tilemap");
235 var tilemapGO = ObjectFactory.CreateGameObject(uniqueName, typeof(Tilemap), typeof(TilemapRenderer));
236 Undo.SetTransformParent(tilemapGO.transform, root.transform, "");
237 tilemapGO.transform.position = Vector3.zero;
238
239 var grid = root.GetComponent<Grid>();
240 if (Grid.CellLayout.Rectangle != grid.cellLayout)
241 {
242 Undo.RecordObject(grid, undoMessage);
243 grid.cellLayout = Grid.CellLayout.Rectangle;
244 }
245
246 GridPaintingState.FlushCache();
247 Selection.activeObject = tilemapGO;
248 Undo.SetCurrentGroupName(undoMessage);
249 return root;
250 }
251
252 private static bool FindOrCreateRootGridAndValidate(GridLayout.CellLayout gridLayout
253 , bool changeSwizzle
254 , GridLayout.CellSwizzle swizzle
255 , bool changeSize
256 , Vector3 cellSize
257 , out GameObject gridGO)
258 {
259 gridGO = null;
260
261 // Check if active object has a Grid and can be a parent for the Tile Map
262 if (Selection.activeObject is GameObject)
263 {
264 var go = (GameObject)Selection.activeObject;
265 var parentGrid = go.GetComponentInParent<Grid>();
266 if (parentGrid != null)
267 {
268 if (showDialog
269 && Application.isHumanControllingUs
270 && !Application.isBatchMode
271 && (parentGrid.cellLayout != gridLayout
272 || (changeSwizzle && parentGrid.cellSwizzle != swizzle)
273 || (changeSize && Vector3.Distance(parentGrid.cellSize,cellSize) > 0.001f)))
274 {
275 var option = EditorUtility.DisplayDialog(Styles.modifyExistingGridTitle
276 , Styles.modifyExistingGridMessage
277 , Styles.continueText
278 , Styles.cancelText);
279 if (!option)
280 return false;
281 }
282 gridGO = parentGrid.gameObject;
283 }
284 }
285
286 if (gridGO == null)
287 {
288 gridGO = ObjectFactory.CreateGameObject("Grid", typeof(Grid));
289 gridGO.transform.position = Vector3.zero;
290
291 var grid = gridGO.GetComponent<Grid>();
292 grid.cellSize = new Vector3(1.0f, 1.0f, 0.0f);
293 Undo.SetCurrentGroupName("Create Grid");
294 }
295 return true;
296 }
297 }
298}