Tilemap cells are stored compactly in the project file: each layer keeps a tile list, an origin and one run-length encoded string per row; older projects with a cell map still load (#134)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
732f6518ae
commit
10b49fac46
6 files changed
+319
-4
No files matched your search
@@ -28,6 +28,7 @@ import type {
|
||||
TilemapLayer,
|
||||
} from '../model/Asset';
|
||||
import { parseCellKey } from '../model/tilemap';
|
||||
import { decodeCells, encodeCells, isStoredCells } from './tilemapCells';
|
||||
import { isAssetType } from '../model/AssetTypes';
|
||||
import { isFontFile } from '../model/font';
|
||||
import { isSoundFile } from '../model/sound';
|
||||
@@ -218,9 +219,19 @@ export function deserializeProject(raw: unknown, fallbackId = ''): Project {
|
||||
return project;
|
||||
}
|
||||
|
||||
/** Plain JSON-ready copy of the project (deep clone, stable key order for readable diffs). */
|
||||
/**
|
||||
* Plain JSON-ready copy of the project (deep clone, stable key order for readable diffs). The cells
|
||||
* of a tilemap are the one thing written differently from how they are held: see `tilemapCells.ts`.
|
||||
*/
|
||||
export function serializeProject(project: Project): unknown {
|
||||
return JSON.parse(JSON.stringify(project));
|
||||
const copy = JSON.parse(JSON.stringify(project)) as Project;
|
||||
for (const asset of copy.assets)
|
||||
if (asset.type === 'tilemap')
|
||||
(asset as { layers: unknown[] }).layers = asset.layers.map(({ cells, ...layer }) => ({
|
||||
...layer,
|
||||
...encodeCells(cells),
|
||||
}));
|
||||
return copy;
|
||||
}
|
||||
|
||||
function normalizeObjects(
|
||||
@@ -513,8 +524,10 @@ function normalizeLayers(raw: unknown): TilemapLayer[] {
|
||||
for (const item of Array.isArray(raw) ? raw : []) {
|
||||
const l = asRecord(item);
|
||||
if (typeof l.id !== 'string' || !l.id || layers.some((o) => o.id === l.id)) continue;
|
||||
// Projects saved before #134 hold the map itself; it is taken over as it is.
|
||||
const stored = isStoredCells(l) ? decodeCells(l) : asRecord(l.cells);
|
||||
const cells: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(asRecord(l.cells)))
|
||||
for (const [key, value] of Object.entries(stored))
|
||||
if (parseCellKey(key) && typeof value === 'string' && value !== '') cells[key] = value;
|
||||
const layer: TilemapLayer = { id: l.id, name: typeof l.name === 'string' ? l.name : 'Layer', cells };
|
||||
if (l.hidden === true) layer.hidden = true;
|
||||
|
||||
Reference in new issue
Block a user