Skip to content

Add drag-and-drop from Project Browser to Stage viewport #5

@elkraneo

Description

@elkraneo

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:

  1. Determine insertion parent path (selected container prim if valid, else root).
  2. Create a new prim container (likely Xform) with a unique name.
  3. Author a USD reference/payload to the dropped asset path.
  4. Refresh stage + scene graph + inspector selection to the new prim.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions