Typed lists: struct type for list items, Add/Set item with Type (#254)
1 parent
2a1ce85981
commit
d4f6ca3e98
3 files changed
+70
-14
No files matched your search
+5
-2
@@ -156,10 +156,13 @@ playing use the same two words.
|
||||
`Select` (`true` if the condition holds, else `false` — the same action with one of two values,
|
||||
such as a walk or an idle animation for one `Play animation`; `Branch` is for two different actions),
|
||||
lists `List` (a constant), `Fill` (one value repeated — how an empty board is made), `Count`,
|
||||
`Item at`, `Set item` (a *new* list, the one that came in is left alone), `Add item` (a new
|
||||
`Item at`, `Set item` (a *new* list, the one that came in is left alone; with a **Type** it
|
||||
sets only a struct with exactly that struct asset's fields, like `Add item`), `Add item` (a new
|
||||
list with `value` as exactly one more item: a struct or a list goes in whole, where `Join lists`
|
||||
would take it apart; at the end, or before `index`, and an index outside the list appends;
|
||||
the item takes the kind the list's items share, like `Set item`), `Sub list`,
|
||||
the item takes the kind the list's items share, like `Set item`; with a **Type** it adds only a
|
||||
struct with exactly that struct asset's fields and reports anything else in the console, see
|
||||
[Structs](Structs)), `Sub list`,
|
||||
`Join lists`, `Index of` (by identity where the items are objects), structs `Pack`/`Expand`,
|
||||
`Length`, `Distance`, `Normalize`, `Axis input` (four keys → a
|
||||
normalized direction, so diagonals are not faster), `Compare` (two numbers count as equal up to
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ npm run build # writes dist/ and regenerates index.html
|
||||
php tools/make-user.php <name> <password> [admin|user] # an account; every tool signs in (see Accounts)
|
||||
php tests/php/accounts.test.php # the API's account rules, no server needed (CI's gate job)
|
||||
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1500 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1513 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||
./e2e.sh status # live progress, or the last run's result
|
||||
|
||||
+64
-11
@@ -61,23 +61,63 @@ takes all of it back:
|
||||
This also works through several levels: if `Chest` holds a `Loot` and a variable holds a `Chest`, a
|
||||
field renamed on `Loot` is renamed inside that variable's value too.
|
||||
|
||||
## Typed lists
|
||||
|
||||
A list says nothing about its items by default: each item carries its own kind, and a struct item
|
||||
its own fields. Such a list is **mixed**. A list can also be **typed**: every item is then one
|
||||
struct asset.
|
||||
|
||||
Every list variable, and every list field inside a struct, has an **Items** row under its head. It
|
||||
reads **Mixed** until you pick a type. Its menu offers:
|
||||
|
||||
- **Mixed** — the list declares nothing again. Its items keep their type each (see below), so
|
||||
nothing is lost.
|
||||
- **every struct asset** — every item takes on that asset's fields, keeping what it holds under the
|
||||
same name and taking the default for the rest, exactly like a struct given a type. A list that
|
||||
holds **anything but structs** (a number, a text, a list) cannot take a type: the edit is refused
|
||||
and the console says how many items are in the way. Placed objects count too — an override
|
||||
holding a number refuses the type as well.
|
||||
- **Make struct type** — makes a new struct asset out of the list's items and types the list with
|
||||
it. The asset gets **every field any item has**, at the value of the first item that has it, so
|
||||
no item loses a field.
|
||||
|
||||
In a typed list:
|
||||
|
||||
- **+ Item** adds an item of the type at its defaults straight away. There is no kind to pick.
|
||||
- The items' fields are the type's: their names cannot be changed, and there is no **+ Field** and
|
||||
no remove button on a field. The **values** are edited as before.
|
||||
- A list field of the type is typed through it: if `Bag` has a list `inside` of `Loot`, the `inside`
|
||||
of every `Bag` item is a typed list of `Loot` too.
|
||||
|
||||
### A type for one item
|
||||
|
||||
In a **mixed** list, every struct item has a **Type** row of its own, as does a struct field inside
|
||||
such an item. Pick a struct asset there, and that one item takes on its fields and follows it, while
|
||||
the other items stay as they are. **Own fields** turns it back.
|
||||
|
||||
### When the asset changes
|
||||
|
||||
Typed items follow their asset like every other place of that type — the table above applies to
|
||||
them too: a field added, removed or renamed reaches every typed item, in the list's own value, in
|
||||
the overrides of placed objects and in lists nested inside other items, in one undo step.
|
||||
|
||||
## Deleting a struct asset
|
||||
|
||||
The delete dialog counts the structs and `Pack`/`Expand` nodes that use it. After deleting, each of
|
||||
them **keeps the fields it last had**, now as its own fields — no value is lost, only the link. Its
|
||||
Type row reads **Own fields** again.
|
||||
The delete dialog counts the structs, the typed lists and the `Pack`/`Expand` nodes that use it.
|
||||
After deleting, each of them **keeps the fields it last had**, now as its own fields — no value is
|
||||
lost, only the link. A Type row reads **Own fields** again, an Items row **Mixed**.
|
||||
|
||||
## In the running game
|
||||
|
||||
Nothing changes there. A struct value is the same plain bundle of fields, with or without a type:
|
||||
the type does not travel with the value, so `Equals`, `Index of`, saving and loading treat it as
|
||||
before. Edges do not check the type either — any struct fits any struct port.
|
||||
A struct value is the same plain bundle of fields, with or without a type: the type does not travel
|
||||
with the value, so `Equals`, `Index of`, saving and loading treat it as before. Edges do not check
|
||||
the type either — any struct fits any struct port.
|
||||
|
||||
## What it does not do (yet)
|
||||
|
||||
Lists stay **untyped**: a list of structs still takes each item's shape from the item itself, and
|
||||
**+ Item → Struct** starts an empty struct. Typed lists, where every item is one struct type, are
|
||||
[issue #254](https://git.nockal.com/meleki/game-maker/issues/254).
|
||||
The places that check are **Add item** and **Set item**, each with its **Type** setting. With a
|
||||
type they take a value only if it is a struct with **exactly** the type's field names — none
|
||||
missing, none more. Anything else is not added or set: the list comes out as it went in, and the
|
||||
console names the value and the type. An item taken out of a typed list, and a `Pack` with the same
|
||||
type, always fit. Without a type (or with one that was deleted) both take anything, as before.
|
||||
|
||||
## Under the hood
|
||||
|
||||
@@ -89,3 +129,16 @@ project is loaded, so a hand-edited file heals too. Its writes go through a `Rec
|
||||
(`src/core/util/recorder.ts`), which is what makes an edit of unknown reach one undo step. A struct
|
||||
asset declares its fields as `variables`, so the variable commands and the inspector's variable
|
||||
rows edit them unchanged.
|
||||
|
||||
A list declares nothing about its items, so an item carries its type itself: a typed list names the
|
||||
asset in `itemType`, and every struct item in it holds the asset's id under the key `$struct`. A
|
||||
struct item with a type of its own in a mixed list holds the same key. No field can have that name,
|
||||
since field names never start with `$`. The same sync brings every marked item into shape, wherever
|
||||
it sits. A run never sees the key: it is taken out where values enter the game
|
||||
(`withoutItemTypes` in `src/core/model/Properties.ts`), which is why `Add item` and `Set item` can
|
||||
compare field names exactly.
|
||||
|
||||
A typed item keeps a field's value as plain JSON, the way a declared struct does: an asset id or a
|
||||
texture id is a text, a color a number. What kind a field is comes from the type, so the item rows
|
||||
draw each field as the type declares it — an asset field with its asset menu, not as the text it
|
||||
holds.
|
||||
Reference in new issue
Block a user