Summary
Enable dragging an asset from Project Browser (grid/sidebar) onto the stage viewport to instantiate it into the open scene.
Today drag-and-drop only supports browser-internal file moves. Dropping onto the stage is not wired.
Why this matters
Reality Composer Pro supports library-to-stage authoring as a primary workflow. Without this, Deconstructed can browse/edit files but cannot perform direct placement from library into scene.
Current state (code audit)
- Drag payload exists in browser UI:
Packages/DeconstructedLibrary/Sources/ProjectBrowserUI/AssetGridView.swift
Packages/DeconstructedLibrary/Sources/ProjectBrowserUI/CollectionsSidebar.swift
- Current drag behavior is file/folder move within browser tree/grid via
ProjectBrowserFeature.Action.moveItems.
- Stage view is rendered in:
Packages/DeconstructedLibrary/Sources/DeconstructedUI/ContentView.swift
DocumentEditorFeature wires viewport/scene/inspector sync, but has no “asset dropped on stage” action path:
Packages/DeconstructedLibrary/Sources/DeconstructedFeatures/DocumentEditorFeature.swift
- Scene editing client currently exposes only primitive/structural creation:
Packages/DeconstructedLibrary/Sources/SceneGraphClients/SceneEditClient.swift
- Inspector can edit references for selected prims, but there is no direct “instantiate asset from URL/path” flow from DnD.
Proposed behavior (v1)
When a supported asset (e.g. .usda, .usd, .usdc, .reality) is dropped onto the stage:
- Determine insertion parent path (selected container prim if valid, else root).
- Create a new prim container (likely
Xform) with a unique name.
- Author a USD reference/payload to the dropped asset path.
- Refresh stage + scene graph + inspector selection to the new prim.
- Invalidate thumbnail for active scene.
v1 can ignore exact 3D cursor/ground hit placement and place at default transform (origin). Positioning can be phase 2.
Implementation plan
Phase 1: DnD contract and routing
- Define a dedicated drag payload type for project assets (avoid overloading plain text IDs used for internal move).
- Add stage drop target wrapper around viewport in
ContentView and route drops to DocumentEditorFeature.
- Add new action(s) in
DocumentEditorFeature, e.g.:
.assetDroppedOnStage(payload: StageAssetDropPayload)
.assetInstantiateSucceeded(createdPrimPath: String)
.assetInstantiateFailed(String)
Phase 2: Scene edit API for asset instantiation
- Extend
SceneEditClient with an operation like:
createReferencedAsset(sceneURL:parentPath:assetURL:suggestedName:) -> String
- Back it with
DeconstructedUSDInterop implementation that:
- creates an insertion prim
- authors reference/payload arc
- returns created prim path
- Keep macOS-only APIs and existing concurrency/TCA patterns.
Phase 3: State updates and UX
- On success, trigger same synchronization patterns used elsewhere:
- reload/refresh viewport (preserve camera where possible)
- refresh scene navigator
- set inspector/viewport selection to created prim
- mark scene modified for thumbnail invalidation
- Add lightweight visual affordance for valid stage drop target (highlight).
- Add unsupported-type rejection with user-facing error in existing error channel.
Phase 4: Tests
DocumentEditorFeatureTests:
- drop success path dispatches expected effects/actions.
- drop failure surfaces error and avoids inconsistent selection state.
ProjectBrowserFeatureTests/UI-level tests:
- drag payload generation for supported asset items.
SceneGraph/SceneEdit tests (or dependency-driven unit tests):
- correct parent path + naming conflict handling.
Acceptance criteria
- User can drag a supported asset from Project Browser and drop it on stage.
- A new prim appears in scene graph and is selected after drop.
- Viewport reflects the change without losing camera context.
- Thumbnail invalidation occurs for modified scene.
- Unsupported assets do not crash; error is surfaced.
- Existing browser internal drag-to-move behavior remains unchanged.
Risks / unknowns
RealityKitStageView package may need a small API extension if we need true in-viewport drop coordinates/hit testing (for future placement).
- Asset-to-USD reference path normalization rules must match project structure (relative vs absolute authored paths).
- Naming strategy for dropped instances should avoid collisions deterministically.
Out of scope (for this ticket)
- Precise placement using raycast/hit test at mouse drop point.
- Drag preview ghost in viewport.
- Multi-item drop batching.
Summary
Enable dragging an asset from Project Browser (grid/sidebar) onto the stage viewport to instantiate it into the open scene.
Today drag-and-drop only supports browser-internal file moves. Dropping onto the stage is not wired.
Why this matters
Reality Composer Pro supports library-to-stage authoring as a primary workflow. Without this, Deconstructed can browse/edit files but cannot perform direct placement from library into scene.
Current state (code audit)
Packages/DeconstructedLibrary/Sources/ProjectBrowserUI/AssetGridView.swiftPackages/DeconstructedLibrary/Sources/ProjectBrowserUI/CollectionsSidebar.swiftProjectBrowserFeature.Action.moveItems.Packages/DeconstructedLibrary/Sources/DeconstructedUI/ContentView.swiftDocumentEditorFeaturewires viewport/scene/inspector sync, but has no “asset dropped on stage” action path:Packages/DeconstructedLibrary/Sources/DeconstructedFeatures/DocumentEditorFeature.swiftPackages/DeconstructedLibrary/Sources/SceneGraphClients/SceneEditClient.swiftProposed behavior (v1)
When a supported asset (e.g.
.usda,.usd,.usdc,.reality) is dropped onto the stage:Xform) with a unique name.v1 can ignore exact 3D cursor/ground hit placement and place at default transform (origin). Positioning can be phase 2.
Implementation plan
Phase 1: DnD contract and routing
ContentViewand route drops toDocumentEditorFeature.DocumentEditorFeature, e.g.:.assetDroppedOnStage(payload: StageAssetDropPayload).assetInstantiateSucceeded(createdPrimPath: String).assetInstantiateFailed(String)Phase 2: Scene edit API for asset instantiation
SceneEditClientwith an operation like:createReferencedAsset(sceneURL:parentPath:assetURL:suggestedName:) -> StringDeconstructedUSDInteropimplementation that:Phase 3: State updates and UX
Phase 4: Tests
DocumentEditorFeatureTests:ProjectBrowserFeatureTests/UI-level tests:SceneGraph/SceneEdittests (or dependency-driven unit tests):Acceptance criteria
Risks / unknowns
RealityKitStageViewpackage may need a small API extension if we need true in-viewport drop coordinates/hit testing (for future placement).Out of scope (for this ticket)