Feature/object-groups - #16
Merged
Merged
Conversation
AlexZ005
added a commit
that referenced
this pull request
Aug 4, 2026
Roadmap #16 second drop, batch Q1 — three reported annoyances in the menu. - SUBMENU CURSOR is remembered per level: stepping out of a submenu lands back on the row you came from instead of jumping to the top. Pointer hovers record the same memory, so mouse and keyboard agree about where you were. - SEARCH IS STICKY. Deleting the query used to snap you back to the grouped menu mid-thought; now the box stays and the list simply widens to EVERY action (capped at 200 rows, scrolling) - the browse list the retired node-search box used to be. Only Esc leaves search, so Esc now unwinds query -> search -> submenu -> menu, one step per press. - THE MENU KEEPS ITS ANCHOR. It picked the roomier side of the click on EVERY re-place, so a long match list re-decided and teleported the menu to the top of the screen. The side is chosen once, the anchored edge stays on the click, and anything that doesn't fit is capped and scrolls (verified: top 140 -> 140 while the list grows from 2 rows to 59). - "Search nodes…" no longer appears among its own search results (`revealFilter` rows are excluded from the leaf collection). Verification: context-menu-redesign +9 checks (sticky search, anchor stability, internal scroll, three-step Esc, cursor memory into and out of a mid-list submenu); node-search updated for the new Esc semantics +1 check for the exclusion; context-menu-v2 and context-menu-overflow green. svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 4, 2026
…ckboxes Roadmap #16 second drop, batch Q2 — five reported items. - DEEP LINKS: "More snapping settings…", "Grid & axes settings…" and "Manage saved views…" now open Configure Scene, EXPAND the named section (even one you had collapsed) and scroll to it. They went through `showSidebar('scene')`, which TOGGLES - so clicking one while the panel was already open closed it. New `openSceneSection(label)` only ever opens, and Section.svelte watches an `inspectorScrollTo` store, expands, scrolls and clears it. - GRID FOLLOW is a three-way choice: Off / Look-at / Camera. "Follow the camera" tracked your POSITION, which is the wrong thing while you are looking somewhere else; Look-at centres the grid under the orbit target. Both modes stay HORIZONTAL (y = 0 - it is the ground plane, not a flying sheet) and snap the centre to whole cells so the lines keep agreeing with world coordinates instead of sliding under objects. The old boolean migrates to Look-at. - SNAPPING STEPS: Scale gained the missing 0.25 (and Rotation 90°), and a value typed in Configure Scene now joins the presets in the menu, sorted and marked as active - custom steps used to be invisible and unreachable there. - PHYSICS CHECKBOXES: the Sensor, freeze-axis and show-collider boxes were raw <input type="checkbox"> rendering as native controls; they use the themed component now, like everything around them. - ADD opens the new object's properties, even when another panel was showing. Verification: new tests/e2e/panel-deeplinks.test.cjs (16 checks: open from closed, expand a collapsed section, no-close on a second link, look-at follow snapped to cells with y pinned, Off recentres, 0.25 + custom step present and marked, themed checkbox, Add switches the panel); grid-snapping, add-menu-cursor, physics-colliders, collider-viz, inspector green. Build green, svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 4, 2026
Roadmap #16 second drop, batch Q3. The transform rows had a drag-to-scrub control; every other number was a plain <input type="number"> that only committed on Enter or blur - so its arrows looked like they did nothing, and the two behaved differently. DragRow is now THE numeric field and the sliders' boxes, the snapping steps, the clip planes, render order and the particle offsets all use it: drag horizontally scrub (Shift = fine, Ctrl = snap) click / type applies LIVE, no Enter needed ArrowUp / Down one MINOR unit (0.01 at 2 decimals), Ctrl x10, Shift x100; integer fields step by 1 / 10 / 100 Esc back to the value you focused it with It is a real <input> the whole time instead of swapping a button for a box: the caret is always there, ids keep working, and touch gets the numeric keypad (inputmode). type="text" on purpose - a native number spinner would fight our own arrow steps. TWO DELEGATION TRAPS, both found by the suites: Svelte's `onkeydown`/`onpointerdown` attributes are DELEGATED, running only once the event reaches the app root, and the panels this field lives in swallow both on the way up (the drawer's drag/resize wiring eats pointerdown, the flowbite dialog eats Escape). Esc-to-revert did nothing, and a drag whose pointerdown never arrived jumped the value by the pointer's absolute X (+22 instead of +2). Both are direct element listeners now. The pointer trio rides the WRAPPER so a scrub can start on the axis label too, and a click there focuses the input for typing. Verification: new tests/e2e/number-fields.test.cjs (13 checks: live typing, the three arrow steps, integer stepping, Esc revert, drag scrub, the same rules in a slider box); inspector updated for the always-input field (its drag check now lands on 2.0 instead of 22.9); camera-clipping, grid-snapping, camera-bookmarks, object-properties, panel-deeplinks, geometry-params, particles(+impact), environment(+v2) green. Build green, svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 4, 2026
Roadmap #16 second drop, batch Q4. Selecting a camera object now shows a small LIVE preview bottom-right. It is not a second WebGL context (that duplicates every texture and geometry on the GPU): Outline.svelte draws one extra SCISSORED viewport of the same renderer after the composer pass, into the rect the window publishes - so the DOM part is pure chrome and the cost is one viewport draw, only while a camera is selected. gl clears respect the scissor box, so the inset clears just itself. - Right-drag moves it (left stays free for the viewport), touch-HOLD then drag; it clamps fully on screen and parks bottom-right, LEFT of an open side panel so the two never overlap. - Inside the frame the camera's own marker and the frustum lines are hidden for that draw - you would otherwise be looking at the inside of its body. - A ⤢ button jumps to the full-screen preview; ✕ turns the window off for that camera. On by default, with "Preview window while selected" in Camera properties. - CAPTURE moved onto its own row below Preview / Set from view / Align view, with a camera icon and a note that it saves a PNG at the framing aspect. Two familiar traps, both caught by the suite: `pipTarget` reads the selection SET (the sticky `selectedObject` kept the window open after a deselect) and takes `objectsGroup` as a dependency (the `pip` flag lives on userData, and THREE trees are not reactive - the post-write poke is the only signal a derived store gets). Verification: new tests/e2e/camera-pip.test.cjs (18 checks: targeting, published rect matches the frame, framing aspect, parking clear of the panel, right-drag + clamping, hidden during a full preview and after deselect, the per-camera switch, and the DOM->gl y-flip); camera-objects (banner check hardened against its fly transition), camera-preview-control, viewport-selection, collider-viz green. view-mode still fails its pre-existing shadow-catcher check. Build green, svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 4, 2026
… PiP polish Roadmap #16 second drop, batch Q5. THE BUG, properly this time. Nothing in the app ever disabled orbiting during a gizmo drag: threlte's TransformControls disables whatever controls sit in ITS OWN context slot, and a camera preview unmounts + remounts the editor's OrbitControls, after which that slot points at an instance which no longer drives the view. So dragging an object also spun the camera. The `dragging-changed` hook now does the suppression itself, first thing and for every gizmo target, writing through `activeOrbit` - instance-proof. The preview's own controls are disposed when Control ends (three keeps DOM listeners on a merely-dropped instance). Reproduced end to end first: the SAME real drag on the REAL gizmo arrow rotated the view 0.21 after a preview cycle and 0.00 before it; now both read 0.00000 and the object still moves the identical 1.04 units. MENU placement, rewritten to the rules you gave: open AT the cursor preferring downward; when the content does not fit below, shift the WHOLE menu up just far enough that its bottom stays inside (no flipping to the other side of the pointer); a scrollbar appears only when the content is taller than the window. SEARCHING no longer moves anything - the menu keeps the top it opened with, the list gets a sensible height instead of unfolding to the floor, and a corner grip resizes it while searching. GRID follow: 'camera' now uses threlte's own followCamera, which keeps the shader drawing lines at WORLD positions - smooth while you pan. Only 'look-at' snaps the centre to whole cells, which is what you want when it is locked to an object. DEEP LINKS scroll the container with the sticky header's height as an offset, so the section label lands BELOW "Filter properties" instead of under it, and "Manage saved views…" targets the SAVED VIEWS sub-heading (`data-anchor`) rather than the top of the Camera section. SNAP STEPS are clean numbers: the shared numeric field quantizes a drag to its own precision (a scrub used to produce 0.7999999999999999), the position/scale snap fields are 2-decimal, and every menu label and hint prints through one formatter. CAMERA PiP: the title bar drags with the LEFT button too (the body keeps right-drag so a stray left-click cannot move it), the transform gizmo is hidden for the inset draw - it sat on the lens as a giant coloured blob, and hiding the controls was not enough because three keeps the gizmo's visuals in a separate helper object - and the parked window keeps clear of the round HUD buttons. Verification: new tests/e2e/gizmo-orbit-leak.test.cjs (9 checks, A/B real-mouse gizmo drag before and after a preview cycle, so normal left-drag orbiting can never be mistaken for the bug); context-menu-redesign +5 (cursor-anchored open, shift-up with no scrollbar, sticky top while searching, bounded height, grip); panel-deeplinks +4 (three headers clear the sticky header, clean snap hint); camera-pip +4 (left-drag on the bar, body left-drag inert, gizmo restored after each draw). camera-objects, camera-preview-control, node-search, grid-snapping, number-fields, inspector all green. Build green, svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 5, 2026
…ght, PiP layer Roadmap #16 second drop, batch Q6 — the six follow-ups. - LOOK-AT POINT no longer jumps to the world origin when you exit a preview. The editor's OrbitControls unmount while the preview owns the view, and the pair that mounts on exit starts from the default target (0, 1.5, 0). The target is now snapshotted when the preview takes over and copied back onto the FRESH instance once it appears (the store still holds the disposed one for a beat). Verified: (6, 2, -3) in, (6, 2, -3) out. - SNAPPING ROWS align: label | chips | field in one grid, so the three numeric boxes share a right edge no matter how many preset chips a row has (4 / 4 / 3), and the chips are tightened enough to stay on ONE line in the 320px panel. - NO CARET during a scrub: pointerdown's default is blocked so a drag can never place or drag the caret through the digits (you could watch it skate about), selection is suppressed while scrubbing, and focus is handed over on RELEASE instead — which is also what makes click-to-type work. - THE SEARCH LIST REMEMBERS the height you drag it to, per menu kind: the viewport menu, the node editor and the object menu each keep their own (`sizeKey` prop → `ctx:searchHeight:<kind>` locally). - DEEP LINKS are deterministic: measure → scroll → re-measure → correct, with the scroller found by real SCROLLABILITY rather than class names, an instant scroll (a `smooth` one was being cancelled by the reflow of the section it had just expanded) and retries while the just-expanded content lays out. All three land 8-20px under the sticky filter header even when the panel starts scrolled to the bottom. NOTE: the previous check passed vacuously — it only asked for "somewhere below the header", which is true without any scrolling at all. - CAMERA PiP frame drops to z-index 2: it is a viewport overlay, not chrome, so panels and HUD now cover it (verified pip z 2 vs panel z 10). Verification: camera-preview-control +2 (look-at round trip), panel-deeplinks +3 (tight landing band from a bottom-scrolled panel), context-menu-redesign +3 (height persisted, restored on reopen, per-kind keys), number-fields +4 (scrub reports itself, no focus, no selection, click still focuses), camera-pip +2 (layer below the panel). camera-objects, gizmo-orbit-leak, grid-snapping, node-search, inspector, object-properties green — 11 suites in one run. Build green, svelte-check 419/62. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AlexZ005
added a commit
that referenced
this pull request
Aug 5, 2026
[feat] roadmap #16: menus, grid & scene cameras (P1-P6)
AlexZ005
added a commit
that referenced
this pull request
Aug 5, 2026
…t store Found while assembling the release: shift-clicking a second object stopped adding to the selection. ROOT CAUSE: `activeOrbit` (cameraPreview.js, #16) is a DERIVED store, and svelte compiles `$activeOrbit.enabled = x` into `store_mutate()` -> `store.set()` — which a derived store does not have. All seven sites in Scene.svelte therefore threw `TypeError: store.set is not a function`. The one in `onPointerUp` aborted the rest of the handler, so the shift path never reached `raycastSelect` — while a PLAIN click, which never enters the marquee branch, kept working. That asymmetry is why it looked like "shift multi-select is gone" rather than "selection is broken". Fix: `setOrbitEnabled(on)` in cameraPreview.js resolves the store with `get()` and mutates the resolved controls object (mutating the object was always fine — it is the `$store.prop =` syntax that is not). Every call site now goes through it; the one remaining `$activeOrbit` read (editor navigation) is a read and stays. Regression guard in viewport-selection: three boxes, REAL mouse clicks at projected positions — plain click selects one, shift-click adds a second and a third, shift-click on a member toggles it out, a plain click collapses the set, no page errors during the gestures, and the member tints are restored on deselect. A store-level `selectObject` call would never have caught this, since the bug lived in the pointer handler. Verified the guard FAILS without the fix (8 page errors, the set stuck at 1). svelte-check holds 419/62; build green; camera-preview-control, camera-pip, gizmo-orbit-leak, notes-v2, annotation-anchor, grid-snapping green, plus multi-select and camera-objects green with PEER_CONFIG set (both are two-peer suites that need the signaling override on a localhost APP_URL). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces the ability to move objects between groups.
This feature includes UI improvements, recursive content visualization, and fixes for related issues.
Additionally, introduces the ability to send group hierarchy to peers.