Add Maya-style Render Layer panel
Render layers built on the existing USD sublayer architecture: each layer is a file-backed SdfLayer mounted as a sublayer and tagged via custom layer data, with membership stored in a UsdCollectionAPI on a hidden /RenderLayerData prim. Activating a layer applies its overrides and isolates it to its members. "Default" is virtual -- it means all render-layer sublayers muted. See docs/adr/0002-render-layer.md for the design and rationale. - RenderLayerManager: create/delete/rename/activate, membership, mute-based isolation. Sdf-level APIs are used while a layer is muted (Usd-level APIs can't see muted layers) and Usd-level APIs when active. - Commands: create/delete/rename/activate and add/remove members, all undoable. - RenderLayerPanel: layer list with one-click activation and a membership editor for the selected prims. - StageEditorPanel / SceneHierarchyPanel: badge render-layer-owned sublayers, disable their mute/remove controls (they're managed from the Render Layer panel so the two can't desync), and lock the edit target while a non-Default layer is active. - ConnectShaderAttrs/DisconnectShaderAttr: take an explicit editLayer captured at construction, so undo targets the same layer as execute even if the ambient edit target changed in between (e.g. a render-layer switch). Note: SceneHierarchyPanel.h also carries declarations for the sublayers section added in the following commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "../utils/Logger.h"
|
||||
#include "../utils/FileDialog.h"
|
||||
#include "../utils/OcioConfigParser.h"
|
||||
#include <pxr/usd/usd/editContext.h>
|
||||
#include <pxr/usd/usdShade/shader.h>
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
#include <pxr/usd/usdShade/materialBindingAPI.h>
|
||||
@@ -1428,25 +1429,42 @@ void MaterialEditorPanel::BindMaterialToTarget(const pxr::SdfPath& materialPath,
|
||||
}
|
||||
|
||||
pxr::UsdStageRefPtr stage = m_stage;
|
||||
auto doBind = [stage, targetPath, materialPath]() {
|
||||
// Captured at construction time so Undo() lands in the same layer as
|
||||
// Execute() even if the ambient edit target changes in between (e.g. a
|
||||
// render-layer switch) — mirrors ConnectShaderAttrsCommand's pattern.
|
||||
pxr::SdfLayerHandle editLayer = m_stage->GetEditTarget().GetLayer();
|
||||
auto doBind = [stage, targetPath, materialPath, editLayer]() {
|
||||
pxr::UsdPrim target = stage->GetPrimAtPath(targetPath);
|
||||
pxr::UsdShadeMaterial material(stage->GetPrimAtPath(materialPath));
|
||||
if (target && material)
|
||||
if (!target || !material) return;
|
||||
if (editLayer) {
|
||||
pxr::UsdEditContext ec(stage, editLayer);
|
||||
pxr::UsdShadeMaterialBindingAPI::Apply(target).Bind(material);
|
||||
} else {
|
||||
pxr::UsdShadeMaterialBindingAPI::Apply(target).Bind(material);
|
||||
}
|
||||
};
|
||||
|
||||
if (m_commandHistory) {
|
||||
m_commandHistory->Push(std::make_unique<AttributeSetCommand>(
|
||||
"Bind Material",
|
||||
doBind,
|
||||
[stage, targetPath, hadPriorRel, priorTargets]() {
|
||||
[stage, targetPath, hadPriorRel, priorTargets, editLayer]() {
|
||||
pxr::UsdPrim target = stage->GetPrimAtPath(targetPath);
|
||||
if (!target) return;
|
||||
pxr::UsdShadeMaterialBindingAPI bindAPI(target);
|
||||
if (hadPriorRel && !priorTargets.empty())
|
||||
bindAPI.GetDirectBindingRel().SetTargets(priorTargets);
|
||||
else
|
||||
bindAPI.UnbindDirectBinding();
|
||||
auto doUnbind = [&]() {
|
||||
pxr::UsdShadeMaterialBindingAPI bindAPI(target);
|
||||
if (hadPriorRel && !priorTargets.empty())
|
||||
bindAPI.GetDirectBindingRel().SetTargets(priorTargets);
|
||||
else
|
||||
bindAPI.UnbindDirectBinding();
|
||||
};
|
||||
if (editLayer) {
|
||||
pxr::UsdEditContext ec(stage, editLayer);
|
||||
doUnbind();
|
||||
} else {
|
||||
doUnbind();
|
||||
}
|
||||
}
|
||||
));
|
||||
} else {
|
||||
@@ -2355,9 +2373,13 @@ pxr::SdfPath MaterialEditorPanel::CreateShaderNode(const std::string& shaderId,
|
||||
void MaterialEditorPanel::CreateConnection(const PinInfo& destInput, const PinInfo& sourceOutput) {
|
||||
if (!m_stage || !m_commandHistory) return;
|
||||
|
||||
// Captured now so Undo() (which may run after the ambient edit target
|
||||
// has since changed, e.g. a render-layer switch) still targets the same
|
||||
// layer this connection was authored into.
|
||||
pxr::SdfLayerHandle editLayer = m_stage->GetEditTarget().GetLayer();
|
||||
m_commandHistory->Push(std::make_unique<ConnectShaderAttrsCommand>(
|
||||
m_stage, destInput.nodePath, destInput.name, destInput.typeName,
|
||||
sourceOutput.nodePath, sourceOutput.name, sourceOutput.typeName));
|
||||
sourceOutput.nodePath, sourceOutput.name, sourceOutput.typeName, editLayer));
|
||||
SyncFromUsd();
|
||||
}
|
||||
|
||||
@@ -2369,7 +2391,8 @@ void MaterialEditorPanel::DeleteNode(const pxr::SdfPath& nodePath) {
|
||||
|
||||
void MaterialEditorPanel::DisconnectAttr(const pxr::SdfPath& destNode, const std::string& destInput) {
|
||||
if (!m_stage || !m_commandHistory) return;
|
||||
m_commandHistory->Push(std::make_unique<DisconnectShaderAttrCommand>(m_stage, destNode, destInput));
|
||||
pxr::SdfLayerHandle editLayer = m_stage->GetEditTarget().GetLayer();
|
||||
m_commandHistory->Push(std::make_unique<DisconnectShaderAttrCommand>(m_stage, destNode, destInput, editLayer));
|
||||
SyncFromUsd();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user