Elin Decompiled Documentation EA 23.344.1 Nightly
Loading...
Searching...
No Matches
TileManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using UnityEngine;
6
7public class TileManager : EClass
8{
9 private struct TileBounds
10 {
11 public int left;
12
13 public int width;
14
15 public int up;
16
17 public int down;
18 }
19
20 private class Grid
21 {
22 public bool[] used;
23
24 public int cols;
25
26 public int rows;
27
28 public void SetUsedSequence(int linear, int span)
29 {
30 for (int i = 0; i < span; i++)
31 {
32 int num = linear + i;
33 if (num >= 0 && num < used.Length)
34 {
35 used[num] = true;
36 }
37 }
38 }
39
40 public void AddRows(int n)
41 {
42 Array.Resize(ref used, cols * (rows + n));
43 rows += n;
44 }
45 }
46
47 private class Entry
48 {
49 public string source;
50
51 public string alias;
52
53 public TileRow row;
54
55 public FileInfo file;
56
57 public FileInfo snowFile;
58
59 public int[] tiles;
60
61 public string[] growth;
62 }
63
64 private static readonly (string source, Func<IEnumerable<TileRow>> rows)[] _sourceData = new(string, Func<IEnumerable<TileRow>>)[5]
65 {
66 ("Block", () => EClass.sources.blocks.rows),
67 ("Floor", () => EClass.sources.floors.rows),
68 ("Obj", () => EClass.sources.objs.rows),
69 ("Deco", () => EClass.sources.decos.rows),
70 ("CellEffect", () => EClass.sources.cellEffects.rows)
71 };
72
73 private static readonly List<Entry> _allocated = new List<Entry>();
74
75 private static bool _applied;
76
77 private const int GrowChunkRows = 8;
78
79 private static readonly Dictionary<TextureData, (int w, int h)> _grownTex = new Dictionary<TextureData, (int, int)>();
80
81 private static readonly Dictionary<ProceduralMesh, Vector2> _grownMesh = new Dictionary<ProceduralMesh, Vector2>();
82
83 private static readonly Dictionary<Material, Vector4> _grownMat = new Dictionary<Material, Vector4>();
84
85 private static readonly int _tiling = Shader.PropertyToID("_Tiling");
86
87 public static void Apply()
88 {
89 if (!_applied)
90 {
91 _applied = true;
93 }
94 }
95
96 private static void AllocateTiles()
97 {
98 Dictionary<MeshPass, TextureData> dictionary = BuildPassData();
99 Dictionary<TextureData, TextureData> dictionary2 = new Dictionary<TextureData, TextureData>();
100 foreach (TextureData value2 in EClass.core.textures.texMap.Values)
101 {
102 foreach (MeshPass item in value2.listPass)
103 {
104 if ((bool)item.snowPass && dictionary.TryGetValue(item.snowPass, out var value) && value != value2)
105 {
106 dictionary2[value2] = value;
107 break;
108 }
109 }
110 }
111 Dictionary<TextureData, Grid> grids = new Dictionary<TextureData, Grid>();
112 (string, Func<IEnumerable<TileRow>>)[] sourceData = _sourceData;
113 for (int i = 0; i < sourceData.Length; i++)
114 {
115 var (text, func) = sourceData[i];
116 foreach (Entry entry in ParseTiles(text, func()))
117 {
118 if (_allocated.Any((Entry e) => e.source == entry.source && string.Equals(e.alias, entry.alias, StringComparison.OrdinalIgnoreCase)))
119 {
120 continue;
121 }
122 int[] tiles = entry.row.tiles;
123 if (tiles != null && tiles.Length != 0 && ModUtil.FindSourceRowPackage(entry.row) == null)
124 {
125 Debug.LogWarning("#tile " + text + "/" + entry.alias + " is a base game row; to reskin it put the sprite in 'Texture Replace' as <texture_sheet>_<cell>.png instead of " + entry.file.FullName.ShortPath() + "; or use in game Texture Viewer");
126 }
127 else
128 {
129 try
130 {
131 Allocate(entry, dictionary, dictionary2, grids);
132 }
133 catch (Exception ex)
134 {
135 Debug.LogError($"#tile failed to allocate {text}/{entry.alias} ({entry.file.FullName.ShortPath()})\n{ex}");
136 }
137 }
138 }
139 }
140 sourceData = _sourceData;
141 for (int i = 0; i < sourceData.Length; i++)
142 {
143 (string, Func<IEnumerable<TileRow>>) tuple2 = sourceData[i];
144 var (text2, _) = tuple2;
145 foreach (TileRow row in tuple2.Item2())
146 {
147 int[] tiles2 = row.tiles;
148 if (tiles2 != null && tiles2.Length == 0 && _allocated.All((Entry e) => e.row != row))
149 {
150 Debug.LogWarning("#tile " + text2 + "/" + row.alias + " has empty tiles and no Texture/" + text2 + "/" + row.alias + ".png");
151 }
152 }
153 }
154 }
155
156 public static void ReapplyRows()
157 {
158 foreach (Entry entry in _allocated)
159 {
160 TileRow tileRow = _sourceData.First(((string source, Func<IEnumerable<TileRow>> rows) t) => t.source == entry.source).rows().FirstOrDefault((TileRow r) => string.Equals(r.alias, entry.alias, StringComparison.OrdinalIgnoreCase));
161 if (tileRow != null)
162 {
163 if (entry.growth != null && tileRow is SourceObj.Row { growth: not null } row)
164 {
165 InitGrowth(row, entry.growth);
166 }
167 ApplyRow(tileRow, entry.tiles);
168 }
169 }
170 if (_applied)
171 {
173 }
174 }
175
176 private static List<Entry> ParseTiles(string source, IEnumerable<TileRow> rows)
177 {
178 string text = source + "/";
179 Dictionary<string, FileInfo> dictionary = new Dictionary<string, FileInfo>(StringComparer.OrdinalIgnoreCase);
180 string key2;
181 foreach (KeyValuePair<string, string> dictModItem in SpriteReplacer.dictModItems)
182 {
183 dictModItem.Deconstruct(out var key, out key2);
184 string text2 = key;
185 string text3 = key2;
186 if (text2.StartsWith(text, StringComparison.OrdinalIgnoreCase))
187 {
188 string text4 = text2[text.Length..];
189 if (text4.IndexOf('/') < 0)
190 {
191 dictionary[text4] = new FileInfo(text3 + ".png");
192 }
193 }
194 }
195 List<TileRow> source2 = rows.ToList();
196 Dictionary<string, Entry> dictionary2 = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
197 FileInfo value;
198 foreach (KeyValuePair<string, FileInfo> item in dictionary)
199 {
200 item.Deconstruct(out key2, out value);
201 string name = key2;
202 FileInfo file = value;
203 TileRow tileRow = source2.FirstOrDefault((TileRow r) => string.Equals(r.alias, name, StringComparison.OrdinalIgnoreCase));
204 if (tileRow != null)
205 {
206 dictionary2[name] = new Entry
207 {
208 source = source,
209 alias = name,
210 row = tileRow,
211 file = file
212 };
213 }
214 }
215 foreach (KeyValuePair<string, FileInfo> item2 in dictionary)
216 {
217 item2.Deconstruct(out key2, out value);
218 string text5 = key2;
219 FileInfo fileInfo = value;
220 if (!dictionary2.ContainsKey(text5))
221 {
222 if (text5.EndsWith("_snow", StringComparison.OrdinalIgnoreCase) && dictionary2.TryGetValue(text5[..^5], out var value2))
223 {
224 value2.snowFile = fileInfo;
225 continue;
226 }
227 Debug.LogWarning("#tile no " + source + " row with alias '" + text5 + "' for " + fileInfo.FullName.ShortPath());
228 }
229 }
230 return dictionary2.Values.ToList();
231 }
232
233 private static TileBounds GetTileBounds(RenderRow row, int frames = 1)
234 {
235 TileBounds result = new TileBounds
236 {
237 width = Math.Max(1, frames)
238 };
239 int[] anime = GetAnime(row);
240 if (anime != null && anime.Length != 0)
241 {
242 result.width = Math.Max(result.width, anime[0]);
243 }
244 if (!(row is SourceCellEffect.Row))
245 {
246 if (row is SourceObj.Row row2)
247 {
248 if (row2.autoTile)
249 {
250 result.width = Math.Max(result.width, 16);
251 }
252 if (row2.growth is GrowSystemWeed)
253 {
254 result.left = 2;
255 result.width = Math.Max(Math.Max(1, frames - 2), 3);
256 }
257 if (row2.idRoof != 0)
258 {
259 result.width = Math.Max(result.width, 12);
260 }
261 }
262 }
263 else
264 {
265 result.width = Math.Max(result.width, 8);
266 }
267 if ((bool)row.renderData && row.renderData.multiSize)
268 {
269 result.up = 1;
270 }
271 if (row is TileRow tileRow && row.tileType != null)
272 {
273 result.down = tileRow.tileType.blockRenderMode switch
274 {
275 BlockRenderMode.WallOrFence => 3,
276 BlockRenderMode.Pillar => Math.Max(result.down, 1),
277 _ => result.down,
278 };
279 }
280 return result;
281 }
282
283 private static void Allocate(Entry entry, Dictionary<MeshPass, TextureData> passData, Dictionary<TextureData, TextureData> snowOf, Dictionary<TextureData, Grid> grids)
284 {
285 TileRow row = entry.row;
286 string text = entry.source + "/" + entry.alias + " (" + entry.file.FullName.ShortPath() + ")";
287 RenderData renderData = row.renderData;
288 if (!renderData || !renderData.pass || !passData.TryGetValue(renderData.pass, out var value))
289 {
290 Debug.LogWarning("#tile " + text + " has invalid render data");
291 return;
292 }
293 if (!TryMeasure(entry.file, value, out var frames, out var rows))
294 {
295 Debug.LogWarning($"#tile {text} sprite must be n*{value.tileW} x m*{value.tileH} (n < 100, m <= 4)");
296 return;
297 }
298 TextureData textureData = snowOf.TryGetValue(value);
299 if (entry.snowFile != null)
300 {
301 int frames2;
302 int rows2;
303 if (textureData == null)
304 {
305 Debug.LogWarning("#tile " + text + " ignore snow");
306 entry.snowFile = null;
307 }
308 else if (!TryMeasure(entry.snowFile, value, out frames2, out rows2) || frames2 != frames || rows2 != rows)
309 {
310 Debug.LogWarning("#tile " + text + " base and snow sprites size mismatch");
311 entry.snowFile = null;
312 }
313 }
314 TileBounds tileBounds = GetTileBounds(row, frames);
315 if (tileBounds.width > frames)
316 {
317 Debug.LogWarning($"#tile {text} uses {tileBounds.width} cells but sprite has {frames}");
318 }
319 if (tileBounds.up > 0 && rows < 1 + tileBounds.up)
320 {
321 Debug.LogWarning($"#tile {text} multiSize needs {1 + tileBounds.up} cells tall");
322 }
323 if (tileBounds.down > 0 && rows < 2)
324 {
325 Debug.LogWarning("#tile " + text + " wall/fence should include the pillar rows below the base row");
326 }
327 if (row is SourceObj.Row row2 && row2.growth is GrowSystemWeed && frames != 5)
328 {
329 Debug.LogWarning($"#tile {text} crop is 5 frames (stages 0..4, the 3rd is the base tile), got {frames}");
330 }
331 if (!grids.TryGetValue(value, out var value2))
332 {
333 value2 = (grids[value] = BuildGrid(value, textureData, passData));
334 }
335 int num = Math.Max(1 + tileBounds.up + tileBounds.down, rows);
336 int num2 = tileBounds.left + tileBounds.width;
337 int num3 = AllocateRect(value2, num2, num, tileBounds.up, tileBounds.left);
338 if (num3 < 0 && num2 <= value2.cols && TryAddRows(value, textureData, value2, num, text))
339 {
340 num3 = AllocateRect(value2, num2, num, tileBounds.up, tileBounds.left);
341 }
342 if (num3 < 0)
343 {
344 Debug.LogError($"#tile no free {num2}x{num} region left in '{value.id}' for {text}");
345 return;
346 }
347 int index = num3 - tileBounds.left - Math.Min(tileBounds.up, rows - 1) * 100;
348 Blit(value, entry.file, index);
349 if (entry.snowFile != null)
350 {
351 Blit(textureData, entry.snowFile, index);
352 }
353 entry.tiles = GetTiles(entry, row, num3, frames);
354 ApplyRow(row, entry.tiles);
355 _allocated.Add(entry);
356 Debug.Log($"#tile {entry.source}/{entry.alias} -> {value.id}#{num3} x{frames}");
357 }
358
359 private static int[] GetTiles(Entry entry, RenderRow row, int baseIndex, int frames)
360 {
361 int[] anime = GetAnime(row);
362 if (anime != null && anime.Length != 0)
363 {
364 return new int[1] { baseIndex };
365 }
366 if (row is SourceObj.Row row2)
367 {
368 if (row2.autoTile)
369 {
370 return new int[1] { baseIndex };
371 }
372 GrowSystem growth = row2.growth;
373 if (growth != null && !(growth is GrowSystemDeco) && !(growth is GrowSystemTreeCoralwood))
374 {
375 if (!(growth is GrowSystemWeed))
376 {
377 return new int[1] { MakeGrowthTile(entry, row2, baseIndex, frames) };
378 }
379 return new int[1] { baseIndex };
380 }
381 }
382 return Enumerable.Range(baseIndex, frames).ToArray();
383 }
384
385 private static int MakeGrowthTile(Entry entry, SourceObj.Row obj, int baseIndex, int frames)
386 {
387 string tag = entry.source + "/" + entry.alias;
388 string[] array = (string[])obj._growth.Clone();
389 if (array.Length > 1)
390 {
391 array[1] = string.Join("/", from v in array[1].Split('/')
392 select Cell(v, "stage").ToString());
393 }
394 int num = ((array.Length > 2 && array[2].ToInt() > 0) ? Cell(array[2], "harvest") : 0);
395 if (array.Length > 2)
396 {
397 array[2] = num.ToString();
398 }
399 entry.growth = array;
400 InitGrowth(obj, array);
401 int num2 = obj.renderData.ConvertTile(baseIndex);
402 int num3 = obj.growth.stages.Where((GrowSystem.Stage st) => st.renderData == obj.renderData).SelectMany((GrowSystem.Stage st) => st.tiles).DefaultIfEmpty(num2)
403 .Max();
404 if (num > 0)
405 {
406 num3 = Math.Max(num3, obj.growth.harvestTile + ((obj.growth is GrowSystemWheat) ? 1 : 0));
407 }
408 if (num3 - num2 + 1 > frames)
409 {
410 Debug.LogWarning($"#tile {tag} the growth stages has {num3 - num2 + 1} frames but the sprite has {frames}");
411 }
412 if (!(obj.growth is GrowSystemTree))
413 {
414 if (num <= 0)
415 {
416 return baseIndex + Math.Max(0, frames - 2);
417 }
418 return num;
419 }
420 return baseIndex + Math.Min(2, frames - 1);
421 int Cell(string s, string what)
422 {
423 int num4 = s.ToInt();
424 if (num4 < 0 || num4 >= frames)
425 {
426 Debug.LogWarning($"#tile {tag} _growth {what} offset {num4} is outside {frames}-frame");
427 num4 = Mathf.Clamp(num4, 0, frames - 1);
428 }
429 return baseIndex + num4;
430 }
431 }
432
433 private static void InitGrowth(SourceObj.Row obj, string[] resolved)
434 {
435 string[] growth = obj._growth;
436 obj._growth = resolved;
437 try
438 {
439 obj.growth.Init(obj);
440 }
441 finally
442 {
443 obj._growth = growth;
444 }
445 }
446
447 private static void ApplyRow(RenderRow row, int[] tiles)
448 {
449 row.tiles = tiles;
450 row._tiles = Array.Empty<int>();
451 row.sprites = null;
452 row.SetTiles();
453 }
454
455 private static void Blit(TextureData data, FileInfo file, int index)
456 {
457 TextureReplace textureReplace = new TextureReplace
458 {
459 file = file,
460 index = index,
461 data = data,
462 source = TextureReplace.Source.Mod
463 };
464 data.AddReplace(textureReplace);
465 textureReplace.TryRefresh(force: false);
466 }
467
468 private static bool TryMeasure(FileInfo file, TextureData data, out int frames, out int rows)
469 {
470 frames = (rows = 0);
471 Texture2D texture2D = IO.LoadPNG(file.FullName);
472 if (!texture2D)
473 {
474 return false;
475 }
476 frames = texture2D.width / data.tileW;
477 rows = texture2D.height / data.tileH;
478 int num = frames;
479 int result;
480 if (num >= 1 && num < 100)
481 {
482 num = rows;
483 if (num >= 1 && num <= 4 && texture2D.width % data.tileW == 0)
484 {
485 result = ((texture2D.height % data.tileH == 0) ? 1 : 0);
486 goto IL_0076;
487 }
488 }
489 result = 0;
490 goto IL_0076;
491 IL_0076:
492 UnityEngine.Object.Destroy(texture2D);
493 return (byte)result != 0;
494 }
495
496 private static void CheckUsedPx(Grid grid, Texture2D tex, int tileW, int tileH)
497 {
498 Color32[] px = tex.GetPixels32();
499 int num = Math.Min(grid.rows, tex.height / tileH);
500 int num2 = Math.Min(grid.cols, tex.width / tileW);
501 for (int i = 0; i < num; i++)
502 {
503 int y = tex.height - (i + 1) * tileH;
504 for (int j = 0; j < num2; j++)
505 {
506 int num3 = i * grid.cols + j;
507 if (!grid.used[num3])
508 {
509 grid.used[num3] = HasAnyPx(tex.width, j * tileW, y, tileW, tileH);
510 }
511 }
512 }
513 bool HasAnyPx(int texW, int x0, int num4, int w, int h)
514 {
515 for (int k = num4; k < num4 + h; k++)
516 {
517 int num5 = k * texW + x0;
518 for (int l = 0; l < w; l++)
519 {
520 if (px[num5 + l].a != 0)
521 {
522 return true;
523 }
524 }
525 }
526 return false;
527 }
528 }
529
530 private static Grid BuildGrid(TextureData data, TextureData snow, Dictionary<MeshPass, TextureData> passData)
531 {
532 Grid grid = new Grid
533 {
534 cols = data.tex.width / data.tileW,
535 rows = data.tex.height / data.tileH
536 };
537 grid.used = new bool[grid.cols * grid.rows];
538 CheckUsedPx(grid, data.tex, data.tileW, data.tileH);
539 if (snow != null)
540 {
541 CheckUsedPx(grid, snow.tex, data.tileW, data.tileH);
542 }
543 foreach (RenderRow allTileRow in GetAllTileRows())
544 {
545 RenderData renderData = allTileRow.renderData;
546 if (!renderData || !renderData.pass || passData.TryGetValue(renderData.pass) != data || allTileRow._tiles == null)
547 {
548 continue;
549 }
550 TileBounds tileBounds = GetTileBounds(allTileRow);
551 int[] tiles = allTileRow._tiles;
552 for (int i = 0; i < tiles.Length; i++)
553 {
554 int num = Math.Abs(tiles[i]) - tileBounds.left;
555 for (int j = -tileBounds.up; j <= tileBounds.down; j++)
556 {
557 grid.SetUsedSequence(num + j * grid.cols, tileBounds.left + tileBounds.width);
558 }
559 }
560 if (allTileRow is SourceObj.Row { growth: { stages: var stages } growth })
561 {
562 foreach (GrowSystem.Stage stage in stages)
563 {
564 if (!stage.renderData || passData.TryGetValue(stage.renderData.pass) != data)
565 {
566 continue;
567 }
568 tiles = stage.tiles;
569 foreach (int num2 in tiles)
570 {
571 for (int l = -tileBounds.up; l <= 0; l++)
572 {
573 grid.SetUsedSequence(num2 + l * grid.cols, 1);
574 }
575 }
576 }
577 if (growth.harvestTile != 0 && (bool)growth.RenderHarvest && passData.TryGetValue(growth.RenderHarvest.pass) == data)
578 {
579 grid.SetUsedSequence(growth.harvestTile, 2);
580 }
581 }
582 if (allTileRow.snowTile <= 0)
583 {
584 continue;
585 }
586 RenderRow renderRow = allTileRow;
587 if (!(renderRow is SourceBlock.Row))
588 {
589 if (renderRow is SourceObj.Row { idRoof: not 0 })
590 {
591 grid.SetUsedSequence(renderData.ConvertTile(allTileRow.snowTile), 12);
592 }
593 }
594 else
595 {
596 grid.SetUsedSequence(renderData.ConvertTile(allTileRow.snowTile), 16);
597 }
598 }
599 SetBuiltinSequence(grid, data, passData);
600 return grid;
601 }
602
603 private static void SetBuiltinSequence(Grid grid, TextureData data, Dictionary<MeshPass, TextureData> passData)
604 {
605 if (grid.cols != 32)
606 {
607 return;
608 }
609 List<SourceFloor.Row> list = EClass.sources.floors.rows.Where((SourceFloor.Row r) => (bool)r.renderData && (bool)r.renderData.pass && passData.TryGetValue(r.renderData.pass) == data).ToList();
610 if (list.Count == 0)
611 {
612 return;
613 }
614 grid.SetUsedSequence(24 * grid.cols, 16);
615 foreach (SourceFloor.Row item in list)
616 {
617 if (item.edge >= 0)
618 {
619 grid.SetUsedSequence((24 + item.edge / 2) * grid.cols + item.edge % 2 * 16, 16);
620 }
621 if (item.autotile > 0)
622 {
623 grid.SetUsedSequence((26 + item.autotile / 2) * grid.cols + item.autotile % 2 * 16, 16);
624 }
625 }
626 foreach (SourceDeco.Row row in EClass.sources.decos.rows)
627 {
628 if (row.autotile > 0 && (bool)row.renderData && (bool)row.renderData.pass && passData.TryGetValue(row.renderData.pass) == data)
629 {
630 grid.SetUsedSequence((26 + row.autotile / 2) * grid.cols + row.autotile % 2 * 16, 16);
631 }
632 }
633 }
634
635 private static int AllocateRect(Grid grid, int cols, int rows, int baseRowOffset, int baseColOffset)
636 {
637 for (int i = 0; i + rows <= grid.rows; i++)
638 {
639 for (int j = 0; j + cols <= grid.cols; j++)
640 {
641 if (IsRectFree(grid, i, j, cols, rows))
642 {
643 for (int k = 0; k < rows; k++)
644 {
645 grid.SetUsedSequence((i + k) * grid.cols + j, cols);
646 }
647 return (i + baseRowOffset) * 100 + j + baseColOffset;
648 }
649 }
650 }
651 return -1;
652 }
653
654 private static bool IsRectFree(Grid grid, int r, int c, int cols, int rows)
655 {
656 for (int i = 0; i < rows; i++)
657 {
658 int num = (r + i) * grid.cols + c;
659 for (int j = 0; j < cols; j++)
660 {
661 if (grid.used[num + j])
662 {
663 return false;
664 }
665 }
666 }
667 return true;
668 }
669
670 private static bool TryAddRows(TextureData data, TextureData snow, Grid grid, int rowsNeeded, string tag)
671 {
672 int cols = grid.cols;
673 int rows = grid.rows;
674 int num = Math.Min(10000 / cols, SystemInfo.maxTextureSize / data.tileH);
675 if (rows + rowsNeeded > num)
676 {
677 Debug.LogError($"#tile '{data.id}' has no empty rows ({rows} rows of {cols}, max {num}), cannot add {tag}");
678 return false;
679 }
680 int num2 = Math.Min(Math.Max(rowsNeeded, 8), num - rows);
681 List<MeshPass> passes = GetPasses(data, snow);
682 TextureData[] array = new TextureData[2] { data, snow };
683 foreach (TextureData textureData in array)
684 {
685 if (textureData != null)
686 {
687 ReinitTextureH(textureData, num2 * textureData.tileH);
688 }
689 }
690 foreach (MeshPass item in passes)
691 {
692 ProceduralMesh pmesh = item.pmesh;
693 if ((bool)pmesh && Mathf.RoundToInt(pmesh.tiling.x) == cols && Mathf.RoundToInt(pmesh.tiling.y) == rows)
694 {
695 if (!_grownMesh.ContainsKey(pmesh))
696 {
697 _grownMesh[pmesh] = pmesh.tiling;
698 }
699 pmesh.tiling.y = rows + num2;
700 pmesh.Create();
701 }
702 Material mat = item.mat;
703 if (!mat || !mat.HasProperty(_tiling))
704 {
705 continue;
706 }
707 Vector4 vector = mat.GetVector(_tiling);
708 if (Mathf.RoundToInt(vector.x) == cols && Mathf.RoundToInt(vector.y) == rows)
709 {
710 _grownMat.TryAdd(mat, vector);
711 float num3 = 1f / (float)rows;
712 if (vector.z > 0f && vector.z < num3)
713 {
714 vector.z *= (float)rows / (float)(rows + num2);
715 }
716 if (vector.w > 0f && vector.w < num3)
717 {
718 vector.w *= (float)rows / (float)(rows + num2);
719 }
720 vector.y = rows + num2;
721 mat.SetVector(_tiling, vector);
722 }
723 }
724 foreach (MeshPass item2 in passes)
725 {
726 if ((bool)item2.pmesh)
727 {
728 item2.mesh = null;
729 item2._Refresh();
730 }
731 }
732 grid.AddRows(num2);
733 Debug.Log($"#tile '{data.id}' added {num2} rows to {grid.rows}x{cols} ({data.tex.width}x{data.tex.height}) for {tag}");
734 return true;
735 }
736
737 private static void ReinitTextureH(TextureData d, int addH)
738 {
739 Texture2D tex = d.tex;
740 int width = tex.width;
741 int height = tex.height;
742 Color32[] pixels = tex.GetPixels32();
743 if (!_grownTex.ContainsKey(d))
744 {
745 _grownTex[d] = (width, height);
746 }
747 bool flag = tex.mipmapCount > 1;
748 if (!tex.Reinitialize(width, height + addH, tex.format, flag))
749 {
750 throw new InvalidOperationException($"could not reinitialize '{d.id}' to {width}x{height + addH}");
751 }
752 tex.SetPixels32(0, addH, width, height, pixels);
753 tex.SetPixels32(0, 0, width, addH, new Color32[width * addH]);
754 tex.Apply(flag, makeNoLongerReadable: false);
755 d.extraRows += addH / d.tileH;
756 }
757
758 private static List<MeshPass> GetPasses(TextureData data, TextureData snow)
759 {
760 HashSet<MeshPass> hashSet = new HashSet<MeshPass>();
761 TextureData[] array = new TextureData[2] { data, snow };
762 foreach (TextureData textureData in array)
763 {
764 if (textureData == null)
765 {
766 continue;
767 }
768 foreach (MeshPass item in textureData.listPass.Where((MeshPass p) => p))
769 {
770 hashSet.Add(item);
771 if ((bool)item.subPass)
772 {
773 hashSet.Add(item.subPass);
774 }
775 if ((bool)item.snowPass)
776 {
777 hashSet.Add(item.snowPass);
778 }
779 if ((bool)item.shadowPass)
780 {
781 hashSet.Add(item.shadowPass);
782 }
783 }
784 }
785 return hashSet.ToList();
786 }
787
788 private static Dictionary<MeshPass, TextureData> BuildPassData()
789 {
790 Dictionary<MeshPass, TextureData> dictionary = new Dictionary<MeshPass, TextureData>();
791 foreach (TextureData value in EClass.core.textures.texMap.Values)
792 {
793 foreach (MeshPass item in value.listPass)
794 {
795 dictionary[item] = value;
796 }
797 }
798 return dictionary;
799 }
800
801 private static IEnumerable<RenderRow> GetAllTileRows()
802 {
803 foreach (SourceBlock.Row row in EClass.sources.blocks.rows)
804 {
805 yield return row;
806 }
807 foreach (SourceFloor.Row row2 in EClass.sources.floors.rows)
808 {
809 yield return row2;
810 }
811 foreach (SourceObj.Row row3 in EClass.sources.objs.rows)
812 {
813 yield return row3;
814 }
815 foreach (SourceDeco.Row row4 in EClass.sources.decos.rows)
816 {
817 yield return row4;
818 }
819 foreach (SourceCellEffect.Row row5 in EClass.sources.cellEffects.rows)
820 {
821 yield return row5;
822 }
823 foreach (SourceThing.Row row6 in EClass.sources.things.rows)
824 {
825 yield return row6;
826 }
827 }
828
829 private static int[] GetAnime(RenderRow row)
830 {
831 if (!(row is SourceBlock.Row { anime: var anime }))
832 {
833 if (!(row is SourceFloor.Row { anime: var anime2 }))
834 {
835 if (!(row is SourceDeco.Row { anime: var anime3 }))
836 {
837 if (!(row is SourceCellEffect.Row { anime: var anime4 }))
838 {
839 if (!(row is SourceThing.Row { anime: var anime5 }))
840 {
841 return null;
842 }
843 return anime5;
844 }
845 return anime4;
846 }
847 return anime3;
848 }
849 return anime2;
850 }
851 return anime;
852 }
853}
Definition: Cell.cs:7
override string ToString()
Definition: Cell.cs:1139
TextureManager textures
Definition: Core.cs:45
Definition: EClass.cs:6
static Core core
Definition: EClass.cs:7
static SourceManager sources
Definition: EClass.cs:43
ProceduralMesh pmesh
Definition: MeshPass.cs:25
void _Refresh()
Definition: MeshPass.cs:466
bool multiSize
Definition: RenderData.cs:33
MeshPass pass
Definition: RenderData.cs:17
RenderData renderData
Definition: RenderRow.cs:71
TileType tileType
Definition: RenderRow.cs:77
int[] _tiles
Definition: RenderRow.cs:12
int[] tiles
Definition: RenderRow.cs:10
virtual void SetTiles()
Definition: RenderRow.cs:258
int snowTile
Definition: RenderRow.cs:28
SourceObj objs
SourceThing things
SourceDeco decos
SourceCellEffect cellEffects
SourceBlock blocks
SourceFloor floors
GrowSystem growth
Definition: SourceObj.cs:34
static Dictionary< string, string > dictModItems
Texture2D tex
Definition: TextureData.cs:39
List< MeshPass > listPass
Definition: TextureData.cs:57
void AddReplace(TextureReplace r)
Definition: TextureData.cs:202
Dictionary< string, TextureData > texMap
void TryRefresh(bool force)
FileInfo snowFile
Definition: TileManager.cs:57
void SetUsedSequence(int linear, int span)
Definition: TileManager.cs:28
void AddRows(int n)
Definition: TileManager.cs:40
static TileBounds GetTileBounds(RenderRow row, int frames=1)
Definition: TileManager.cs:233
static void AllocateTiles()
Definition: TileManager.cs:96
static readonly Dictionary< ProceduralMesh, Vector2 > _grownMesh
Definition: TileManager.cs:81
static void Blit(TextureData data, FileInfo file, int index)
Definition: TileManager.cs:455
const int GrowChunkRows
Definition: TileManager.cs:77
static bool IsRectFree(Grid grid, int r, int c, int cols, int rows)
Definition: TileManager.cs:654
static bool TryAddRows(TextureData data, TextureData snow, Grid grid, int rowsNeeded, string tag)
Definition: TileManager.cs:670
static Grid BuildGrid(TextureData data, TextureData snow, Dictionary< MeshPass, TextureData > passData)
Definition: TileManager.cs:530
static int MakeGrowthTile(Entry entry, SourceObj.Row obj, int baseIndex, int frames)
Definition: TileManager.cs:385
static Dictionary< MeshPass, TextureData > BuildPassData()
Definition: TileManager.cs:788
static void InitGrowth(SourceObj.Row obj, string[] resolved)
Definition: TileManager.cs:433
static IEnumerable< RenderRow > GetAllTileRows()
Definition: TileManager.cs:801
static void CheckUsedPx(Grid grid, Texture2D tex, int tileW, int tileH)
Definition: TileManager.cs:496
static int[] GetTiles(Entry entry, RenderRow row, int baseIndex, int frames)
Definition: TileManager.cs:359
static readonly int _tiling
Definition: TileManager.cs:85
static readonly List< Entry > _allocated
Definition: TileManager.cs:73
static void SetBuiltinSequence(Grid grid, TextureData data, Dictionary< MeshPass, TextureData > passData)
Definition: TileManager.cs:603
static readonly(string source, Func< IEnumerable< TileRow > > rows)[] _sourceData
static bool _applied
Definition: TileManager.cs:75
static void Apply()
Definition: TileManager.cs:87
static List< Entry > ParseTiles(string source, IEnumerable< TileRow > rows)
Definition: TileManager.cs:176
static void ReinitTextureH(TextureData d, int addH)
Definition: TileManager.cs:737
static void Allocate(Entry entry, Dictionary< MeshPass, TextureData > passData, Dictionary< TextureData, TextureData > snowOf, Dictionary< TextureData, Grid > grids)
Definition: TileManager.cs:283
static void ReapplyRows()
Definition: TileManager.cs:156
static List< MeshPass > GetPasses(TextureData data, TextureData snow)
Definition: TileManager.cs:758
static readonly Dictionary< TextureData,(int w, int h)> _grownTex
Definition: TileManager.cs:79
static readonly Dictionary< Material, Vector4 > _grownMat
Definition: TileManager.cs:83
static int AllocateRect(Grid grid, int cols, int rows, int baseRowOffset, int baseColOffset)
Definition: TileManager.cs:635
static bool TryMeasure(FileInfo file, TextureData data, out int frames, out int rows)
Definition: TileManager.cs:468
static void ApplyRow(RenderRow row, int[] tiles)
Definition: TileManager.cs:447
static int[] GetAnime(RenderRow row)
Definition: TileManager.cs:829
string alias
Definition: TileRow.cs:13