Files
UsdLayerManager/src/core/commands/RenamePrimCommand.cpp
T
indigo b02a736da0 Fix prim expiry crashes and add context menu hierarchy ops
Crash fixes (expired UsdPrim after namespace edits):
- RenderPrimNode: early-out after rename commit (renamed flag + column cleanup)
- RenderPrimNode: early-out after context menu op expires prim (prim.IsValid() guard)
- RenderContextMenu: EndPopup+return when Unparent/Group expires prim mid-popup
- Child iteration: snapshot GetChildren() into vector before recursing to guard
  against live iterator invalidation from stage mutations deeper in the tree
- Rename: firstFrame guard prevents spurious IsItemDeactivated cancel on
  SetKeyboardFocusHere activation frame (fixes second-rename not working)
- RenamePrimCommand: check RenamePrim() return value, log if rejected

New features:
- Context menu Add Child submenu: create typed child prim under selection
- Context menu Unparent to Root: move prim to stage root (undo-able)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 03:43:01 +08:00

66 lines
2.2 KiB
C++

#include "RenamePrimCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/namespaceEditor.h>
#include <pxr/usd/usd/prim.h>
#include <pxr/base/tf/token.h>
PXR_NAMESPACE_USING_DIRECTIVE
namespace UsdLayerManager {
RenamePrimCommand::RenamePrimCommand(UsdStageRefPtr stage,
const SdfPath& primPath,
const std::string& newName)
: m_stage(stage)
, m_oldPath(primPath)
, m_oldName(primPath.GetName())
, m_newName(newName)
, m_description("Rename " + primPath.GetName() + " \xe2\x86\x92 " + newName)
{
m_newPath = primPath.GetParentPath().AppendChild(TfToken(newName));
}
void RenamePrimCommand::Execute() {
UsdPrim prim = m_stage->GetPrimAtPath(m_oldPath);
if (!prim.IsValid()) {
LOG_ERROR("RenamePrimCommand::Execute: prim not found: " + m_oldPath.GetString());
return;
}
UsdNamespaceEditor editor(m_stage);
if (!editor.RenamePrim(prim, TfToken(m_newName))) {
LOG_ERROR("RenamePrimCommand::Execute: RenamePrim() rejected for " + m_oldPath.GetString());
return;
}
std::string whyNot;
if (!editor.CanApplyEdits(&whyNot)) {
LOG_ERROR("RenamePrimCommand::Execute: cannot rename " + m_oldPath.GetString() + ": " + whyNot);
return;
}
if (!editor.ApplyEdits()) {
LOG_ERROR("RenamePrimCommand::Execute: ApplyEdits failed for " + m_oldPath.GetString());
}
}
void RenamePrimCommand::Undo() {
UsdPrim prim = m_stage->GetPrimAtPath(m_newPath);
if (!prim.IsValid()) {
LOG_ERROR("RenamePrimCommand::Undo: prim not found: " + m_newPath.GetString());
return;
}
UsdNamespaceEditor editor(m_stage);
if (!editor.RenamePrim(prim, TfToken(m_oldName))) {
LOG_ERROR("RenamePrimCommand::Undo: RenamePrim() rejected for " + m_newPath.GetString());
return;
}
std::string whyNot;
if (!editor.CanApplyEdits(&whyNot)) {
LOG_ERROR("RenamePrimCommand::Undo: cannot rename back " + m_newPath.GetString() + ": " + whyNot);
return;
}
if (!editor.ApplyEdits()) {
LOG_ERROR("RenamePrimCommand::Undo: ApplyEdits failed for " + m_newPath.GetString());
}
}
} // namespace UsdLayerManager