Init Repo

This commit is contained in:
2026-06-03 09:00:11 +08:00
commit 9be48d8b9e
155 changed files with 14827 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
#include "AddReferenceCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/references.h>
#include <pxr/base/tf/token.h>
namespace UsdLayerManager {
AddReferenceCommand::AddReferenceCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& xformPath,
const std::string& refFilePath)
: m_stage(stage)
, m_xformPath(xformPath)
, m_refFilePath(refFilePath)
, m_description("Add Reference " + refFilePath)
{
}
void AddReferenceCommand::Execute() {
if (!m_stage) return;
try {
pxr::UsdPrim xformPrim = m_stage->DefinePrim(m_xformPath, pxr::TfToken("Xform"));
if (!xformPrim.IsValid()) {
LOG_ERROR("AddReferenceCommand: failed to define Xform at " + m_xformPath.GetString());
return;
}
if (!xformPrim.GetReferences().AddReference(m_refFilePath))
LOG_ERROR("AddReferenceCommand: failed to add reference " + m_refFilePath);
} catch (const std::exception& e) {
LOG_ERROR(std::string("AddReferenceCommand::Execute error: ") + e.what());
}
}
void AddReferenceCommand::Undo() {
if (!m_stage) return;
try {
if (!m_stage->RemovePrim(m_xformPath))
LOG_ERROR("AddReferenceCommand::Undo: failed to remove prim " + m_xformPath.GetString());
} catch (const std::exception& e) {
LOG_ERROR(std::string("AddReferenceCommand::Undo error: ") + e.what());
}
}
} // namespace UsdLayerManager
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include "../CommandHistory.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/sdf/reference.h>
#include <string>
namespace UsdLayerManager {
/// Wraps adding an Xform prim + reference (stage-level "Add Reference..." action).
class AddReferenceCommand : public ICommand {
public:
AddReferenceCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& xformPath,
const std::string& refFilePath);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
pxr::UsdStageRefPtr m_stage;
pxr::SdfPath m_xformPath;
std::string m_refFilePath;
std::string m_description;
};
} // namespace UsdLayerManager
+14
View File
@@ -0,0 +1,14 @@
#include "AttributeSetCommand.h"
namespace UsdLayerManager {
AttributeSetCommand::AttributeSetCommand(std::string description,
std::function<void()> executeFunc,
std::function<void()> undoFunc)
: m_description(std::move(description))
, m_executeFunc(std::move(executeFunc))
, m_undoFunc(std::move(undoFunc))
{
}
} // namespace UsdLayerManager
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include "../CommandHistory.h"
#include <functional>
#include <string>
namespace UsdLayerManager {
/// Type-agnostic attribute set command.
/// Stores execute and undo as std::function closures capturing the typed values.
class AttributeSetCommand : public ICommand {
public:
AttributeSetCommand(std::string description,
std::function<void()> executeFunc,
std::function<void()> undoFunc);
void Execute() override { if (m_executeFunc) m_executeFunc(); }
void Undo() override { if (m_undoFunc) m_undoFunc(); }
std::string GetDescription() const override { return m_description; }
private:
std::string m_description;
std::function<void()> m_executeFunc;
std::function<void()> m_undoFunc;
};
} // namespace UsdLayerManager
+38
View File
@@ -0,0 +1,38 @@
#include "CreatePrimCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/prim.h>
namespace UsdLayerManager {
CreatePrimCommand::CreatePrimCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
const pxr::TfToken& typeName)
: m_stage(stage)
, m_primPath(primPath)
, m_typeName(typeName)
, m_description("Create " + typeName.GetString() + " " + primPath.GetString())
{
}
void CreatePrimCommand::Execute() {
if (!m_stage) return;
try {
pxr::UsdPrim prim = m_stage->DefinePrim(m_primPath, m_typeName);
if (!prim.IsValid())
LOG_ERROR("CreatePrimCommand: failed to define prim " + m_primPath.GetString());
} catch (const std::exception& e) {
LOG_ERROR(std::string("CreatePrimCommand::Execute error: ") + e.what());
}
}
void CreatePrimCommand::Undo() {
if (!m_stage) return;
try {
if (!m_stage->RemovePrim(m_primPath))
LOG_ERROR("CreatePrimCommand: failed to remove prim " + m_primPath.GetString());
} catch (const std::exception& e) {
LOG_ERROR(std::string("CreatePrimCommand::Undo error: ") + e.what());
}
}
} // namespace UsdLayerManager
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include "../CommandHistory.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/sdf/layer.h>
#include <pxr/base/tf/token.h>
#include <string>
namespace UsdLayerManager {
class CreatePrimCommand : public ICommand {
public:
CreatePrimCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
const pxr::TfToken& typeName);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
pxr::UsdStageRefPtr m_stage;
pxr::SdfPath m_primPath;
pxr::TfToken m_typeName;
std::string m_description;
};
} // namespace UsdLayerManager
+69
View File
@@ -0,0 +1,69 @@
#include "DeletePrimCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/sdf/copyUtils.h>
#include <pxr/usd/sdf/primSpec.h>
namespace UsdLayerManager {
DeletePrimCommand::DeletePrimCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath)
: m_stage(stage)
, m_primPath(primPath)
, m_description("Delete " + primPath.GetString())
{
if (!stage) return;
pxr::SdfLayerHandle rootLayer = stage->GetRootLayer();
if (!rootLayer) return;
// Only capture if the spec exists on the root layer.
if (!rootLayer->HasSpec(primPath)) {
LOG_ERROR("DeletePrimCommand: no spec found for " + primPath.GetString());
return;
}
m_savedLayer = pxr::SdfLayer::CreateAnonymous(".usda");
if (!m_savedLayer) return;
// Ensure the parent path hierarchy exists in the saved layer.
pxr::SdfPath parentPath = primPath.GetParentPath();
while (!parentPath.IsAbsoluteRootPath() && !m_savedLayer->HasSpec(parentPath)) {
pxr::SdfPrimSpec::New(m_savedLayer,
parentPath.GetName(),
pxr::SdfSpecifierOver);
parentPath = parentPath.GetParentPath();
}
if (pxr::SdfCopySpec(rootLayer, primPath, m_savedLayer, primPath)) {
m_specWasSaved = true;
} else {
LOG_ERROR("DeletePrimCommand: SdfCopySpec failed for " + primPath.GetString());
}
}
void DeletePrimCommand::Execute() {
if (!m_stage) return;
try {
if (!m_stage->RemovePrim(m_primPath))
LOG_ERROR("DeletePrimCommand: RemovePrim failed for " + m_primPath.GetString());
} catch (const std::exception& e) {
LOG_ERROR(std::string("DeletePrimCommand::Execute error: ") + e.what());
}
}
void DeletePrimCommand::Undo() {
if (!m_stage || !m_specWasSaved || !m_savedLayer) {
LOG_ERROR("DeletePrimCommand::Undo: cannot restore — spec was not saved");
return;
}
pxr::SdfLayerHandle rootLayer = m_stage->GetRootLayer();
if (!rootLayer) return;
try {
if (!pxr::SdfCopySpec(m_savedLayer, m_primPath, rootLayer, m_primPath))
LOG_ERROR("DeletePrimCommand::Undo: SdfCopySpec failed for " + m_primPath.GetString());
} catch (const std::exception& e) {
LOG_ERROR(std::string("DeletePrimCommand::Undo error: ") + e.what());
}
}
} // namespace UsdLayerManager
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "../CommandHistory.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/sdf/layer.h>
#include <string>
namespace UsdLayerManager {
/// Saves the prim spec via SdfCopySpec into an anonymous in-memory layer
/// before deletion; restores it on Undo.
class DeletePrimCommand : public ICommand {
public:
/// Captures the current spec of @p primPath from the root layer into an
/// anonymous layer. Must be constructed BEFORE the prim is removed.
DeletePrimCommand(pxr::UsdStageRefPtr stage, const pxr::SdfPath& primPath);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
pxr::UsdStageRefPtr m_stage;
pxr::SdfPath m_primPath;
pxr::SdfLayerRefPtr m_savedLayer; ///< anonymous layer holding the spec snapshot
std::string m_description;
bool m_specWasSaved = false;
};
} // namespace UsdLayerManager
+104
View File
@@ -0,0 +1,104 @@
#include "LayerCommands.h"
#include "../../utils/Logger.h"
namespace UsdLayerManager {
// ─── LayerCreateCommand ───────────────────────────────────────────────────────
LayerCreateCommand::LayerCreateCommand(LayerManager* mgr, std::string path, int index)
: m_mgr(mgr)
, m_path(std::move(path))
, m_index(index)
, m_description("Create Layer " + m_path)
{
}
void LayerCreateCommand::Execute() {
if (!m_mgr) return;
// Record how many sublayers exist before insert to compute the real index used.
auto before = m_mgr->GetLayerStack().size();
m_mgr->CreateSublayer(m_path, m_index);
auto after = m_mgr->GetLayerStack().size();
// If a layer was actually inserted, compute its index.
if (after > before) {
auto layers = m_mgr->GetLayerStack();
for (int i = 0; i < static_cast<int>(layers.size()); ++i) {
if (layers[i].identifier == m_path || layers[i].displayName == m_path) {
m_insertedIndex = i;
break;
}
}
}
}
void LayerCreateCommand::Undo() {
if (!m_mgr) return;
if (m_insertedIndex >= 0) {
m_mgr->RemoveSublayer(m_insertedIndex);
}
}
// ─── LayerRemoveCommand ───────────────────────────────────────────────────────
LayerRemoveCommand::LayerRemoveCommand(LayerManager* mgr, int index)
: m_mgr(mgr)
, m_index(index)
, m_description("Remove Layer")
{
if (!mgr) return;
auto layers = mgr->GetLayerStack();
if (index >= 0 && index < static_cast<int>(layers.size())) {
m_savedPath = layers[index].identifier;
m_description = "Remove Layer " + layers[index].displayName;
}
}
void LayerRemoveCommand::Execute() {
if (!m_mgr) return;
m_mgr->RemoveSublayer(m_index);
}
void LayerRemoveCommand::Undo() {
if (!m_mgr || m_savedPath.empty()) return;
// Re-insert at the original index.
m_mgr->InsertSublayerPath(m_savedPath, m_index);
}
// ─── LayerReorderCommand ──────────────────────────────────────────────────────
LayerReorderCommand::LayerReorderCommand(LayerManager* mgr,
std::vector<std::string> before,
std::vector<std::string> after)
: m_mgr(mgr)
, m_before(std::move(before))
, m_after(std::move(after))
, m_description("Reorder Layers")
{
}
void LayerReorderCommand::Execute() { ApplyOrder(m_after); }
void LayerReorderCommand::Undo() { ApplyOrder(m_before); }
void LayerReorderCommand::ApplyOrder(const std::vector<std::string>& order) {
if (!m_mgr) return;
// Remove all sublayers and re-insert in the desired order.
// We only control sublayers — root and session are fixed.
// First gather current sublayer indices (non-root, non-session).
auto layers = m_mgr->GetLayerStack();
// Count sublayers and remove them from highest index down.
std::vector<int> sublayerIndices;
for (int i = 0; i < static_cast<int>(layers.size()); ++i) {
if (!layers[i].isRootLayer && !layers[i].isSessionLayer)
sublayerIndices.push_back(i);
}
// Remove from back to front to preserve indices.
for (int i = static_cast<int>(sublayerIndices.size()) - 1; i >= 0; --i)
m_mgr->RemoveSublayer(sublayerIndices[i]);
// Re-add in desired order.
for (const auto& path : order)
m_mgr->InsertSublayerPath(path, -1);
}
} // namespace UsdLayerManager
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include "../CommandHistory.h"
#include "../LayerManager.h"
#include <string>
namespace UsdLayerManager {
class LayerCreateCommand : public ICommand {
public:
LayerCreateCommand(LayerManager* mgr, std::string path, int index = -1);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
LayerManager* m_mgr;
std::string m_path;
int m_index;
int m_insertedIndex = -1;
std::string m_description;
};
class LayerRemoveCommand : public ICommand {
public:
LayerRemoveCommand(LayerManager* mgr, int index);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
LayerManager* m_mgr;
int m_index;
std::string m_savedPath;
std::string m_description;
};
class LayerReorderCommand : public ICommand {
public:
LayerReorderCommand(LayerManager* mgr, std::vector<std::string> before, std::vector<std::string> after);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
void ApplyOrder(const std::vector<std::string>& order);
LayerManager* m_mgr;
std::vector<std::string> m_before;
std::vector<std::string> m_after;
std::string m_description;
};
} // namespace UsdLayerManager
@@ -0,0 +1,42 @@
#include "ReplaceReferenceCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/references.h>
namespace UsdLayerManager {
ReplaceReferenceCommand::ReplaceReferenceCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
const pxr::SdfReference& oldRef,
const pxr::SdfReference& newRef)
: m_stage(stage)
, m_primPath(primPath)
, m_oldRef(oldRef)
, m_newRef(newRef)
, m_description("Replace Reference on " + primPath.GetString())
{
}
void ReplaceReferenceCommand::Execute() { Apply(m_oldRef, m_newRef); }
void ReplaceReferenceCommand::Undo() { Apply(m_newRef, m_oldRef); }
void ReplaceReferenceCommand::Apply(const pxr::SdfReference& toRemove,
const pxr::SdfReference& toAdd)
{
if (!m_stage) return;
pxr::UsdPrim prim = m_stage->GetPrimAtPath(m_primPath);
if (!prim.IsValid()) {
LOG_ERROR("ReplaceReferenceCommand::Apply: prim not valid " + m_primPath.GetString());
return;
}
try {
pxr::UsdReferences refs = prim.GetReferences();
if (!refs.RemoveReference(toRemove))
LOG_ERROR("ReplaceReferenceCommand: failed to remove reference");
if (!refs.AddReference(toAdd))
LOG_ERROR("ReplaceReferenceCommand: failed to add reference");
} catch (const std::exception& e) {
LOG_ERROR(std::string("ReplaceReferenceCommand::Apply error: ") + e.what());
}
}
} // namespace UsdLayerManager
@@ -0,0 +1,32 @@
#pragma once
#include "../CommandHistory.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/sdf/reference.h>
#include <string>
namespace UsdLayerManager {
class ReplaceReferenceCommand : public ICommand {
public:
ReplaceReferenceCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
const pxr::SdfReference& oldRef,
const pxr::SdfReference& newRef);
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
void Apply(const pxr::SdfReference& toRemove, const pxr::SdfReference& toAdd);
pxr::UsdStageRefPtr m_stage;
pxr::SdfPath m_primPath;
pxr::SdfReference m_oldRef;
pxr::SdfReference m_newRef;
std::string m_description;
};
} // namespace UsdLayerManager
+67
View File
@@ -0,0 +1,67 @@
#include "TransformCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/editContext.h>
namespace UsdLayerManager {
TransformCommand::TransformCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
pxr::SdfLayerHandle editLayer,
const pxr::GfVec3d& oldTranslate,
const pxr::GfVec3f& oldRotate,
const pxr::GfVec3f& oldScale,
const pxr::GfVec3d& newTranslate,
const pxr::GfVec3f& newRotate,
const pxr::GfVec3f& newScale,
pxr::UsdGeomXformCommonAPI::RotationOrder rotOrder,
std::string description)
: m_stage(stage)
, m_primPath(primPath)
, m_editLayer(editLayer)
, m_oldTranslate(oldTranslate)
, m_oldRotate(oldRotate)
, m_oldScale(oldScale)
, m_newTranslate(newTranslate)
, m_newRotate(newRotate)
, m_newScale(newScale)
, m_rotOrder(rotOrder)
, m_description(std::move(description))
{
}
void TransformCommand::Execute() {
Apply(m_newTranslate, m_newRotate, m_newScale);
}
void TransformCommand::Undo() {
Apply(m_oldTranslate, m_oldRotate, m_oldScale);
}
void TransformCommand::Apply(const pxr::GfVec3d& t,
const pxr::GfVec3f& r,
const pxr::GfVec3f& s)
{
if (!m_stage || m_primPath.IsEmpty()) return;
pxr::UsdPrim prim = m_stage->GetPrimAtPath(m_primPath);
if (!prim) return;
pxr::UsdGeomXformCommonAPI api(prim);
if (!api) return;
try {
if (m_editLayer) {
pxr::UsdEditContext ec(m_stage, m_editLayer);
api.SetTranslate(t, pxr::UsdTimeCode::Default());
api.SetRotate(r, m_rotOrder, pxr::UsdTimeCode::Default());
api.SetScale(s, pxr::UsdTimeCode::Default());
} else {
api.SetTranslate(t, pxr::UsdTimeCode::Default());
api.SetRotate(r, m_rotOrder, pxr::UsdTimeCode::Default());
api.SetScale(s, pxr::UsdTimeCode::Default());
}
} catch (const std::exception& e) {
LOG_ERROR(std::string("TransformCommand::Apply error: ") + e.what());
}
}
} // namespace UsdLayerManager
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include "../CommandHistory.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/sdf/layer.h>
#include <pxr/base/gf/vec3d.h>
#include <pxr/base/gf/vec3f.h>
#include <pxr/usd/usdGeom/xformCommonAPI.h>
#include <string>
namespace UsdLayerManager {
/// Reverses a complete TRS edit on a single prim (from gizmo drag or
/// Property panel field commit). Stores the prim path, edit-target layer,
/// and pre/post translate/rotate/scale triples.
class TransformCommand : public ICommand {
public:
TransformCommand(pxr::UsdStageRefPtr stage,
const pxr::SdfPath& primPath,
pxr::SdfLayerHandle editLayer,
const pxr::GfVec3d& oldTranslate,
const pxr::GfVec3f& oldRotate,
const pxr::GfVec3f& oldScale,
const pxr::GfVec3d& newTranslate,
const pxr::GfVec3f& newRotate,
const pxr::GfVec3f& newScale,
pxr::UsdGeomXformCommonAPI::RotationOrder rotOrder,
std::string description = "Transform");
void Execute() override;
void Undo() override;
std::string GetDescription() const override { return m_description; }
private:
void Apply(const pxr::GfVec3d& t,
const pxr::GfVec3f& r,
const pxr::GfVec3f& s);
pxr::UsdStageRefPtr m_stage;
pxr::SdfPath m_primPath;
pxr::SdfLayerHandle m_editLayer;
pxr::GfVec3d m_oldTranslate;
pxr::GfVec3f m_oldRotate;
pxr::GfVec3f m_oldScale;
pxr::GfVec3d m_newTranslate;
pxr::GfVec3f m_newRotate;
pxr::GfVec3f m_newScale;
pxr::UsdGeomXformCommonAPI::RotationOrder m_rotOrder;
std::string m_description;
};
} // namespace UsdLayerManager