diff --git a/Architecture.md b/Architecture.md index 7693cbf..d0f1d32 100644 --- a/Architecture.md +++ b/Architecture.md @@ -144,6 +144,8 @@ src/editor/ App → Editor (layout + ticker), PlaySession (the run), EditorRun (run in editor), state, actions, shortcuts, clipboard (#240: copy and paste of objects and graph pieces — where a paste lands, into which parent, what a graph may take; the snapshot is `core/model/clipboard`, the paste `core/commands/pasteCommands`), + objectGroups (#241: the group entries of the object menu and the group row's menu; + the commands are `core/commands/groupCommands`), debugHook (installs `window.__gm`; the hooks are grouped by area in debug/: ui, scene, graph, documents, pixel art, vector art, render — `tools/` sees one flat object as before), @@ -194,7 +196,8 @@ src/editor/inspector/ Inspector panel, host (what a section builds into), field 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), - assetMenu (the two groups of the + menu), HierarchyPanel, + assetMenu (the two groups of the + menu), HierarchyPanel + hierarchyDrop (#241: what + dropping a row does, group rows included) + GroupNameDialog, Toolbar + toolbarIcons (icon buttons, no captions: menu, undo, redo, play, pause, #183, and the eye), SceneVisibilityPopup (behind the eye: symbol, name and collider outline per type), headerIcons (the pictures of the tab headers' switches: the magnet, #194), diff --git a/Development.md b/Development.md index f7e1ec9..2526aef 100644 --- a/Development.md +++ b/Development.md @@ -15,7 +15,7 @@ npm run build # writes dist/ and regenerates index.html php tools/make-user.php [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 # 1432 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1442 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 diff --git a/Scene-editing.md b/Scene-editing.md index 64e330b..46cf779 100644 --- a/Scene-editing.md +++ b/Scene-editing.md @@ -149,6 +149,39 @@ unfolds the way down to it and scrolls it into view, so a selection is never hid 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. +**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 +they are, and the game never sees it. Select one or more top-level objects, right-click → +**Group…**, name it; the row shows a folder, the name and the number of members, the members +indented below it and their own children one step further in. Only top-level objects go in: the +entry is greyed out as soon as a child is selected, and an object put under a parent leaves its +group. There are no groups inside groups. + +- **Clicking the group row selects all members**, so they move together in the view; Ctrl-click + adds or takes them off the selection. A group whose members are all selected stays folded; one + selected member alone unfolds it, like a parent. +- **A plain click on a row that is already selected** along with others keeps only that row + selected, a member of a group included. The press alone changes nothing yet, the release does, so + a drag that starts there leaves the selection as it was. +- **Dragging** an object onto the group row puts it in behind the last member; dropping it into + the gap between two members puts it there, dropping it beside a row outside the group takes it + out. The group row itself drags as one block between top-level rows. +- **The group row's menu** has *Select members*, *Rename…* and *Ungroup* (the members stay). + The object menu adds *Remove from group*. Grouping, renaming, ungrouping and moving in or out + are one undo step each. +- **Order:** a group is listed where its first member stands, with the others moved up behind it. + That listed order is also the order equal `z` is drawn in (`groupedOrder` in + `src/core/model/hierarchy.ts`), in the editor and in the game, so the list never shows a + different order than the one drawn. Grouping objects can therefore change which of two objects + at the same `z` is in front. +- Which groups are open is view state like a folded parent: a reloaded scene starts folded. +- A copy pasted at the top level of the same scene lands in its original's group. A container made + from members of one group takes their place in it; its template has no groups of its own. A + container tab can group its template's top level the same way, and a placed container shows + its content in that order. +- Stored as `groups: [{ id, name }]` on the scene or container and `groupId` on the object; a + group left without members disappears from the list and is dropped on the next load. + **The object menu in the view.** Right-clicking an object in the scene view opens the same menu its row in **Scene objects** has (#204) — one function builds both (`src/editor/objectMenu.ts`), so they cannot drift apart. Only *Expand all* / *Collapse all* stay in the panel, where they mean