Describe copy and paste of objects and nodes (#240)

- Scene editing: new section on Ctrl+C/Ctrl+V, where a paste lands
  and under which parent.
- Behaviors: a point on copying nodes and what the palette filter
  leaves out.
- Keyboard: Ctrl+C/Ctrl+V per tab and the picture import.
- Architecture: clipboard snapshot and paste commands.
- Development: e2e check total 1432.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-09-27 00:25:59 +02:00
1 parent c7ec2ba816
commit 79c3b3ef53
5 files changed
+38 -5

No files matched your search

+4 -1
@@ -141,7 +141,10 @@ src/editor/ App → Editor (layout + ticker), PlaySession (the run),
snapshot may be made: only with everything saved, #231),
ProjectSettingsDialog + settingsChanges (name, the start-scene switch and the collision
layers in one dialog; the pure rule of what Apply has to carry out),
EditorRun (run in editor), state, actions, shortcuts, debugHook (installs `window.__gm`;
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`),
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),
textProbe (finding widgets by their text — the ground floor of the test hook, shared with the sign-in screen),
+8
@@ -314,6 +314,14 @@ playing use the same two words.
(types are checked; a data input holds one link and is replaced), drag nodes, right-click a
node or port to delete/disconnect, `Delete` removes the selection, wheel zooms. Everything is
undoable.
- **Copy and paste** (#240) works in every graph (behavior, state machine, shader, particles):
`Ctrl+C` or right-click → *Copy* takes the selected nodes, the links between them and the
groups and comments selected with them. `Ctrl+V` pastes under the pointer, or one grid step
beside the original when the pointer is elsewhere; the palette on empty canvas offers *Paste*
at the spot it was opened. A link to a node that was not copied stays behind. A node is pasted
only where the palette would offer it: a `State` never lands in a behavior, a behavior node
never in a shader, a second `Start`/`End` and a behavior calling itself are left out. What is
left out is named in a notice, the rest is pasted as one undo step and selected.
- **Mouse and selection work as in the scene view.** The **middle button pans** from anywhere,
a node under the pointer included (shift-drag on empty canvas does too); the left button never
pans. Dragging on empty canvas pulls a **rubber band** instead, which selects every node it
+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 # 1423 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1432 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
+3 -2
@@ -1,8 +1,9 @@
`Ctrl+Z` / `Ctrl+Shift+Z` / `Ctrl+Y` undo/redo (`Cmd` works wherever `Ctrl` does) · `Delete` or
`Backspace` remove the selection (objects, nodes, frames, keys or a row of the Animation tab, a graph group or comment — the box only, its nodes stay, and a band that caught boxes and nodes together removes both in one step; an asset asks first) · `Ctrl+G` create
container from the selection · `Ctrl+Enter` play, and pause/resume while playing · `Esc` stop ·
`Ctrl+V` import an image from
the clipboard as a texture (ignored while a text field has focus) · Animation tab: `Ctrl+C` copy
`Ctrl+C` copy the selected objects or graph nodes, `Ctrl+V` paste them
under the pointer ([Scene editing](Scene-editing), [Behaviors](Behaviors)) · `Ctrl+V` import an image from
the clipboard as a texture when nothing copied fits the tab (ignored while a text field has focus) · Animation tab: `Ctrl+C` copy
the picked keys, `Ctrl+V` paste them at the playhead (while keys are copied this takes `Ctrl+V`
there, so an image is pasted from another tab), `Ctrl`+drag duplicate keys · `Tab` / `Shift+Tab` cycle fields · lists: `↑`/`↓` move,
`←`/`→` fold, `Enter` activates · number
+22 -1
@@ -155,7 +155,28 @@ so they cannot drift apart. Only *Expand all* / *Collapse all* stay in the panel
something. Which object the menu is for follows the rule of a press: a selected object under the
pointer, hidden behind others or not, keeps the selection, and the menu acts on all of it;
otherwise the topmost object there is selected first. Empty space, an empty tilemap cell
included, opens no menu. The Container tab does the same for its template.
included, opens a menu with *Paste* alone. The Container tab does the same for its template.
**Copy and paste (#240).** `Ctrl+C` copies the selected objects, each with everything below it
(children, colliders, rigidbodies), and `Ctrl+V` pastes them into the scene or container the
visible tab shows. The object menu offers the same as *Copy* and *Paste*. The copy keeps names,
overrides and the look (rotation, scale, mirror); the editor offset stays behind. A placed
container is copied as a placed container and keeps showing its template, content picked out
of one is pasted as ordinary objects. The clipboard is the editor's own and holds ids of this
project, so it lives until another project is opened.
- **Where it lands:** under the pointer when the pointer is over the view (the copied group
keeps its layout, centred there), else one grid step (100) down and right of the original, and
another step for every earlier paste that is still there.
- **Into which parent:** into the one selected object (from the menu: the one clicked). When that
object is an original or an earlier paste, the copy goes beside it instead, under its parent, so
pasting again and again never stacks copies inside each other. Without such an object the copy
keeps the parent it had, if this scene or container has it, else it goes to the top level. It
keeps its look under the new parent, as a re-parent does.
- **Refused:** a container pasted into its own template (or into anything it ends up inside),
with the notice a drop gets. One paste is one undo step and selects what it pasted.
- While objects are copied, `Ctrl+V` in the Scene and Container tab pastes them; an image from
the system clipboard is then pasted from another tab. With nodes copied it goes through there.
**Editor offset (scene view only).** Every scene object additionally carries an
`editorOffset` — an x/y shift of where it is *drawn, selected and dragged* in the Scene tab,