Vendor node editor in-tree; add material presets; debug drag regression

Move the imgui-node-editor subset the build actually compiles from
third_party/imgui-node-editor to src/ui/NodeEditor (version-controlled,
MIT LICENSE included). FindImguiNodeEditor.cmake points at the new
location; CMakeLists excludes src/ui/NodeEditor from UI_SOURCES so it
isn't compiled twice.

Material editor presets: a Presets menu (disabled with no open material)
builds a UsdPreviewSurface + UsdUVTexture graph fed by an st primvar
reader, or a MaterialX standard_surface + image graph fed by a texcoord
node. Each is one idempotent, undoable command that re-normalizes layout.
Create Material becomes an icon button. New nodes route through
FindFreeCanvasSpot so a creation never lands on top of an existing node
(overlapping nodes fight over the editor hit test and become undraggable).

Shader-ball preview: pick a previewable output (terminal or 3/4-component
color-like) instead of always the first output, so scalar-only nodes keep
the whole-material preview rather than failing Storm codegen. Per-shape
camera frame-fit margins and auto-clip framing.

Fixes: DeletePrimCommand::Undo recreates missing destination ancestors
before SdfCopySpec (parent material may have been deleted after the
command ran). ConfigWindowsMoveFromTitleBarOnly stops a content-area drag
in the node canvas from moving the whole Material Editor window.

Temporary (marked for removal once the node-editor drag regression is
diagnosed): main.cpp mirrors LOG_INFO to %APPDATA%\UsdLayerManager\
debug.log; a g_AxNodeEditorDebugLog hook in the vendored editor plus a
[NodeGraph] event-trace block in RenderNodeGraphCanvas dump click/drag/
selection/position-save state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 22:35:23 +08:00
parent 0f30e080e3
commit 038450a1ca
29 changed files with 13658 additions and 27 deletions
+20
View File
@@ -12,6 +12,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace UsdLayerManager {
@@ -82,6 +83,11 @@ private:
void RenderMaterialBrowser();
/// Creates a uniquely-named empty material under /Materials and opens it.
void CreateNewMaterial();
/// Preset graphs for the open material (one undoable command each):
/// UsdPreviewSurface + UsdUVTextures fed by an st primvar reader, or a
/// MaterialX standard_surface + image nodes fed by a texcoord node.
void CreateUsdPresetGraph();
void CreateMaterialXPresetGraph();
void RenderNodeGraphCanvas();
void RenderPreviewPanel();
void HandleCreateAndDelete();
@@ -89,6 +95,11 @@ private:
/// creates the highlighted node at canvasPos.
void RenderNodeSearchMenu(const ImVec2& canvasPos);
void CreateShaderNode(const std::string& shaderId, const ImVec2& canvasPos);
/// Nudges a creation point right until the new node's estimated rectangle
/// clears every existing node's rendered rectangle. Overlapping nodes
/// fight over the editor's hit test: the buried one becomes unmovable and
/// its pins unhoverable. Must be called with the editor context current.
ImVec2 FindFreeCanvasSpot(ImVec2 desired, const std::string& shaderId) const;
/// Binds an existing material to targetPath, undoably, restoring whatever
/// direct binding (if any) targetPath had before.
void BindMaterialToTarget(const pxr::SdfPath& materialPath, const pxr::SdfPath& targetPath);
@@ -153,6 +164,15 @@ private:
/// is only valid inside the editor's Begin/End).
std::string m_pendingCreateShaderId;
/// Debug event-trace state (see the logging block at the end of
/// RenderNodeGraphCanvas): whether the last LMB press landed on a node
/// rect, whether that press's drag-start has been logged yet, and the
/// editor NodeIds hit at press time (their live positions are logged on
/// every drag-move so a node that stops following the mouse is visible).
bool m_debugPressOnNode = false;
bool m_debugDragLogged = false;
std::vector<uintptr_t> m_debugDragNodeIds;
/// First node currently selected in the graph editor (empty = none);
/// drives the properties section under the preview.
pxr::SdfPath m_selectedNodePath;