Describe sprite preview, machine ports and shared local machines
The wiki catches up with the last four commits in the code repo. - Concepts: new paragraph Sprite preview. Architecture lists SpritePreview.ts and previewFit.ts. - State-machines: a Start input or a Variables node can name the machine it carries. A called behavior now shares the caller's local machines instead of starting empty. - Behaviors: the warning at Run behavior for a different machine, the shared local machines and Get world position in the data nodes. - Scene-editing: a half sentence on Get world position. - Development: e2e sum 1744. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent
1d9e589d07
commit
70697cce9a
6 files changed
+41
-15
No files matched your search
+3
-1
@@ -281,7 +281,9 @@ src/editor/inspector/ Inspector panel, host (what a section builds into, and `e
|
||||
every variable), shapeSection (the shapes of a vector drawing: the list, the four order
|
||||
buttons and the style of the picked one, #129; Fill type and Line type with the stop bar,
|
||||
the picked stop's rows or the texture, #186), portSection, aspectAction,
|
||||
objectQueries/vectorRows/parentRow, cutSection (the Nine-slice and Sorting rows, shared by the frame and the drawing inspectors, #308)
|
||||
objectQueries/vectorRows/parentRow, cutSection (the Nine-slice and Sorting rows, shared by the frame and the drawing inspectors, #308),
|
||||
SpritePreview (a sprite as `syncSpriteMesh` draws it in the scene) + previewFit (whole device
|
||||
pixels per unit, the corner on one)
|
||||
src/editor/panels/ AssetPanel, assetGroups (groups by type and their order, #176), assetIcons (one SVG per
|
||||
asset type in icons/, shared by the panel, the + menu, the tabs and Scene objects,
|
||||
plus the List, Game, Plugins and User management tabs' own four, which stand for no asset),
|
||||
|
||||
+8
-4
@@ -220,7 +220,7 @@ the inspector).
|
||||
the given object, nearer levels first, the order `Child by name` searches in), `Children` (the
|
||||
children of an object; with **recursive** every object below it, level by level) and
|
||||
`Objects of asset` (every instance of the chosen asset, spawned ones included),
|
||||
`Variables`, `Properties` (every property row of the target's type, the transform rows `scale`, `rotation`, `mirrorX`, `mirrorY` included — how a graph turns a sprite), `Get position` (local and world), `Get Z` (the object's own `z` and `world z`, summed up with its parents'), `Is enabled`, literals `Number`/`Text`/`Boolean`/`Texture`/`State machine`/`Sound`/`Scene`/`Animation`/`Asset`, `Texture size` (a texture's, frame's or pixel art's own size in pixels, 0 for none — wired into a sprite's `width`/`height`, a picture shows pixel for pixel), `Add/Subtract/Multiply/Divide`,
|
||||
`Variables`, `Properties` (every property row of the target's type, the transform rows `scale`, `rotation`, `mirrorX`, `mirrorY` included — how a graph turns a sprite), `Get position` (local and world), `Get world position` (only the world `x`/`y`), `Get Z` (the object's own `z` and `world z`, summed up with its parents'), `Is enabled`, literals `Number`/`Text`/`Boolean`/`Texture`/`State machine`/`Sound`/`Scene`/`Animation`/`Asset`, `Texture size` (a texture's, frame's or pixel art's own size in pixels, 0 for none — wired into a sprite's `width`/`height`, a picture shows pixel for pixel), `Add/Subtract/Multiply/Divide`,
|
||||
`Min/Max/Abs/Sqrt/Clamp`, `Lerp` (from a to b as t runs from 0 to 1, t held in 0…1; the setting
|
||||
*Ease* bends the way: *Linear*, *In* starts slow, *Out* ends slow, *In-out* both, all quadratic,
|
||||
or *Curve*, which follows the [curve asset](Curves) picked in the *Curve* row and may overshoot b;
|
||||
@@ -372,7 +372,8 @@ the inspector).
|
||||
removing takes the edges hanging on it in *every* graph that calls the behavior. A call is a
|
||||
**call, not an inlining**: the nested graph runs in its own pulse cache with a fresh copy of its
|
||||
variable defaults, so values travel in and out through the ports and nothing else. That makes a
|
||||
call repeatable and keeps a nested behavior free of hidden state. A behavior that would run
|
||||
call repeatable and keeps a nested behavior free of hidden state. The one exception are local
|
||||
state machines, which belong to the instance running the call (see *Keep* below). A behavior that would run
|
||||
itself raises an error instead of looping; there is one start and one end node per behavior.
|
||||
A behavior **without a start node** is called from its **On start** nodes instead, all of them in
|
||||
graph order, as when it starts on its own. It takes no inputs then, but its end node still hands
|
||||
@@ -427,7 +428,8 @@ the inspector).
|
||||
a call inside a call has one per outer node. It follows today's declarations: a variable added
|
||||
since starts at its default, a removed one is dropped, and one whose kind changed starts over.
|
||||
The kept value lives as long as the object does in the run and is never saved. Local state
|
||||
machines of the called behavior are not kept, they start in no state every call. For state
|
||||
machines need no Keep: a call reads and moves the states of the instance running it, so they
|
||||
carry over from call to call anyway (see *State machines*). For state
|
||||
shared between objects, use a Variables asset or a behavior object in the scene (see
|
||||
*Cross-object state* below).
|
||||
Three ways in and out of a call: **drag** a behavior out of the asset panel onto the graph and it
|
||||
@@ -437,7 +439,9 @@ the inspector).
|
||||
stays in the same tab, and the trail belongs to that tab: a behavior opened any other way comes
|
||||
up in a tab of its own, without a trail, and switching back brings the trail back with it. And a call that cannot
|
||||
do anything **says so on the node** — no behavior picked, the behavior deleted,
|
||||
or neither a start node nor an On start in it. The last one is the one worth naming: without
|
||||
or neither a start node nor an On start in it. It also warns when a State machine input is set
|
||||
to another machine than the one its Start input carries (see *State machines*). The missing
|
||||
start is the one worth naming: without
|
||||
either there is no way in, so the call is skipped and the flow simply carries on at its `exec` output. A missing
|
||||
*end* node is not a defect — a call is always synchronous, "done" is the nested flow running out,
|
||||
and the end node only decides what comes back.
|
||||
|
||||
+7
@@ -288,6 +288,13 @@ without rows is left out.
|
||||
with a header of its own (*Layers*, *Frames*, *Shapes*) folds with a click on that header, clear
|
||||
of its plus, and takes the notes and buttons under it along.
|
||||
|
||||
**Sprite preview.** A sprite, placed or as an asset, ends its inspector with a **Preview** group:
|
||||
the sprite as the scene draws it, with its picture or frame, nine-slice, tint and shader, on the
|
||||
scene's background. A placed sprite shows its own overrides. An edit shows at once, also while a
|
||||
value is dragged, and a shader with a Time node keeps moving while the group is open. The picture
|
||||
is fitted into the group and magnified by whole device pixels at most 8 times, so pixel art stays
|
||||
sharp; a sprite larger than the group is shrunk to fit.
|
||||
|
||||
The asset panel and **Scene objects** share the left column; the divider between them drags
|
||||
the height from one to the other, and dragged all the way either keeps its header. The split is a
|
||||
share of the column, so a taller or shorter window keeps it.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun
|
||||
# has and the web server's container has not (SKIP there)
|
||||
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
||||
php tests/php/releases.test.php # the release store (#266), the same way
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1742 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1744 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
|
||||
|
||||
+2
-1
@@ -179,7 +179,8 @@ scene opens fully collapsed — which rows are open is view state of the panel,
|
||||
the project — and selecting an object anywhere (viewport, `Add collider…`, `Create container`)
|
||||
unfolds the way down to it and scrolls it into view, so a selection is never hidden. In
|
||||
play mode entities carry the same `parent` link: moving a parent entity moves its subtree,
|
||||
`Destroy` removes it. `Get position` exposes both the local and the world coordinates.
|
||||
`Destroy` removes it. `Get position` exposes both the local and the world coordinates,
|
||||
`Get world position` only the world ones.
|
||||
|
||||
**Groups in the hierarchy (#241).** A group is a folder for top-level objects — 100 crates under
|
||||
one foldable row, say. It is editor looks only: parents, positions and behaviors stay exactly as
|
||||
|
||||
+20
-8
@@ -95,15 +95,25 @@ state lives in the *machine* — so nothing cleans up there, and the edge stays
|
||||
lost, though: the behavior's node shows the key as a **ghost port** with the edge dashed in the
|
||||
warning colour, and *Disconnect* on its right-click menu removes it. Put the state back and the
|
||||
edge works again. Which machine the
|
||||
ports belong to is read off the graph, not off a running value — the inline pick, or a
|
||||
`State machine` literal wired in; a variable or an `Item at` feeding the input yields no state
|
||||
ports, exactly as `Run behavior` knows its behavior only as a setting. That machine is still not
|
||||
ports belong to is read off the graph, not off a running value — the inline pick, a
|
||||
`State machine` literal wired in, or an input of the behavior's **Start** node of the kind
|
||||
State machine with a machine picked next to its name in the inspector. A variable of that kind
|
||||
read by a `Variables` node works the same way: the machine is picked next to the variable's row.
|
||||
The pick only names the states, the value the variable holds at run time is not checked against
|
||||
it. An `Item at` or anything else feeding the input yields no state ports, exactly as
|
||||
`Run behavior` knows its behavior only as a setting. That machine is still not
|
||||
stuck: `Set state by name` names the state as text, `State branch` leaves along `else`, and
|
||||
`Current state` answers as always. The price is spelled out, not hidden — a name is typed, so a
|
||||
typo is possible where a port made it impossible, which is what `not found` is there for.
|
||||
Picking another machine
|
||||
orphans the edges of the old states, the way any setting that decides a node's ports does.
|
||||
|
||||
A Start input with a machine picked has that machine **picked in advance** on every node running
|
||||
the behavior. Another pick there is allowed, but the node warns (`"machine" expects "Doors"`):
|
||||
the called graph asks for the states of its own machine, so with another one every state would
|
||||
read as never entered. A **local** machine handed in is the caller's: the called graph reads and
|
||||
moves the very state the calling instance holds (see *The current state while playing* below).
|
||||
|
||||
Two more read it as **data** rather than as a flow, both pure readers (no exec ports, answered
|
||||
whenever they are asked):
|
||||
|
||||
@@ -148,9 +158,9 @@ The rules, all of them worth knowing before wiring a graph on them:
|
||||
whose events keep moving the machine stops the run with an endless-loop error, like the step limit.
|
||||
- Who hears it follows the **scope**: a local machine is heard by the instance that moved it alone,
|
||||
a global one by **every** instance with a matching event node — which is the point of sharing a
|
||||
state. A move a nested `Run behavior` makes to a *local* machine dies with the call and is not
|
||||
reported, even where the called behavior keeps variables (see *Behaviors*); a move it makes to a
|
||||
global one is a move like any other.
|
||||
state. A move made inside a `Run behavior`, however deep, counts as a move of the instance that
|
||||
runs the call: its own `On state entered` and `On state exited` hear it. The event nodes of the
|
||||
called graph itself stay silent, like every event there.
|
||||
|
||||
## The current state while playing
|
||||
|
||||
@@ -164,8 +174,10 @@ gone the moment the run stops. Play repaints the tab the way it repaints the Beh
|
||||
|
||||
**A local machine's current state is the behavior instance's own**, kept beside its variables
|
||||
(`NodeContext.states`, machine id → state id): two crates running the same behavior are in
|
||||
states of their own, and a behavior run through `Run behavior` starts in no state,
|
||||
and again with every call. A **global** one is kept for the run instead (`SharedState.states`, built
|
||||
states of their own. A behavior run through `Run behavior` has no states of its own: it reads and
|
||||
moves those of the instance that runs the call, however deep, so a state one call sets is still set
|
||||
in the next one, and the call begins in the start state like the instance does. Two characters
|
||||
running the same behavior therefore stay apart, each with its calls. A **global** one is kept for the run instead (`SharedState.states`, built
|
||||
once per run in `core/graph/sharedState.ts`) and every instance reads and moves that one — which
|
||||
bag a node touches is decided by the machine's scope, not by the node (`stateBag`). Neither
|
||||
survives a stop: both begin the next Play at the start state again, or in no state where there is
|
||||
|
||||
Reference in new issue
Block a user