Skip to content

Feature/object-groups - #16

Merged
AlexZ005 merged 9 commits into
mainfrom
feature/object-groups
Nov 28, 2024
Merged

Feature/object-groups#16
AlexZ005 merged 9 commits into
mainfrom
feature/object-groups

Conversation

@AlexZ005

@AlexZ005 AlexZ005 commented Nov 28, 2024

Copy link
Copy Markdown
Collaborator

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.

@AlexZ005
AlexZ005 merged commit 2139fb2 into main Nov 28, 2024
@AlexZ005
AlexZ005 deleted the feature/object-groups branch November 28, 2024 21:15
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant