Stop marking older sprites as changed after loading (#232)
game-maker / gate (push) Successful in 3m9s
game-maker / suite (push) Successful in 9m36s

Loading filled every missing asset property with its `default`. For
Sort with parent that is `false`, while the gold mark and Reset compare
against `initial`, which is `true`. So every sprite, text and particle
source saved before #232 counted as changed once loaded, and each save
wrote the `false` into the project file.

- normalizeBag leaves a missing key missing when it has its own
  `initial`. It still reads as `false`, so older projects draw as
  before, but they no longer count as changed.
- e2e module 4 failed in CI on three checks since 8b44f97. Its Reset
  click hit the extra Reset of Sort with parent instead of Height.
- The #232 test deleted the key on the object instead of going through
  the load path. It now checks that loading keeps the key missing and
  marks nothing. serialize.test.ts no longer expects the filled value.

Tests:
- ./check.sh: 167 files, 2435 tests, CHECK EXIT 0
- e2e 1-5 chained: ALL PASSED, 141 checks (before the fix the same
  three module 4 checks failed locally, as in CI)
- Counter-check: without the fix the extended test fails

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-26 15:05:10 +02:00
1 parent 085e6c8cce
commit 74b9c60661
3 files changed
+7 -2

No files matched your search

+4 -1
View File
@@ -84,6 +84,7 @@ import {
import { type FlatItem, makeFlatItem } from '../properties/listItems';
import {
coerceValue,
initialOf,
isValidFieldName,
isValidVariableName,
type PropertyDef,
@@ -771,7 +772,9 @@ function normalizeBag(raw: unknown, schema: PropertySchema, sparse: boolean): Pr
for (const def of schema) {
const value = r[def.key];
if (value === undefined || value === null) {
if (!sparse) bag[def.key] = def.default;
// A key with its own `initial` stays missing: written out, the old reading would count as
// a deviation from what a new asset starts with, and mark every older asset gold.
if (!sparse && initialOf(def) === def.default) bag[def.key] = def.default;
continue;
}
bag[def.key] = coerceValue(def, value as PropertyValue);
-1
View File
@@ -177,7 +177,6 @@ describe('serialize', () => {
rotation: 0,
mirrorX: false,
mirrorY: false,
sortWithParent: false,
width: 10,
height: 100,
color: 0xffffff,
+3
View File
@@ -65,6 +65,9 @@ describe('a child sorted with its parent (#232)', () => {
delete weapon.props[SORT_WITH_PARENT_KEY];
const loaded = findAsset(roundTrip(s.f.project), s.weaponId)!;
expect(resolveAssetProps(s.f.project, loaded)[SORT_WITH_PARENT_KEY]).toBe(false);
// Loading must not write the old reading out, or every older asset would be marked.
expect(loaded.props[SORT_WITH_PARENT_KEY]).toBeUndefined();
expect(isModified(s.f.project, loaded, SORT_WITH_PARENT_KEY)).toBe(false);
});
it('marks an asset only once it is switched off, and Reset switches it on again', () => {