Paint an asset's name gold while any of its values deviates
The inspector already marked an asset value that differs from its schema default, but the Assets panel gave no hint, so a changed asset looked like an untouched one until you opened it. The rule sits next to the existing objectDeviates as a pure function: assetDeviates asks whether any marked property differs, markedAssetSchema says which rows the inspector marks at all. buildAssetSection now builds its rows from that same list, replacing the behavior/rest split it used to carry, so the list cannot claim a deviation the inspector then fails to show. A behavior's variables are deliberately not in it. Their default is declared on the variable itself, which means the asset value *is* that default; counting them would paint the fixture's Mover gold while the inspector beside it marks nothing.
This commit is contained in:
1 parent
e0d43e12aa
commit
e9634f0f0d
10 files changed
+166
-15
No files matched your search
@@ -20,7 +20,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
|
|||||||
| **Behavior** | Logic as an asset: a **node graph** plus the **variables** it declares. Placed like anything else (a diamond symbol in the scene); its parent is the **owner** the graph acts on. |
|
| **Behavior** | Logic as an asset: a **node graph** plus the **variables** it declares. Placed like anything else (a diamond symbol in the scene); its parent is the **owner** the graph acts on. |
|
||||||
| **Collider** | A shape (box or circle) for collision detection, placed as a **child** of the object it belongs to (its *body*). Drawn as a green outline in edit mode only. |
|
| **Collider** | A shape (box or circle) for collision detection, placed as a **child** of the object it belongs to (its *body*). Drawn as a green outline in edit mode only. |
|
||||||
| **Override** | A per-object value that replaces the asset's value for one property. Only changed keys are stored; the inspector paints their label gold and offers a reset (↺) and an **apply** (↑) that writes the value into the asset instead. Both appear only where the value really differs from its base – an override carrying the asset's own value is none. |
|
| **Override** | A per-object value that replaces the asset's value for one property. Only changed keys are stored; the inspector paints their label gold and offers a reset (↺) and an **apply** (↑) that writes the value into the asset instead. Both appear only where the value really differs from its base – an override carrying the asset's own value is none. |
|
||||||
| **Default** | Every property has a schema default. Asset values that differ from it are marked gold in the inspector and can be reset (↺) the same way an override can. |
|
| **Default** | Every property has a schema default. Asset values that differ from it are marked gold in the inspector and can be reset (↺) the same way an override can. The asset's name in the **Assets** panel carries the same gold while any of them does (`assetDeviates`, `src/core/properties/deviation.ts` – the inspector marks the rows of that same schema, so the list cannot claim a deviation the inspector then fails to show). A behavior's variables are not in it: their default is declared on the variable itself, so the asset value cannot differ from it. |
|
||||||
| **Instance** | An object resolved from a placed container's template. Its **values** can be edited – position, name, property overrides – and only what actually deviates is stored, as a sparse `instanceEdits` entry on the container object keyed by the template path. Everything else keeps following the template. Its **structure** cannot: it can not be removed, re-parented or given a collider, and nothing of the scene can be parented into it. ↺ ▾ resets to the nearest base, which inside a container is the **template as the containers in between leave it**; ↑ ▾ offers **Apply to container** (write the value into the template, where every other instance still at the old value picks it up) and/or **Apply to asset** (which drops the template's override as well). With one base left the menu collapses to a plain ↺ / ↑, with none the buttons disappear. Gold marks the same thing the buttons offer. |
|
| **Instance** | An object resolved from a placed container's template. Its **values** can be edited – position, name, property overrides – and only what actually deviates is stored, as a sparse `instanceEdits` entry on the container object keyed by the template path. Everything else keeps following the template. Its **structure** cannot: it can not be removed, re-parented or given a collider, and nothing of the scene can be parented into it. ↺ ▾ resets to the nearest base, which inside a container is the **template as the containers in between leave it**; ↑ ▾ offers **Apply to container** (write the value into the template, where every other instance still at the old value picks it up) and/or **Apply to asset** (which drops the template's override as well). With one base left the menu collapses to a plain ↺ / ↑, with none the buttons disappear. Gold marks the same thing the buttons offer. |
|
||||||
| **Unpack** | Writes a placed container's content into the scene as ordinary objects (hierarchy context menu, or the inspector's *Content* section). The ids survive it, so the selection does; from then on the structure is editable and the objects no longer follow the template. |
|
| **Unpack** | Writes a placed container's content into the scene as ordinary objects (hierarchy context menu, or the inspector's *Content* section). The ids survive it, so the selection does; from then on the structure is editable and the objects no longer follow the template. |
|
||||||
| **Edit mode** | The Scene tab draws the project model; panels, grid, gizmos and drag-to-move are active. |
|
| **Edit mode** | The Scene tab draws the project model; panels, grid, gizmos and drag-to-move are active. |
|
||||||
@@ -440,7 +440,7 @@ npm run format # Prettier over src, tests and tools
|
|||||||
npm run check # typecheck + lint + format:check + tests, what CI would run
|
npm run check # typecheck + lint + format:check + tests, what CI would run
|
||||||
npm run build # writes dist/ and regenerates index.html
|
npm run build # writes dist/ and regenerates index.html
|
||||||
export GM_REMOTE=user@host # where the browser runs; see below
|
export GM_REMOTE=user@host # where the browser runs; see below
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 312 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 318 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||||
node tools/seed-jumprun.mjs && node tools/smoke-jumprun.mjs # 24 checks: the example game, played end to end
|
node tools/seed-jumprun.mjs && node tools/smoke-jumprun.mjs # 24 checks: the example game, played end to end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
|
import type { Asset } from '../model/Asset';
|
||||||
import { ancestorIdsOf, type ObjectTree } from '../model/hierarchy';
|
import { ancestorIdsOf, type ObjectTree } from '../model/hierarchy';
|
||||||
import { instanceTargetOf, isEmptyEdit, resolveObjects } from '../model/instance';
|
import { instanceTargetOf, isEmptyEdit, resolveObjects } from '../model/instance';
|
||||||
import { findAsset, type Project } from '../model/Project';
|
import { findAsset, type Project } from '../model/Project';
|
||||||
import type { SceneObject } from '../model/SceneObject';
|
import type { SceneObject } from '../model/SceneObject';
|
||||||
import { schemaForAsset } from './PropertySchema';
|
import { COMMON_PROPS, type PropertySchema, schemaForAsset } from './PropertySchema';
|
||||||
import { deviatesFromAsset } from './resolve';
|
import { deviatesFromAsset, isModified } from './resolve';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rows the asset inspector marks as modified. A behavior's variables are left out: their
|
||||||
|
* default is declared on the variable itself, so the asset value cannot differ from it.
|
||||||
|
*/
|
||||||
|
export function markedAssetSchema(asset: Asset): PropertySchema {
|
||||||
|
return asset.type === 'behavior' ? COMMON_PROPS : schemaForAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether any asset property the inspector would mark gold differs from its default. */
|
||||||
|
export function assetDeviates(asset: Asset): boolean {
|
||||||
|
return markedAssetSchema(asset).some((def) => isModified(asset, def.key));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether a placed object deviates from whatever it follows: the container template it was
|
* Whether a placed object deviates from whatever it follows: the container template it was
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
|||||||
dropPreview: () => viewport.dropInfo(),
|
dropPreview: () => viewport.dropInfo(),
|
||||||
/** An asset row by id – two assets can share a name with the container picker's label. */
|
/** An asset row by id – two assets can share a name with the container picker's label. */
|
||||||
assetRow: (id: string) => assets.rowGlobal(id),
|
assetRow: (id: string) => assets.rowGlobal(id),
|
||||||
|
assetRowColor: (id: string) => assets.rowColor(id),
|
||||||
gameInfo: () => gameView.debugInfo(),
|
gameInfo: () => gameView.debugInfo(),
|
||||||
layerOf: (id: string) => viewport.layerOf(id),
|
layerOf: (id: string) => viewport.layerOf(id),
|
||||||
drawOrder: () => viewport.drawOrder(),
|
drawOrder: () => viewport.drawOrder(),
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import {
|
|||||||
import type { Asset, BehaviorAsset } from '../../core/model/Asset';
|
import type { Asset, BehaviorAsset } from '../../core/model/Asset';
|
||||||
import { findAsset, type Project } from '../../core/model/Project';
|
import { findAsset, type Project } from '../../core/model/Project';
|
||||||
import {
|
import {
|
||||||
COMMON_PROPS,
|
|
||||||
type PropertyDef,
|
type PropertyDef,
|
||||||
schemaForAsset,
|
schemaForAsset,
|
||||||
VARIABLE_KINDS,
|
VARIABLE_KINDS,
|
||||||
type VariableKind,
|
type VariableKind,
|
||||||
} from '../../core/properties/PropertySchema';
|
} from '../../core/properties/PropertySchema';
|
||||||
|
import { markedAssetSchema } from '../../core/properties/deviation';
|
||||||
import { isModified, resolveAssetProps } from '../../core/properties/resolve';
|
import { isModified, resolveAssetProps } from '../../core/properties/resolve';
|
||||||
import { Button, Dropdown, HStack, Label, Menu, Spacer, TextField, Theme } from '../../ui';
|
import { Button, Dropdown, HStack, Label, Menu, Spacer, TextField, Theme } from '../../ui';
|
||||||
import { aspectActions, sizeCommand } from './aspectAction';
|
import { aspectActions, sizeCommand } from './aspectAction';
|
||||||
@@ -63,12 +63,8 @@ export function buildAssetSection(host: InspectorHost, assetId: string): void {
|
|||||||
row.add(host.nameField, 1);
|
row.add(host.nameField, 1);
|
||||||
host.body.add(row);
|
host.body.add(row);
|
||||||
|
|
||||||
if (asset.type === 'behavior') {
|
buildProps(host, asset, markedAssetSchema(asset));
|
||||||
buildProps(host, asset, COMMON_PROPS);
|
if (asset.type === 'behavior') buildVariables(host, asset);
|
||||||
buildVariables(host, asset);
|
|
||||||
} else {
|
|
||||||
buildProps(host, asset, schemaForAsset(asset));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pushes the current asset values into the rows. False when the asset is gone (rebuild). */
|
/** Pushes the current asset values into the rows. False when the asset is gone (rebuild). */
|
||||||
|
|||||||
@@ -8,13 +8,19 @@ import {
|
|||||||
isPlaceableType,
|
isPlaceableType,
|
||||||
} from '../../core/model/AssetTypes';
|
} from '../../core/model/AssetTypes';
|
||||||
import { findAsset } from '../../core/model/Project';
|
import { findAsset } from '../../core/model/Project';
|
||||||
|
import { assetDeviates } from '../../core/properties/deviation';
|
||||||
import type { TextureStore } from '../../core/store/TextureStore';
|
import type { TextureStore } from '../../core/store/TextureStore';
|
||||||
import { Button, ListView, Menu, type MenuItem, Panel, ScrollContainer, startDrag } from '../../ui';
|
import { Button, ListView, Menu, type MenuItem, Panel, ScrollContainer, startDrag } from '../../ui';
|
||||||
import { confirmDeleteAsset } from '../actions';
|
import { confirmDeleteAsset } from '../actions';
|
||||||
import type { EditorState } from '../state';
|
import type { EditorState } from '../state';
|
||||||
import { pickAndImport } from '../textureImport';
|
import { pickAndImport } from '../textureImport';
|
||||||
|
|
||||||
/** Lists all assets of the project; creates and deletes them. Placing is a drag into a view. */
|
/**
|
||||||
|
* Lists all assets of the project; creates and deletes them. Placing is a drag into a view.
|
||||||
|
*
|
||||||
|
* A row's name turns gold when the asset carries a property the inspector marks – the same rule,
|
||||||
|
* so the list cannot promise a deviation the inspector then fails to show.
|
||||||
|
*/
|
||||||
export class AssetPanel extends Panel {
|
export class AssetPanel extends Panel {
|
||||||
private readonly list = new ListView();
|
private readonly list = new ListView();
|
||||||
private readonly scroll = new ScrollContainer();
|
private readonly scroll = new ScrollContainer();
|
||||||
@@ -59,6 +65,7 @@ export class AssetPanel extends Panel {
|
|||||||
label: asset.name,
|
label: asset.name,
|
||||||
hint: asset.type === 'scene' && asset.id === active ? 'scene ●' : asset.type,
|
hint: asset.type === 'scene' && asset.id === active ? 'scene ●' : asset.type,
|
||||||
swatch: hasColorSwatch(asset.type) ? Number(asset.props.color ?? 0) : undefined,
|
swatch: hasColorSwatch(asset.type) ? Number(asset.props.color ?? 0) : undefined,
|
||||||
|
overridden: assetDeviates(asset),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
this.syncSelection();
|
this.syncSelection();
|
||||||
@@ -98,6 +105,11 @@ export class AssetPanel extends Panel {
|
|||||||
return this.list.rowGlobal(assetId);
|
return this.list.rowGlobal(assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Label colour of a row as `#rrggbb` – gold means the asset deviates from the defaults (test hook). */
|
||||||
|
rowColor(assetId: string): string | null {
|
||||||
|
return this.list.rowColor(assetId);
|
||||||
|
}
|
||||||
|
|
||||||
/** Hands the asset to the viewport under the pointer; a scene has nowhere to be placed into. */
|
/** Hands the asset to the viewport under the pointer; a scene has nowhere to be placed into. */
|
||||||
private startPlacementDrag(assetId: string): void {
|
private startPlacementDrag(assetId: string): void {
|
||||||
const asset = findAsset(this.state.project, assetId);
|
const asset = findAsset(this.state.project, assetId);
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import {
|
||||||
|
CreateAssetCommand,
|
||||||
|
ResetAssetPropertyCommand,
|
||||||
|
SetAssetPropertyCommand,
|
||||||
|
} from '../../src/core/commands/assetCommands';
|
||||||
import { CreateContainerCommand } from '../../src/core/commands/containerCommands';
|
import { CreateContainerCommand } from '../../src/core/commands/containerCommands';
|
||||||
|
import { AddVariableCommand } from '../../src/core/commands/variableCommands';
|
||||||
import {
|
import {
|
||||||
ClearOverrideCommand,
|
ClearOverrideCommand,
|
||||||
SetOverrideCommand,
|
SetOverrideCommand,
|
||||||
@@ -8,8 +14,8 @@ import {
|
|||||||
import { instanceChildId } from '../../src/core/model/instance';
|
import { instanceChildId } from '../../src/core/model/instance';
|
||||||
import { findAsset } from '../../src/core/model/Project';
|
import { findAsset } from '../../src/core/model/Project';
|
||||||
import type { ContainerAsset } from '../../src/core/model/Asset';
|
import type { ContainerAsset } from '../../src/core/model/Asset';
|
||||||
import { deviationMarks, objectDeviates } from '../../src/core/properties/deviation';
|
import { assetDeviates, deviationMarks, objectDeviates } from '../../src/core/properties/deviation';
|
||||||
import { makeSpriteScene, place } from '../helpers';
|
import { makeProject, makeSpriteScene, place } from '../helpers';
|
||||||
|
|
||||||
describe('deviation marks', () => {
|
describe('deviation marks', () => {
|
||||||
it('marks an object only once an override really deviates', () => {
|
it('marks an object only once an override really deviates', () => {
|
||||||
@@ -48,3 +54,37 @@ describe('deviation marks', () => {
|
|||||||
expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([content, create.objectId].sort());
|
expect([...deviationMarks(f.project, f.sceneOf())].sort()).toEqual([content, create.objectId].sort());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('asset deviation', () => {
|
||||||
|
const makeAsset = (type: 'sprite' | 'behavior', name: string) => {
|
||||||
|
const f = makeProject();
|
||||||
|
const create = new CreateAssetCommand(type, name);
|
||||||
|
f.stack.execute(create);
|
||||||
|
const asset = () => findAsset(f.project, create.asset.id)!;
|
||||||
|
expect(asset().type).toBe(type);
|
||||||
|
return { ...f, asset, assetId: create.asset.id };
|
||||||
|
};
|
||||||
|
|
||||||
|
it('marks an asset only once a property really differs from its default', () => {
|
||||||
|
const f = makeAsset('sprite', 'Box');
|
||||||
|
expect(assetDeviates(f.asset())).toBe(false);
|
||||||
|
// Written, but the default value – the inspector shows no gold, so neither does the list.
|
||||||
|
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'width', 100));
|
||||||
|
expect(f.asset().props.width).toBe(100);
|
||||||
|
expect(assetDeviates(f.asset())).toBe(false);
|
||||||
|
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'width', 250));
|
||||||
|
expect(assetDeviates(f.asset())).toBe(true);
|
||||||
|
f.stack.execute(new ResetAssetPropertyCommand(f.assetId, 'width'));
|
||||||
|
expect(assetDeviates(f.asset())).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('leaves a behavior unmarked for its variables, which the inspector does not mark either', () => {
|
||||||
|
const f = makeAsset('behavior', 'Mover');
|
||||||
|
f.stack.execute(new AddVariableCommand(f.assetId, 'speed', 'number'));
|
||||||
|
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'speed', 42));
|
||||||
|
expect(f.asset().props.speed).toBe(42);
|
||||||
|
expect(assetDeviates(f.asset())).toBe(false);
|
||||||
|
f.stack.execute(new SetAssetPropertyCommand(f.assetId, 'enabled', false));
|
||||||
|
expect(assetDeviates(f.asset())).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
die textfarbe beim asset soll auch in diesem gold dargestellt werden, falls ein property des assets einen override hat.
|
||||||
|
ist somit relativ simpel: im prinzip genau das checken was im inspector erscheint wenn man das asset auswählt => gibt es wo einen override (gold) dann auch den assetname links im panel gold darstellen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Umgesetzt (2026-09-09).** Der Name einer Asset-Zeile im Assets-Panel ist gold, solange das
|
||||||
|
Asset irgendeine Property traegt, die der Inspector gold malen wuerde — dieselbe Farbe und
|
||||||
|
dasselbe Kriterium wie in der Hierarchie.
|
||||||
|
|
||||||
|
Die Regel steht als reine Funktion in `src/core/properties/deviation.ts`, neben dem schon
|
||||||
|
vorhandenen `objectDeviates`:
|
||||||
|
|
||||||
|
- `markedAssetSchema(asset)` — die Zeilen, die der Asset-Inspector als "modified" markiert.
|
||||||
|
- `assetDeviates(asset)` — ob davon eine von ihrem Schema-Default abweicht (`isModified`).
|
||||||
|
|
||||||
|
**Panel und Inspector benutzen dieselbe Liste**, statt die Bedingung zweimal zu formulieren:
|
||||||
|
`buildAssetSection` baut seine Property-Zeilen jetzt aus `markedAssetSchema(asset)` (das ersetzt
|
||||||
|
die Fallunterscheidung Behavior/Rest, die dort vorher stand). Damit kann die Liste keine
|
||||||
|
Abweichung behaupten, die der Inspector danach nicht zeigt.
|
||||||
|
|
||||||
|
**Ein Sonderfall, der eine Entscheidung brauchte: die Variablen eines Behaviors.** Sie sind Teil
|
||||||
|
von `schemaForAsset`, aber der Inspector markiert sie bewusst nie (`setModified` ist dort ein
|
||||||
|
No-op) — ihr Default ist auf der Variablen selbst deklariert, der Asset-Wert *ist* dieser
|
||||||
|
Default. Ein Behavior mit `speed = 200` ist deshalb nicht gold. Sonst waere im E2E-Fixture der
|
||||||
|
"Mover" gold gewesen, ohne dass der Inspector irgendwo etwas markiert haette — genau der
|
||||||
|
Widerspruch, den die Notiz ausschliesst.
|
||||||
|
|
||||||
|
**Belegt** (E2E-Modul 04, sechs neue Checks ueber den Test-Hook `__gm.assetRowColor`, der die
|
||||||
|
tatsaechliche Label-Farbe der Zeile liest):
|
||||||
|
|
||||||
|
- Crate (Hoehe 60 statt 100, eigene Farbe) → `#f2c84b`, Main camera (alles auf Default) → `#e6e8ee`
|
||||||
|
- Mover (Variable `speed` = 200 gegen deklarierten Default 0) → `#e6e8ee`, wie der Inspector
|
||||||
|
- ein ↺ zurueckgesetzt → bleibt gold, weil die zweite Abweichung noch steht
|
||||||
|
- die zweite auch zurueckgesetzt → wird schlicht, **ohne Reload**; Undo bringt die Marke zurueck
|
||||||
|
|
||||||
|
Screenshot `15-asset-reset`: im Panel sind "Level 1" (Hintergrundfarbe), "Crate" und
|
||||||
|
"Crate collider" gold, "Main camera", "Mover", "Spawner" und das frisch angelegte "Sprite" weiss.
|
||||||
@@ -1 +0,0 @@
|
|||||||
die textfarbe beim asset soll auch in diesem gold dargestellt werden, falls ein property des assets einen override hat
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Zitat aus der readme: "Unreferenced image files are never collected."
|
||||||
|
|
||||||
|
Ich würde sagen dass soll vorerst auch so bleiben.
|
||||||
|
|
||||||
|
Was passt:
|
||||||
|
drag and drop file in den editor => textur wird hochgeladen und passende asset wird erstellt => das soll so bleiben, das passt
|
||||||
|
|
||||||
|
Was wir auch haben aber ändern:
|
||||||
|
klickt man auf das `+` => `Texture`, dann öffnet sich der File System Browser.
|
||||||
|
|
||||||
|
Anstelle des file system browser => ein dialog mit allen images die am server existieren.
|
||||||
|
- auswählen => ok, dann wird es wiederverwendet => dialog schließt sich => texture asset mit ausgewählten image wird erstellt.
|
||||||
|
- oder hochladen button => file system browser => OK => dialog schließt sich => texture asset mit hochgeladenen image wird erstellt (im prinzip das was wir jetzt auch haben)
|
||||||
|
|
||||||
@@ -143,4 +143,42 @@ export async function assets(t) {
|
|||||||
(await evaluate(`__gm.locate('↺')`))?.y === heightReset.y,
|
(await evaluate(`__gm.locate('↺')`))?.y === heightReset.y,
|
||||||
JSON.stringify(await evaluate(`__gm.locate('↺')`)),
|
JSON.stringify(await evaluate(`__gm.locate('↺')`)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 12b. The same gold in the asset list: a row is marked while the asset carries anything the
|
||||||
|
// inspector marks. The Crate deviates twice, so it takes two resets to turn it plain.
|
||||||
|
const GOLD = '#f2c84b';
|
||||||
|
const PLAIN = '#e6e8ee';
|
||||||
|
const assetColor = (id) => json(`__gm.assetRowColor('${id}')`);
|
||||||
|
check('a deviating asset is marked gold in the list', (await assetColor('crate')) === GOLD);
|
||||||
|
check('an asset at its defaults is not', (await assetColor('cam')) === PLAIN, await assetColor('cam'));
|
||||||
|
// The Mover's `speed` is 200 against a declared variable default of 0. The inspector marks no
|
||||||
|
// variable, so neither may the list – the two must say the same thing.
|
||||||
|
check(
|
||||||
|
'a behavior is not marked for a variable value, which the inspector does not mark either',
|
||||||
|
(await assetColor('mover')) === PLAIN,
|
||||||
|
await assetColor('mover'),
|
||||||
|
);
|
||||||
|
await click(heightReset.x, heightReset.y);
|
||||||
|
await sleep(150);
|
||||||
|
check(
|
||||||
|
'the mark stays while the second deviation is left',
|
||||||
|
(await assetColor('crate')) === GOLD,
|
||||||
|
await assetColor('crate'),
|
||||||
|
);
|
||||||
|
const colorOnly = await evaluate(`__gm.locate('↺')`);
|
||||||
|
await click(colorOnly.x, colorOnly.y);
|
||||||
|
await sleep(150);
|
||||||
|
check(
|
||||||
|
'resetting the last deviation clears the mark, without a reload',
|
||||||
|
(await assetColor('crate')) === PLAIN,
|
||||||
|
`${await assetColor('crate')} props=${JSON.stringify((await asset('crate')).props)}`,
|
||||||
|
);
|
||||||
|
await shot('15b-asset-marks');
|
||||||
|
await undo();
|
||||||
|
await undo();
|
||||||
|
check(
|
||||||
|
'undo brings the mark back',
|
||||||
|
(await assetColor('crate')) === GOLD,
|
||||||
|
`${await assetColor('crate')} props=${JSON.stringify((await asset('crate')).props)}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user