Commit Graph
3 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 f84defb9b6 Pick an object of the same scene for an Object variable (#258)
game-maker / gate (push) Successful in 3m32s
game-maker / suite (push) Failing after 10m2s
An Object variable could only be set by a graph while the game runs.
A placed object always showed "(null)", although the other objects of
its scene are there to choose from and the runtime can already find
any object by its id. Now the placed object stores a reference to one
of them, and the running game turns it into the real object.

- Stored as {"$object": "<id>"}. The empty placeholder stays as it
  was, so old projects load unchanged and empty still means "(null)".
- The row of an Object variable on a placed object is a dropdown with
  None and every object of the scene, indented like the Hierarchy.
  The same goes for Object fields in structs and Object items in
  lists, also in the Variables and List tabs.
- The behavior asset keeps "(null)". An asset has no scene, so "Apply
  to asset" is gone from Object rows.
- The runtime resolves the reference when the Variables or Properties
  node reads it. A destroyed target reads as null, a missing one shows
  "(missing)" in the row.
- Inside a container only objects of the same container are offered.
  The reference keeps the template id, so every placement finds its
  own copy.
- Deleting the target clears the reference in the same undo step.
  Paste points references inside the pasted group at the copies and
  leaves outside references alone. Create container and Unpack carry
  references along with the new ids.
- A value a graph writes while running stays in the run. The scene
  keeps the picked object, also in "Run in editor".

Found on the way:

- Setting an override coerced every object slot to empty, in plain
  values, struct fields and list items. The shared objectPlace() now
  keeps the reference.

Not done:

- No eyedropper to pick in the scene, the dropdown is enough for now.
- Deleting a template object in the container editor does not clean up
  references in other scenes. They read as null there.

Tests:

- ./check.sh: 187 files, 2724 tests, CHECK EXIT 0
- e2e 1-9, 51, 57: ALL PASSED, 389 checks
- e2e 1, 57 on the final bundle: ALL PASSED, 17 checks
- 13 unit tests in object-references.test.ts, 5 checks in e2e 57
- Counter-checks: 8 unit breaks fail their tests, the browser break
  without a pick list fails 57b-57d

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:35:17 +02:00
adminandClaude Opus 5.5 61bbb96a96 Define a struct once as an asset and reuse its shape (#253)
game-maker / gate (push) Successful in 3m30s
game-maker / suite (push) Successful in 10m33s
A struct used to declare its fields wherever it stood. The same shape
in two variables meant typing it twice, and Pack/Expand copied it once
without staying in sync. A Struct asset now holds the shape in one
place, and every struct that picks it as its type follows it.

- New asset type "Struct" (not placeable, group Structs, own icon).
  The inspector shows its fields with name, kind and default value,
  and "Open" shows them in the variables tab.
- Struct variables and struct fields get a Type row: own fields, any
  Struct asset, or "Make struct type". With a type the fields come
  from the asset and cannot be added, renamed or removed there. The
  values stay per variable, overrides on placed objects still work.
- Pack and Expand get the setting Type. With a type their ports are
  the fields of the asset and read-only in the inspector.
- A change to the asset reaches every typed place in one undo step
  (syncStructTypes). A new field arrives with its default. A removed
  field goes along with its port, edge and typed value. A renamed
  field keeps its value in variables, overrides and on ports with
  edges, also through nested types.
- Undo for these edits records plain assignments (Recorder), because
  the reach of a change is not known in advance.
- Cycles such as Loot in Loot, also through another type, are refused
  and not offered in the picker.
- Deleting the asset names how many places use it. Afterwards each
  place keeps its fields as its own.
- Loading reshapes a stale copy in a project file to its type.
- "Make struct type" creates an asset from an existing struct and
  links the place to it.

Differs from the plan:

- A changed default value applies to new fields and newly typed
  places only. Existing values stay.
- Removing a single field shows no warning. Undo brings it back.

Typed lists are left for #254. Lists stay dynamic for now.

Found by e2e: after deleting or renaming the type the inspector did
not rebuild and kept showing the old name. Fixed, the check was red
before.

Tests:
- ./check.sh: 182 files, 2661 tests, CHECK EXIT 0
- GM_STEPS=1,4,21,22,54: ALL PASSED, 176 checks
- 14 unit tests in tests/core/struct-types.test.ts
- New e2e module 54 with 14 checks, real mouse. Module 04 counts
  23 asset types.
- Counter-probes: without the rename pass 4 unit tests fail, without
  reshaping values 8, without the cycle rule 1. In the browser,
  without spreading changes and with + Field despite a type, 3
  checks fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 06:04:40 +02:00
adminandClaude Opus 5.5 4857bb75e6 Show lists in the inspector and variables in their own tab (#252)
game-maker / gate (push) Successful in 3m24s
game-maker / suite (push) Successful in 10m22s
The List tab could show one list at a time and was the only place to
see its items. A list now shows its items right where it lives, and a
new Variables tab shows all variables of an asset or placed object.

- InlineList draws the items of a list under its row in the inspector,
  in struct fields and in the Variables tab. A list inside a list or a
  struct field is drawn the same way, one step indented.
- The index column is the indent. Items sit under their list without an
  own margin, and the index column is 16 px wide instead of 28 px.
- Above 20 items (INLINE_LIMIT) the rest collapses into "... N more -
  open in tab". During a run the rows show the values from the game.
- ListHead puts "N items" and "+ Item" in one row. "N items" opens the
  list in a tab. A separate Open button squeezed the counter to zero
  width in the narrow inspector column.
- VariablesEditor shows every variable of a behavior asset, a variables
  asset or a placed behavior. On an asset it edits the declarations. On
  a placed object an edit only overrides that object, with the usual
  reset and push buttons.
- Opening a list inside a tab adds a new tab and keeps the open one.
  valuesKey gives each list its own document, so a list that is already
  open is shown instead of opened twice.
- Titles read "Pickup · Variables" or "Listy · nums · [3]". The tab
  closes when its asset or object is deleted.
- Lists on node inputs stay inline only, a node owns no variables.
- The List tab, ListEditor and the __gm.list hook are gone.

Tests:
- ./check.sh: 181 files, 2645 tests, CHECK EXIT 0
- GM_STEPS=1,21,22,32: ALL PASSED, 123 checks
- e2e 21 is rewritten for inline lists and the new tab, 22 and 32 are
  adapted. Sum in README: 1486 (+6 in 21, -1 in 22), counted by hand.
- Counter-probes fail as expected: sub-lists not told apart (1 unit
  test), sub-list replacing the open tab, all items drawn inline (60
  rows instead of 20), no live values (0 rows at 24 items in a run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:56:21 +02:00