ca5b2db449ebf575ea65edf4ef477b2a7bfdfb11
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6d79cf59a3 |
Move a large graph instead of drawing it again (#292)
In a graph of many nodes the frame rate dropped while panning, and more so while one node was dragged. Every pointer move rebuilt every box, every text and every curve, and a drag also announced a changed project, so the panels rebuilt along with it. - Panning and zooming move the picture. GraphCanvas.applyView sets position and scale and draws anew only the grid and the rubber band. It used to call redraw(). - A node draws its box and makes its texts only when what they show has changed. NodeView keeps a signature of what redraw reads and one of what rebuildTexts reads, and returns early while they hold. - A drag does not announce a changed project. GraphDrags writes the model on every pointer move and asks the canvas once a frame to follow (GraphCanvasHost.moved). state.preview() waits for the command of the release. - Nodes outside the picture are not drawn. inView in graphView.ts is the rule, cull() applies it after every redraw and every change of the view. - The graph is a render group, and box and pins go into the batch. The mask sits on a container above the group, on the group itself it would be panned and zoomed along. - The rubber band and the drop mark of a dragged behavior are drawn on their own (drawBand), without a redraw of the graph. Measured in the CI image with 388 nodes and 540 links, fitted to the canvas, 240 pointer moves 16 ms apart: - Pan, script per move: 25.2 ms before, 2.0 ms after - Pan: 4.4 frames per second before, 18.7 after - Drag a node: 2.7 frames per second before, 22.4 after - The still picture: 9 frames per second before, 21 after Not solved: the still picture of such a graph stays at 21 frames per second in the test browser. What is left is the drawing itself, and the frame rates are those of that browser, not of a desktop GPU. Tests: - Gate on melektaus-atx: 207 files, 3121 tests (3114 + 7), exit 0 - e2e 4,6,18,19,20,23,24,26,28,31,36,43,51,53 on melektaus-atx: 542 pass, 1 fail. The fail is module 51 after module 43, an order the suite does not have, and it fails the same way without this change. Module 51 alone: 12 checks, all pass. - No full run and no smokes. The sum of 1660 (1656 + 4) is reckoned, and the CI workflow is switched off. - Seven unit tests: six for inView in tests/editor/graph-view.test.ts and one in frame-preview.test.ts - Four e2e checks in block 6z-xii of module 06: pan, drag, zoom in and fit, a changed value - Seven browser counter-probes fail 2 to 3 checks each Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2ff3a78607 |
Put the shapes of a vector drawing on layers and in groups (#190)
A vector drawing was one flat list of shapes. With many shapes the list got hard to read, and several shapes could not be kept or moved together. Now the shapes stand on layers, as in pixel art, and can be put into groups that nest. - A drawing has layers, each with a name and an eye. A hidden layer is neither in the tab nor in the picture a sprite wears, and its shapes cannot be pressed. One layer is the one worked on: the pen and Add shape draw onto it, and SHAPES lists what is on it. - The inspector has a list LAYERS over the shapes. Its plus adds a layer, the cross on a row removes it with all on it, the last one stays. A double-click renames, a drag sorts. - Group (Ctrl+G) puts the selected shapes into a group, Ungroup (Ctrl+Shift+G) takes it away. A group stands over its rows in the list, the rows one step in, and a row is dragged into a group or out of it. - In the tab a press on a shape takes its outermost group, and a drag moves the group as one undo step. - The model has layers with a tree of shapes and groups instead of a flat shapes array. The rules are pure functions in core/model/vectorTree.ts. A drawing saved before opens with all its shapes on one layer. - SortableList takes rows with a depth and drops into a tree. The flat lists of tilemap and pixel art run as before. Decided here: - A group has no transformation of its own and cannot be hidden or locked. Rotating and scaling is the follow-up #291. - A group is never empty: the one that loses its last shape goes with it. - Several selected shapes are dragged together, grouped or not, and a click on a shape of the selection keeps the selection. This is what #217 asked for. - Shift+click selects like Ctrl+click. With Select, Shift pans only beside the shapes, as in the scene view. The middle button pans anywhere, and with the pen and Paint Shift pans as before. - A row of the list picks one shape of a group alone. - Shapes change their layer through a row Layer in the inspector, which is there from two layers on. Rows are not dragged between layers. - A group cannot span two layers, the button is off then. - The pen does not draw onto a hidden layer, the hint says so. - Groups are always shown unfolded. - The four order buttons work inside the own group or layer. Tests: - Gate: 204 files, 3067 tests (3008 + 59), exit 0 - e2e 47,48: 108 checks. e2e 39,40,47,48 before the Shift change: 209 checks. No full run, the sum of 1645 (1639 + 6) is reckoned and CI measures it. - 59 unit tests: 36 in tests/core/vector-tree.test.ts, 23 in tests/editor/vector-layers.test.ts - Six e2e checks with a real mouse in block 47j - 47 unit counter-probes for layers and groups and three for the Shift click all fail tests, run on stein2 - Three browser counter-probes fail their checks - Two screenshots looked at (group in the list, hidden layer) - Only unit tested: the row Layer, sorting and removing layers, copying a group, the Shift pan beside the shapes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
d6171fd386 |
Preview pixel art and curve fields once per frame too (#274)
The previous commit left two findings open: in the pixel art tab the palette colour and the opacity of a layer still told the editor about every input, and so did the place fields of the curve tab. They now follow the same rule as the inspector rows. - PixelArtSide writes colour and opacity into the model on every input and requests the preview through a FramePreview. Both commits cancel a waiting preview first. - CurveCanvas.movePicked does the same for the t and v fields of the picked point. Showing another curve cancels a waiting preview. - Also fixed: when the colour picker ended on the colour it started from, the model was put back but nobody was told, so the previewed colour stayed on screen. commitColor now says so, as the opacity already did. The gain was not measured for either tab, only the behaviour is tested. Tests: - Gate: 198 files, 2911 tests (2907 + 4), exit 0 - e2e 47,48,53: 117 checks passed - Four new unit tests in tests/editor/frame-preview.test.ts: colour, opacity, curve fields and the return to the starting colour - Seven counter-probes fail, one test each. They ran on stein2, not in the container. - No new e2e check, the sum stays at 1616. Neither the full suite nor the smokes ran for this state, and there was no counter-probe in the browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c4a9280140 |
Preview inspector edits once per frame, not per input (#274)
Scrubbing a number in the inspector and dragging a colour stop of a gradient told the editor about every input. Pixi repeats each pointer move shortly after, so both gestures paid for two previews per move. The issue asked to measure first and to build only from 10 % per move. The measurement showed about 50 %. - previewingHandlers still writes the model on every input but requests the preview through a FramePreview of its own. The commit cancels a waiting preview first. - The preview handler of the GradientBar in shapeSection.ts does the same. - Wider than the issue describes: the row handlers also serve typing, the arrow keys and the colour picker. All of them preview once per frame now. Measured on stein2, fixture project with 120 extra objects, 120 moves 8 ms apart, three runs each: - Scrub: 236 project events before, 51 to 61 after. 45 to 50 ms per move before, 22 to 27 after. - Colour stop: 238 project events before, 50 to 51 after. 44 to 49 ms per move before, 22 after. - One preview still costs 13 to 17 ms. That price per frame is what remains. Finding, not fixed here: in the pixel art tab the palette colour and the opacity of a layer still preview on every input (PixelArtSide.ts), and so do the head fields of the curve tab. Neither was measured. Tests: - Gate: 198 files, 2907 tests (2903 + 4), exit 0 - e2e, full run: 1616 checks passed (1615 + 1), exit 0 - Smokes: 24 / 19 / 21, exit 0 - Four new unit tests in tests/editor/frame-preview.test.ts, two for a row and two for a colour stop - One new e2e check in module 02: a held scrub gave 10 project events in 12 frames, and the value is there before the release - Four unit counter-probes fail, 1 to 2 tests each. They ran on stein2, not in the container. - The browser counter-probe fails the new check with 50 events in 16 frames Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
30fb3a2316 |
Dragging previews once per frame instead of on every move (#213)
Scene view, texture tab and graph called state.preview() on every pointer move. Each call rebuilds panels, the editor run and generated images, so a drag in a busy project cost up to 34 ms per move. The model is still written on every move. Only the preview now waits for the next frame. - New FramePreview in src/editor/framePreview.ts. request() goes into the move handler, cancel() into the release. The rule lives in one place instead of six copies. - Scene view: object drag, polygon corners and tilemap strokes use it. - Texture tab: frames, slice edges and collision corners use it. - Graph: nodes, groups and comments use it through GraphDrags. That covers the state machine, shader and particle tabs as well. - Vector art is unchanged. Its frame already writes the model since #129. Findings: - The texture tab paid twice per move (232 project events for 120 moves). Pixi sends a second pointer event 4 to 8 ms after each real move as a hover update. It now lands in the same frame for free. - Inspector scrubbing and gradient stop dragging still preview on every input. Both lie outside the three canvases of the issue. Measured with a throwaway probe, 120 moves at 8 ms, 120 extra objects: scene 26.2 -> 18.5 ms/move, texture 34.2 -> 17.9, graph 28.8 -> 17.0. Project events dropped from 120/232/119 to 48/48/41. Tests: - ./check.sh: 147 files, 2204 tests, exit 0 (before 146 / 2199). - 5 new unit tests in tests/editor/frame-preview.test.ts, including the real GraphDrags. Counter-checks (direct preview in the graph, no cancel on release, one key per name) each fail the expected test. - e2e 1-16,29,31,36,37,39-43: 708 checks passed. - e2e 1-16,26,28: 634 checks passed. - No new e2e check, the check sum stays at 1314. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |