Cycle each node through All -> Connected -> Collapsed -> All via a custom-drawn icon (filled-dot count encodes how much is shown: 3/2/1). Collapsed hides every pin on a side, linked or not, behind one connector nub; existing links now redirect to that nub too (EffectivePinId), so they visually converge like Hypershade's collapse view instead of only hiding unconnected pins. Also moved the connector nubs off the title row onto the node's bottom row. Persisted mode switches from a bool (uiShowAllPins) to an int (uiPinDisplayMode). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
USD Layer Manager
A C++17 / Windows desktop application providing a Maya Render Layers-style USD scene editor using OpenUSD v25.05, ImGui 1.92.7 (docking branch), and OpenGL 3.3 (via GLAD). Users can open, edit, and save USD files, manage layered stage overrides, inspect and edit prim properties, and interact with 3D scenes through a Hydra viewport.
Features
- Layer Stack Management — Create, reorder, mute/unmute sublayers with full undo support
- Scene Hierarchy — Browse prim tree with per-type SVG icons; create, delete, rename prims; add/replace references
- Property Editor — Maya Channel Box-style attribute editing with type-aware drag inputs, color pickers, and undoable transforms
- 3D Viewport — Hydra rendering via
UsdImagingGLEngineinto an offscreen FBO; switchable render delegates (Storm, Embree, Arnold, Cycles); grid overlay; selection bounding boxes; camera wireframes - Multi-Viewport — Single, horizontal split, vertical split, and quad layouts; per-tile camera and render settings; Space to maximize/restore
- Camera Control — Free orbital camera (tumble/truck/dolly) or drive from USD camera prims; auto near/far clipping; frame selection; correct camera prim orientation for Y-up and Z-up stages
- Transform Gizmo — Pure ImDrawList-based manipulator (translate/rotate/scale) in object or world space
- Undo/Redo — Full command history for prim creation/deletion, attribute edits, transform changes, and layer operations; Ctrl+Z / Ctrl+Y hotkeys; Edit menu integration
- Multi-select — Rectangular selection in viewport with cross-panel syncing
Dependencies
| Dependency | Version | Notes |
|---|---|---|
| OpenUSD | v25.05 | Prebuilt; found via FindOpenUSD.cmake |
| Dear ImGui | v1.92.7 | Docking branch; Win32 + OpenGL3 backends |
| GLAD | — | OpenGL 3.3 core loader |
| Python | 3.12 | Required by OpenUSD runtime (python312.dll) |
Optional Render Delegates
| Delegate | Renderer Version | Variable | Notes |
|---|---|---|---|
| hdEmbree | Embree 4.4.1 | HDEMBREE_USD_ROOT |
USD build with PXR_ENABLE_EMBREE_PLUGIN=ON; set EMBREE_LOCATION if Embree DLLs are not in HDEMBREE_USD_ROOT/bin |
| hdArnold | Arnold 7.4.0 (MtoA 5.5.0) | HDARNOLD_ROOT, ARNOLD_LOCATION |
arnold-usd install dir + MtoA root for ai.dll |
| hdCycles | Cycles 5.2.0 | WITH_CYCLES=ON |
Built from source under third_party/cycles via ExternalProject; requires MSVC |
All delegate paths are pre-configured in CMakePresets.json.
Build
Prerequisites
- Visual Studio 17 2022 (MSVC v143) with C++17 support
- CMake 3.20+
- Python 3.12 installed at
%LOCALAPPDATA%\Programs\Python\Python312\
Steps
cmake --preset default
cmake --build build --config Release
cmake --install build --config Release
The installed executable lives in install/bin/.
Presets — default (Release + tests), debug, release, no-tests.
Building with Cycles
WITH_CYCLES=ON is set in the default preset. The first build compiles Blender Cycles from third_party/cycles via ExternalProject — expect a significantly longer initial build. Subsequent builds are incremental.
Cycles runtime dependencies (embree4.dll, openvdb.dll, OpenImageDenoise.dll, tbb12.dll, etc.) are automatically deployed to the output directory by a post-build step. CRT DLLs bundled inside the Cycles install are excluded to avoid version conflicts with the app's own MSVC runtime.
Tests
cmake --build build --config Release
ctest --test-dir build -C Release
Architecture
src/
├── main.cpp — Entry point (plugin path init, app lifecycle)
├── core/ — USD business logic (no UI dependency)
│ ├── UsdStageManager — Stage open/create/save/close lifecycle
│ ├── LayerManager — Layer stack introspection and mutation
│ ├── PropertyManager — Property read/write via edit target with undo
│ ├── CommandHistory — Undo/redo stack for ICommand instances
│ ├── UsdSceneRenderer — Hydra rendering + picking + overlays
│ ├── ViewportCamera — Free / USD-camera-driven orbital camera
│ └── commands/ — ICommand subclasses for all mutable operations
│ ├── TransformCommand — Undoable translate/rotate/scale
│ ├── CreatePrimCommand — Undoable prim creation (with camera orientation)
│ ├── DeletePrimCommand — Undoable prim deletion (SdfCopySpec snapshot)
│ ├── AttributeSetCommand — Type-agnostic undoable attribute writes
│ ├── AddReferenceCommand — Undoable reference addition
│ ├── ReplaceReferenceCommand — Undoable reference replacement
│ └── LayerCommands — Create, remove, reorder sublayers
├── ui/ — ImGui panels and application shell
│ ├── Application — App shell (owns managers/panels, docking, menus)
│ ├── ImGuiContext — Win32+OpenGL+ImGui initialization and loop
│ ├── ViewportPanel — Viewport container (layout, divider drag, maximize)
│ ├── ViewportTile — Single viewport tile (camera, rendering, overlays, picking)
│ ├── SceneHierarchyPanel — Prim tree browser with context menus
│ ├── PropertyPanel — Attribute/transform editor (channel box-style)
│ ├── LayerPanel — Layer stack editor with modal dialogs
│ ├── TransformManipulator — ImDrawList gizmo (move/rotate/scale)
│ └── IconManager — SVG icon rasterization via NanoSVG
└── utils/ — Cross-cutting utilities
├── Logger — Thread-safe logging (file + console)
├── FileDialog — Win32 file open/save dialogs
├── PathUtils — Exe-relative path resolution
└── GLExt — GLAD extension initialization
Key Design Patterns
- Command Pattern — All mutable USD operations go through
ICommand→CommandHistoryfor undo/redo - Panel-Manager Separation — UI panels hold pointers to core managers but contain no USD layer/prim logic
- Callback Wiring — Cross-panel communication via
std::functioncallbacks (e.g. viewport pick → hierarchy select → property panel update) - Render-Delegate Plugability —
UsdSceneRenderercan switch Hydra render plugins at runtime - Gizmo as 2D Overlay —
TransformManipulatoruses pureImDrawListcalls (no GL resources), same approach as ImGuizmo
Project Configuration
| Config | Purpose |
|---|---|
cmake/modules/FindOpenUSD.cmake |
OpenUSD SDK discovery |
cmake/modules/FindImgui.cmake |
ImGui source integration |
cmake/modules/FindGlad.cmake |
GLAD loader setup |
CMakePresets.json |
Build presets (VS 17 2022, x64) |
AGENTS.md |
AI agent build/architecture guide |
.kilo/ |
Kilo AI configuration (commands, agents, skills) |
openspec/changes/ |
Feature proposals and implementation tracking |
Development Workflow
This project uses OpenSpec for feature development:
- Propose — Create a new change under
openspec/changes/<name>/withproposal.md,design.md,specs/, andtasks.md - Implement — Work through checkbox-tracked tasks in
tasks.md - Archive — Move completed changes to
openspec/archive/when done
Use Kilo's openspec-* skills to streamline this workflow.
Runtime Requirements
- Python 3.12 — OpenUSD requires
python312.dllat runtime. CMake copies it to the output directory viaPOST_BUILDcommands. - USD Plugin Path — The app scans
<exe_dir>/usd/forplugInfo.jsonand registers plugins viapxr::PlugRegistry. - Render delegate DLLs — hdEmbree, hdArnold, and hdCycles each bring their own runtime dependencies (Embree, Arnold SDK, Cycles libs). CMake
POST_BUILDsteps deploy all required DLLs next to the executable automatically.
Contributing
Before writing any OpenUSD API call, verify the API exists in the actual SDK:
findstr /r /s "FunctionName" third_party\OpenUSD_v25.05\include\
Always build and install before running tests:
cmake --build build --config Release
cmake --install build --config Release
ctest --test-dir build -C Release
License
See LICENSE file for details.