ca5b2db449ebf575ea65edf4ef477b2a7bfdfb11
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ded71a92c9 |
Pick the target of an object variable in the Scene View (#276)
Choosing the target of an object variable meant finding its name in a dropdown. With many objects, or several with the same sprite, the name alone does not say which one it is. The eyedropper lets you click the object where you see it instead. - Every object dropdown gets an eyedropper button next to it. This covers variables, struct fields and list entries, in the Inspector and in the Variables tab. - The button opens the Scene View or the container tab the object lives in. A strip above the view names the field and the current candidate and offers Take and Cancel. The cursor is a crosshair. - A click picks a candidate and writes nothing yet. The candidate gets its own cyan frame, the selection stays on the object with the variable. - Clicking follows the selection rule. `pickOn` in `src/viewport/pick.ts` uses `pressOn` and only counts objects the dropdown offers. A click on empty space keeps the candidate. - Enter or Take writes through the same handlers as the dropdown. That is one undo step, or none if nothing changes. - Esc, Cancel, a right click in the view or a second click on the button cancel without writing. So do a tab switch, another selection, undo, redo, play and loading a project. - After Take or Cancel the editor goes back to the tab the pick came from. - While the eyedropper runs, the view does not drag, marquee, paint, show handles or open its context menu. Panning and zooming stay. Found on the way: - Started from the Variables tab, the click missed the object. The Scene View is hidden while that tab is open, and the layout skips hidden children. The strip appeared then, the view moved down by 32 px but kept its old height. `Editor.display()` now lays the row out again after showing it. Tests (on melektaus-atx): - unit pick and object-pick: 27 passed, 13 new - gate: 196 files, 2844 tests, CHECK EXIT 0. Two more come from svg-icons, which checks every icon twice. - e2e 57: ALL PASSED, 12 checks, 5 new (57e to 57g) - Counter-checks work. Without the layout fix 57g fails. Picking objects the dropdown does not offer fails 2 tests. Writing on cancel fails 2 more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cb32b4bc23 |
Draw scene symbols as white panel icons that make room for each other
The scene view drew its symbols from its own SVGs, each in a type colour and some on a plate. They looked heavier than the panel icons and were hard to read on busy ground. Symbols of different objects also sat on top of each other whenever their positions met. - Every symbol is now the panel icon of its kind, one file for both places. The scene-only SVGs in src/viewport/icons are gone. - Symbols are white in a thin dark outline with no plate behind them. haloSvg widens each shape of the file by its own stroke and draws that silhouette dark under the icon, so no second file is needed. - A butt stroke end would leave its end without outline. The halo caps such strokes square, and the rigidbody arrow shaft is now a filled rect so its top edge is outlined exactly. - Symbols are 18 world units across, stay upright and are clickable. A click selects the object, a drag moves it. - symbolLayout places every symbol on its object's position. Symbols that overlap stand on a ring round the middle of their positions, evenly spaced one icon apart. A ring that reaches into another symbol takes it in until nothing overlaps. Ownership plays no part. - Names sit beside their symbol, on the outside of a ring. Selection frames and parent links follow the symbol. - A collider icon no longer shows trigger or invalid state. The outline colour of the shape still does. - A lone collider sits on its sprite's middle again. A press there on an unselected sprite drags the collider, so e2e 02 and 16 now grab the sprite beside its middle. Hook __gm.container.objectRect helps 16 find that spot. Tests: - check.sh: 2245 tests, CHECK EXIT 0 (+8 for layout and halo) - e2e 1-16,31,39-43: 670 PASS, 2 FAIL. Both were sampling too strictly for the thinner, smaller icons. 5c looked for the exact outline colour, which the thin outline only reaches blended at this zoom. 31n started the ring scan one pixel past the smaller ring. Both are fixed, and e2e 5,31 then passed with 48 checks. - 5c checks white with an outline and none of the old colours, 41b checks the ring positions and that a click on a symbol selects its object, 31n checks the now white particle ring. - Counter-checks: without the halo only 5c fails, also with the looser outline match. Without the layout the ring and click checks in 41b fail. Originals restored by cmp. - The e2e check total stays 1351. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
056a622524 |
Refactoring round 6: shared sheet canvas, fewer copies (#85)
Recurring cleanup round. Behaviour is unchanged. Duplicated code in
src went from 27 clones with 299 lines to 6 clones with 56 lines
(jscpd, the two identical OFL licence texts not counted).
- SheetCanvas is the new base of the texture, pixel art and vector art
canvases. It holds background, mask, hint, panning, wheel zoom, fit,
view save and restore and the screen mapping. Pixel art keeps its
whole-pixel panning and fixed zoom steps.
- mixColor in src/core/util/color.ts replaces three copies in
animation, gradient and particles. It clamps t like the particle one.
- fingerprint now lives once in generated.ts, next to the revision
contract from #185.
- MoveCommand next to RenameCommand is the base of the three reorder
commands for tile pictures, tilemap layers and vector shapes.
- The two raycast nodes share inputs, settings and filter via rayOf.
- canvasRect() lives once in AssetTabEditor.
- Removed unused code: findPixelArt, isDrawableShape,
GeneratedPictures.has and SnapToggle.snapping. Tests now check the
same things through equivalent paths.
- 38 values used only in their own file lost their export.
- Three comments that told history now describe the current state.
The bundle stayed md5-identical for those edits.
- README lists vector art, pixel art and palette, and links the two
wiki pages.
Findings:
- PaintTilesCommand.changes is meant to prevent empty undo steps but
has not been called since #128. The rectangle tool therefore records
a no-op undo step when it paints the same tile over itself. Left as
is, because fixing it changes behaviour.
- No test covered middle-click panning in any sheet tab before. 13f
and 48a now check it.
- The default values of the ray inputs were untested. Length 1000
could become 10 without a red test. tests/core/raycast.test.ts now
covers it.
- CI measured 1308 editor checks at
|
||
|
|
28b1afa7af |
Panning the scene view no longer redraws the whole scene
A middle-mouse pan used to run the full redraw on every frame. It collected every object from the project, cleared and redrew every shape, re-sorted all children and made Pixi re-upload every buffer, although only the camera had moved. The user saw the frame rate drop while panning. - WorldViewport gets moveCamera(). When zoom and view size are unchanged it only moves the world and redraws the overlays drawn in screen pixels. collectFrame, the shape redraw and the re-sort drop out of a pan frame. - Every full redraw remembers the box each object is culled by. A pan that moves an object across the edge of the view still takes the full redraw, so objects appear and vanish as before. - Grid, selection outlines, rays and the container origin mark move into a shared drawOnScreen hook. It runs after every full redraw and after every pan. The parent links stay in afterItems because they are drawn in world units. - Wheel zoom keeps the full redraw, because line widths follow the zoom. A cache for collectFrame was left out: it would save about 1 ms and risk stale data. - debugInfo() reports redraws and cameraMoves, and __gm gets a hook that forces a full redraw, so a check can compare against it. Findings: - Chrome already coalesces mouse moves to one per frame (500 moves gave 183 redraws in 189 frames). A throttle was tried and removed again, because its counter-check did not fail. - A check in module 03 compared the whole gameInfo() object and broke on the new counters. It now compares camera, objects and rendering. - The stall without ?vsync most likely comes from the desynchronized context in src/main.ts. It cannot be reproduced headless. Tests: - Measured on Jump and Run, main-thread time per frame, 3 runs of 240 moves: pan 5.7-7.4 ms before, 3.8-4.8 ms after. Plain mouse moves stay at 2.1-2.4 ms. 208 of 240 moves took the fast path. - ./check.sh: 141 files, 2080 tests, exit 0. - GM_STEPS=1-16,29,42,43: 535 checks, 1 failed (the module 03 test above). After the fix GM_STEPS=1-5: all passed, 130 checks. - 3 new e2e checks in 5d: 12 pan steps give 12 camera moves and 0 full redraws, pixel rows after the pan match a fresh redraw, a box panned out of view and back is drawn again. - Counter-checks: overlays not redrawn on pan gives "3 of 3 rows differ". Edge test disabled keeps the box visible with 0 redraws. - Check total 1285 (1282 confirmed by CI task 229, plus 3). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
cc285af10a |
Tabs are open documents: Scene, Game and Plugins stay as fixed tabs, every other asset opens in its own tab (double click or Enter in the asset panel, on creation, from the list button), several assets of one kind can be open at once, a tab is labelled with its kind dimmed before the name, cut at 160 px and renamed with its asset, closes with its x or a middle click and goes away when its asset is deleted; a tab always shows its own document instead of following the selection, the picker in the tab head is gone, zoom and scroll are kept per document for the session and dropped on close, a double click on a call node stays in the same tab with breadcrumbs per tab; one editor per kind is switched between documents, the placement rules live in the pure module documents.ts, and the test hook showTab stays as a compatibility path; new e2e module 44 documents (#171)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
11981b40d0 |
Give the three asset tabs one base, and move the viewports into the editor
src/viewport/ held three classes only src/editor/ ever used, and framing.ts sat under graph/ although the scene view wants the same bounds sum. The graph, the texture and the container tab repeated the same header, subscription and disposal code with two silent divergences: the graph tab said "nothing shown" with null instead of '', and the texture tab refell back to the first asset on a selection change but not on a project event. These arrive together because GraphCanvas ties them: it reads framing from its new home, hands its fold marks to folding.ts, and its '' change is what GraphEditor must agree with. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d7c8d3e579 |
Measure a deviation against the base, not the innermost template
An instance edit was dropped as soon as its value matched the template object. With nested containers the template is not what the value falls back to: the outer container holds an edit for the object below it, and that one wins. If the inner template happened to carry the same value the user typed, the edit was thrown away and the value jumped to whatever the container in between says. Reported against the Jump-and-Run project: a coin narrowed to 8 inside "level", then set back to the sprite's own 24 in the scene, snapped back to 8. Reproduced through the inspector before touching anything. InstanceTarget now offers `base`: the template with the edits of every container in between woven in. Everything that judges deviation uses it - setOverride/setName/setPosition, both Revert commands, and the gold marks in the inspector. Writing still goes into the real template, which is where "apply to container" belongs. `base` is built on every read. Apply writes into the template and then asks whether the edit still deviates, so a base captured beforehand would answer for the template as it was - the e2e suite caught exactly that. Also in here, because it corrects the commit before it: placing an asset by double-clicking its row is gone, as asked for in asset-doppelklick.md. Dragging is the only way to place now. That took AssetPanel.place, the PlacementTarget interface, Editor.placementTarget and the two worldCenter() methods that existed only to feed it. A double-click on a scene asset still makes it the active scene. |
||
|
|
75d377af39 |
Place assets by dragging them from the panel into the view
The context menu entry is gone; dragging replaces it entirely. The drop target is the view under the pointer, not the active tab, so the same gesture works for scenes and for container templates. While dragging, an outline shows the footprint the object will have plus a crosshair on its origin, turning red when the drop would be refused. Preview and command share one function (placementRejection), so the outline cannot promise something the drop then rejects. A left-press used to select the list row immediately. Since the container tab follows the selection, it switched to the very container being dragged and every drop would have nested it inside itself. The list now selects on release without a drag: picking something up is not the same as choosing it. |
||
|
|
9d93020bd8 |
Add a Container tab and propagate template edits
The Container tab reuses SceneViewport against any object holder, so a container template is edited exactly like a scene. Right-click no longer changes the selection, which previously made nesting impossible: opening the menu on a container loaded it, and "Place in container" then targeted itself. Template edits (move, rename, override) now reach already-placed instances per slot, through a shared templateSync used by both the apply path and the plain object commands. Copies the user has touched keep their own value. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |