A game about forced loneliness, made by TACStudios
at master 293 lines 14 kB view raw
1using UnityEngine; 2using UnityEngine.Tilemaps; 3using Object = UnityEngine.Object; 4 5namespace UnityEditor.Tilemaps 6{ 7 /// <summary> 8 /// Utility Class for creating Palettes 9 /// </summary> 10 public static class GridPaletteUtility 11 { 12 internal enum GridPaletteType 13 { 14 Rectangle, 15 HexagonalPointTop, 16 HexagonalFlatTop, 17 Isometric, 18 IsometricZAsY, 19 }; 20 21 internal static readonly Vector3 defaultSortAxis = new Vector3(0f, 0f, 1f); 22 23 internal static GridLayout.CellLayout GetCellLayoutFromGridPaletteType(GridPaletteType paletteType) 24 { 25 switch (paletteType) 26 { 27 case GridPaletteType.HexagonalPointTop: 28 case GridPaletteType.HexagonalFlatTop: 29 { 30 return GridLayout.CellLayout.Hexagon; 31 } 32 case GridPaletteType.Isometric: 33 { 34 return GridLayout.CellLayout.Isometric; 35 } 36 case GridPaletteType.IsometricZAsY: 37 { 38 return GridLayout.CellLayout.IsometricZAsY; 39 } 40 } 41 return GridLayout.CellLayout.Rectangle; 42 } 43 44 internal static RectInt GetBounds(GameObject palette) 45 { 46 if (palette == null) 47 return new RectInt(); 48 49 Vector2Int min = new Vector2Int(int.MaxValue, int.MaxValue); 50 Vector2Int max = new Vector2Int(int.MinValue, int.MinValue); 51 52 foreach (var tilemap in palette.GetComponentsInChildren<Tilemap>()) 53 { 54 Vector3Int p1 = tilemap.editorPreviewOrigin; 55 Vector3Int p2 = p1 + tilemap.editorPreviewSize; 56 Vector2Int tilemapMin = new Vector2Int(Mathf.Min(p1.x, p2.x), Mathf.Min(p1.y, p2.y)); 57 Vector2Int tilemapMax = new Vector2Int(Mathf.Max(p1.x, p2.x), Mathf.Max(p1.y, p2.y)); 58 min = new Vector2Int(Mathf.Min(min.x, tilemapMin.x), Mathf.Min(min.y, tilemapMin.y)); 59 max = new Vector2Int(Mathf.Max(max.x, tilemapMax.x), Mathf.Max(max.y, tilemapMax.y)); 60 } 61 62 return GridEditorUtility.GetMarqueeRect(min, max); 63 } 64 65 /// <summary> 66 /// Creates a Palette Asset at the current selected folder path. This will show a popup allowing you to choose 67 /// a different folder path for saving the Palette Asset if required. 68 /// </summary> 69 /// <param name="name">Name of the Palette Asset.</param> 70 /// <param name="layout">Grid Layout of the Palette Asset.</param> 71 /// <param name="cellSizing">Cell Sizing of the Palette Asset.</param> 72 /// <param name="cellSize">Cell Size of the Palette Asset.</param> 73 /// <param name="swizzle">Cell Swizzle of the Palette.</param> 74 /// <returns>The created Palette Asset if successful.</returns> 75 public static GameObject CreateNewPaletteAtCurrentFolder(string name, GridLayout.CellLayout layout, GridPalette.CellSizing cellSizing, Vector3 cellSize, GridLayout.CellSwizzle swizzle) 76 { 77 return CreateNewPaletteAtCurrentFolder(name, layout, cellSizing, cellSize, swizzle 78 , TransparencySortMode.Default, defaultSortAxis); 79 } 80 81 /// <summary> 82 /// Creates a Palette Asset at the current selected folder path. This will show a popup allowing you to choose 83 /// a different folder path for saving the Palette Asset if required. 84 /// </summary> 85 /// <param name="name">Name of the Palette Asset.</param> 86 /// <param name="layout">Grid Layout of the Palette Asset.</param> 87 /// <param name="cellSizing">Cell Sizing of the Palette Asset.</param> 88 /// <param name="cellSize">Cell Size of the Palette Asset.</param> 89 /// <param name="swizzle">Cell Swizzle of the Palette.</param> 90 /// <param name="sortMode">Transparency Sort Mode for the Palette</param> 91 /// <param name="sortAxis">Transparency Sort Axis for the Palette</param> 92 /// <returns>The created Palette Asset if successful.</returns> 93 public static GameObject CreateNewPaletteAtCurrentFolder(string name 94 , GridLayout.CellLayout layout 95 , GridPalette.CellSizing cellSizing 96 , Vector3 cellSize 97 , GridLayout.CellSwizzle swizzle 98 , TransparencySortMode sortMode 99 , Vector3 sortAxis) 100 { 101 string defaultPath = ProjectBrowser.s_LastInteractedProjectBrowser ? ProjectBrowser.s_LastInteractedProjectBrowser.GetActiveFolderPath() : "Assets"; 102 string folderPath = EditorUtility.SaveFolderPanel("Create palette into folder ", defaultPath, ""); 103 folderPath = FileUtil.GetProjectRelativePath(folderPath); 104 if (!TilePaletteSaveUtility.ValidateSaveFolder(folderPath)) 105 return null; 106 return CreateNewPalette(folderPath, name, layout, cellSizing, cellSize, swizzle, sortMode, sortAxis); 107 } 108 109 /// <summary> 110 /// Creates a Palette Asset at the given folder path. 111 /// </summary> 112 /// <param name="folderPath">Folder Path of the Palette Asset.</param> 113 /// <param name="name">Name of the Palette Asset.</param> 114 /// <param name="layout">Grid Layout of the Palette Asset.</param> 115 /// <param name="cellSizing">Cell Sizing of the Palette Asset.</param> 116 /// <param name="cellSize">Cell Size of the Palette Asset.</param> 117 /// <param name="swizzle">Cell Swizzle of the Palette.</param> 118 /// <returns>The created Palette Asset if successful.</returns> 119 public static GameObject CreateNewPalette(string folderPath 120 , string name 121 , GridLayout.CellLayout layout 122 , GridPalette.CellSizing cellSizing 123 , Vector3 cellSize 124 , GridLayout.CellSwizzle swizzle) 125 { 126 return CreateNewPalette(folderPath, name, layout, cellSizing, cellSize, swizzle, 127 TransparencySortMode.Default, defaultSortAxis); 128 } 129 130 /// <summary> 131 /// Creates a Palette Asset at the given folder path. 132 /// </summary> 133 /// <param name="folderPath">Folder Path of the Palette Asset.</param> 134 /// <param name="name">Name of the Palette Asset.</param> 135 /// <param name="layout">Grid Layout of the Palette Asset.</param> 136 /// <param name="cellSizing">Cell Sizing of the Palette Asset.</param> 137 /// <param name="cellSize">Cell Size of the Palette Asset.</param> 138 /// <param name="swizzle">Cell Swizzle of the Palette.</param> 139 /// <param name="sortMode">Transparency Sort Mode for the Palette</param> 140 /// <param name="sortAxis">Transparency Sort Axis for the Palette</param> 141 /// <returns>The created Palette Asset if successful.</returns> 142 public static GameObject CreateNewPalette(string folderPath 143 , string name 144 , GridLayout.CellLayout layout 145 , GridPalette.CellSizing cellSizing 146 , Vector3 cellSize 147 , GridLayout.CellSwizzle swizzle 148 , TransparencySortMode sortMode 149 , Vector3 sortAxis) 150 { 151 GameObject temporaryGO = new GameObject(name); 152 Grid grid = temporaryGO.AddComponent<Grid>(); 153 154 // We set size to kEpsilon to mark this as new uninitialized palette 155 // Nice default size can be decided when first asset is dragged in 156 grid.cellSize = cellSize; 157 grid.cellLayout = layout; 158 grid.cellSwizzle = swizzle; 159 CreateNewLayer(temporaryGO, "Layer1", layout); 160 161 string path = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + name + ".prefab"); 162 163 Object prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(temporaryGO, path, InteractionMode.AutomatedAction); 164 GridPalette palette = CreateGridPalette(cellSizing, sortMode, sortAxis); 165 AssetDatabase.AddObjectToAsset(palette, prefab); 166 PrefabUtility.ApplyPrefabInstance(temporaryGO, InteractionMode.AutomatedAction); 167 AssetDatabase.Refresh(); 168 169 Object.DestroyImmediate(temporaryGO); 170 return AssetDatabase.LoadAssetAtPath<GameObject>(path); 171 } 172 173 private static GameObject CreateNewLayer(GameObject paletteGO, string name, GridLayout.CellLayout layout) 174 { 175 GameObject newLayerGO = new GameObject(name); 176 var tilemap = newLayerGO.AddComponent<Tilemap>(); 177 var renderer = newLayerGO.AddComponent<TilemapRenderer>(); 178 newLayerGO.transform.parent = paletteGO.transform; 179 newLayerGO.layer = paletteGO.layer; 180 181 // Set defaults for certain layouts 182 switch (layout) 183 { 184 case GridLayout.CellLayout.Hexagon: 185 { 186 tilemap.tileAnchor = Vector3.zero; 187 break; 188 } 189 case GridLayout.CellLayout.Isometric: 190 { 191 renderer.sortOrder = TilemapRenderer.SortOrder.TopRight; 192 break; 193 } 194 case GridLayout.CellLayout.IsometricZAsY: 195 { 196 renderer.sortOrder = TilemapRenderer.SortOrder.TopRight; 197 renderer.mode = TilemapRenderer.Mode.Individual; 198 break; 199 } 200 } 201 202 return newLayerGO; 203 } 204 205 internal static GridPalette GetGridPaletteFromPaletteAsset(Object palette) 206 { 207 string assetPath = AssetDatabase.GetAssetPath(palette); 208 GridPalette paletteAsset = AssetDatabase.LoadAssetAtPath<GridPalette>(assetPath); 209 return paletteAsset; 210 } 211 212 internal static GridPalette CreateGridPalette(GridPalette.CellSizing cellSizing) 213 { 214 return CreateGridPalette(cellSizing, TransparencySortMode.Default, defaultSortAxis); 215 } 216 217 internal static GridPalette CreateGridPalette(GridPalette.CellSizing cellSizing 218 , TransparencySortMode sortMode 219 , Vector3 sortAxis 220 ) 221 { 222 var palette = ScriptableObject.CreateInstance<GridPalette>(); 223 palette.name = "Palette Settings"; 224 palette.cellSizing = cellSizing; 225 palette.transparencySortMode = sortMode; 226 palette.transparencySortAxis = sortAxis; 227 return palette; 228 } 229 230 internal static Vector3 CalculateAutoCellSize(Grid grid, Vector3 defaultValue) 231 { 232 Tilemap[] tilemaps = grid.GetComponentsInChildren<Tilemap>(); 233 Sprite[] sprites = null; 234 var maxSize = Vector2.negativeInfinity; 235 var minSize = Vector2.positiveInfinity; 236 237 // Get minimum and maximum sizes for Sprites 238 foreach (var tilemap in tilemaps) 239 { 240 var spriteCount = tilemap.GetUsedSpritesCount(); 241 if (sprites == null || sprites.Length < spriteCount) 242 sprites = new Sprite[spriteCount]; 243 tilemap.GetUsedSpritesNonAlloc(sprites); 244 for (int i = 0; i < spriteCount; ++i) 245 { 246 Sprite sprite = sprites[i]; 247 if (sprite != null) 248 { 249 var cellSize = new Vector3(sprite.rect.width, sprite.rect.height, 0f) / sprite.pixelsPerUnit; 250 if (tilemap.cellSwizzle == GridLayout.CellSwizzle.YXZ) 251 { 252 var swap = cellSize.x; 253 cellSize.x = cellSize.y; 254 cellSize.y = swap; 255 } 256 minSize.x = Mathf.Min(cellSize.x, minSize.x); 257 minSize.y = Mathf.Min(cellSize.y, minSize.y); 258 maxSize.x = Mathf.Max(cellSize.x, maxSize.x); 259 maxSize.y = Mathf.Max(cellSize.y, maxSize.y); 260 } 261 } 262 } 263 // Validate that Sprites are in multiples of sizes 264 foreach (var tilemap in tilemaps) 265 { 266 var spriteCount = tilemap.GetUsedSpritesCount(); 267 if (sprites == null || sprites.Length < spriteCount) 268 sprites = new Sprite[spriteCount]; 269 tilemap.GetUsedSpritesNonAlloc(sprites); 270 for (int i = 0; i < spriteCount; ++i) 271 { 272 Sprite sprite = sprites[i]; 273 if (sprite != null) 274 { 275 var cellSize = new Vector3(sprite.rect.width, sprite.rect.height, 0f) / sprite.pixelsPerUnit; 276 if (tilemap.cellSwizzle == GridLayout.CellSwizzle.YXZ) 277 { 278 var swap = cellSize.x; 279 cellSize.x = cellSize.y; 280 cellSize.y = swap; 281 } 282 // Return maximum size if sprites are not multiples of the smallest size 283 if (cellSize.x % minSize.x > 0) 284 return maxSize.x * maxSize.y <= 0f ? defaultValue : new Vector3(maxSize.x, maxSize.y, 0f); 285 if (cellSize.y % minSize.y > 0) 286 return maxSize.x * maxSize.y <= 0f ? defaultValue : new Vector3(maxSize.x, maxSize.y, 0f); 287 } 288 } 289 } 290 return minSize.x * minSize.y <= 0f || minSize == Vector2.positiveInfinity ? defaultValue : new Vector3(minSize.x, minSize.y, 0f); 291 } 292 } 293}