Commit Graph

69 Commits

Author SHA1 Message Date
indigo dc0c15de70 Scale manipulator: center handle for uniform scale + hover fix
- Add center dot hit test (axis 3) for the scale gizmo so hovering/
  clicking the center circle performs uniform scale on all three axes.
  Center is checked before HitTestAxes to prevent the pivot (which is
  an endpoint of all three axis segments) from always resolving to X.

- Uniform scale uses screen-space pixel delta (right = grow, left =
  shrink, 200 px ≈ ×2) instead of the world-space axis-line ratio.
  The axis-line approach broke because the mouse starts at the pivot
  (oT ≈ 0), making cT/oT explode on any small movement.

- Center dot highlights in orange and grows when hovered or active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 06:47:42 +08:00
indigo 7d53eb18d4 Fix USD camera tumble: lossless matrix write-back + gimbal-free orbit init
Two issues caused the camera orientation to flip when tumbling a custom
USD camera:

1. Write-back decomposed the camera matrix to XYZ-euler via
   Decompose(X,Y,Z) and re-authored it as a rotateXYZ op. That round-trip
   is lossy — the angles Decompose returns do not reconstruct the same
   matrix as a rotateXYZ op, so the orientation read back from the prim
   differed from the free-camera view shown during the drag. The view
   jumped every time a drag finished and snapped back on the next drag.
   Now author the full camera-to-world transform as a single matrix op,
   which round-trips exactly through UsdGeomCamera::GetCamera().

2. Orbit init relied on PullFromCameraTransform's Euler decomposition for
   theta/phi, which is gimbal-affected. Added
   ViewportCamera::InitOrbitFromEyeAndCenter to derive theta/phi directly
   from the eye->center vector (zero roll), respecting the Z-up matrix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 07:28:28 +08:00
indigo ee1b750f8c Fix USD camera orbit pivot — use scene bbox centroid instead of focus distance
When switching to a USD camera, the orbit pivot was set from
GfCamera::GetFocusDistance() which is a depth-of-field attribute
that defaults to 5 scene units regardless of scene scale.

InitCameraNavigation() now computes the scene bounding box centroid,
projects it onto the camera view ray to get a proper orbit distance,
and calls SetFocalPoint/SetDist to place the pivot correctly.
Added SetDist() setter on ViewportCamera to support this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 04:46:20 +08:00
indigo 8f309e5440 Update imgui.ini panel layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 04:04:36 +08:00
indigo a62764397c Scene Hierarchy ET switcher + Create Sublayer via Save dialog
- Add edit-target layer combo at top of Scene Hierarchy panel (always
  visible when stage loaded — session, root, sublayers); routes through
  LayerManager::SetEditTarget so StageEditor ET checkboxes stay in sync
- Replace custom Create Sublayer modal with native SaveFile dialog;
  LayerManager::CreateNewSublayer creates the file on disk, inserts it
  at the top of the sublayer stack, and activates it as edit target

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 03:49:35 +08:00
indigo e5d7967455 View menu — panel visibility toggles for all 5 panels
Each panel (Stage Editor, Scene Hierarchy, Viewport, Property Panel,
Timeline) now has a checkable menu item under View. Closing a panel via
its X button also unchecks the entry. Stage Info and Demo Window follow
below a separator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:39:50 +08:00
indigo 7f0fa6a944 Fix rotate manipulator axis and gizmo pivot placement
Rotate manipulator — correct axis bug:
- Object-space delta axis was set to initRot.GetRow3(axis) (a parent-space
  vector) then applied in the prim's local frame via deltaM * initRot.
  These frames are mismatched: the axis must be the canonical e_a so that
  Rot(e_a) fixes e_a and the prim rotates purely about its own axis.
  Fixed to use the canonical axis for both spaces; only composition order
  differs (deltaM * initRot for object, initRot * deltaM for world).

Gizmo pivot placement:
- ComputeGizmoPivot() used the bounding-box centre (geometry centroid),
  placing the gizmo at the wrong location for any non-centred prim.
  Replaced with parentToWorld.Transform(translate + pivot) from
  XformCommonAPI::GetXformVectors — the authored pivot point in world space.
  Fallback for incompatible op stacks uses worldMatrix.ExtractTranslation().

Property panel:
- Show pivot (X/Y/Z) as read-only row below Scale, populated from
  XformCommonAPI::GetXformVectors each frame.
- Removed active-rotate-axis display (was added and then removed per request).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 09:57:39 +08:00
indigo e0b0fd8204 Fix sublayers not persisted on save
- SaveStage: explicitly call rootLayer->Save() before m_stage->Save() to
  ensure root-layer metadata (subLayers field) is always written to disk
- SaveUsdFile: redirect to SaveAs when the root layer is anonymous so
  Ctrl+S on an in-memory stage no longer silently does nothing
- SaveUsdFileAs: call RefreshManagers() after SaveStageAs so LayerManager
  stays in sync with the newly opened file-backed stage; without this,
  sublayers added after a Save As went to the old stale stage and were lost
- LayerCreateCommand::Execute: use GetSublayers() (sublayer-local indices)
  instead of GetLayerStack() (full-stack indices) to record m_insertedIndex,
  fixing undo of add-sublayer removing the wrong layer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 07:49:34 +08:00
indigo 9816fb8759 Stage Editor Panel — sublayer editing with ET control, mute, reorder, dirty state
Replace LayerPanel with StageEditorPanel for full sublayer composition workflow:
- Edit target (ET) checkbox on root/session and each sublayer; pen icon header
- Dirty indicator (*) per layer; muted layers remain visible in list
- Drag-drop and Move Up/Down reordering with undo (LayerReorderCommand)
- Add existing sublayer via file dialog; create new sublayer modal
- Fixed LayerReorderCommand::ApplyOrder using full-stack indices on sublayer-local
  list (silent remove failure → duplicate insert → USD _ValidateEdit error)
- Fixed muted sublayer visibility: walk GetSubLayerPaths() + FindOrOpenRelativeToLayer
  + m_layerRefs to keep muted layers alive and visible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 16:37:30 +08:00
indigo 9ec9761dd7 Timeline playback controls — transport icons, loop/bounce/rewind
- Replace all text buttons with SVG icon buttons (skip-back, step-back,
  play-back, play, pause, step-forward, skip-end)
- Add rewind: separate play-backward button that flips direction
- Add loop mode button with submenu (Loop / Bounce / Off)
  - Loop wraps at boundaries; Bounce reflects direction (ping-pong)
- Start/end frames moved to flank the scrub slider as plain numbers
- New icons: play-back.svg, loop.svg (FA repeat), bounce.svg (FA exchange-alt)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 13:36:07 +08:00
indigo c4bf9673a8 Timeline Prototype 2026-06-13 11:48:56 +08:00
indigo 43c70be574 PropertyPanel Update 2026-06-13 08:45:16 +08:00
indigo 2a8534eda7 Update README.md 2026-06-13 08:10:05 +08:00
indigo ae4a5ab96d Refract Manipulator 2026-06-09 08:47:44 +08:00
indigo 4cb6ec7341 Refract Manipulator 2026-06-09 08:43:29 +08:00
indigo 3b0250b882 Fix rotate issue 2026-06-06 09:34:39 +08:00
indigo d4b46b438c Fix manipulator translate and rotate problem 2026-06-03 19:51:20 +08:00
indigo 607b36b97d cleanup files 2026-06-03 17:12:47 +08:00
indigo 9be48d8b9e Init Repo 2026-06-03 09:00:11 +08:00