-
Notifications
You must be signed in to change notification settings - Fork 210
/
Copy pathUsdUndoDuplicateCommand.cpp
152 lines (121 loc) · 4.7 KB
/
UsdUndoDuplicateCommand.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Copyright 2019 Autodesk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "UsdUndoDuplicateCommand.h"
#include "private/UfeNotifGuard.h"
#include <mayaUsd/base/tokens.h>
#include <mayaUsd/ufe/Utils.h>
#include <mayaUsd/utils/loadRules.h>
#include <mayaUsdUtils/MergePrims.h>
#include <usdUfe/base/tokens.h>
#include <usdUfe/undo/UsdUndoBlock.h>
#include <usdUfe/utils/editRouter.h>
#include <usdUfe/utils/editRouterContext.h>
#include <usdUfe/utils/layers.h>
#include <usdUfe/utils/loadRules.h>
#include <usdUfe/utils/usdUtils.h>
#include <pxr/base/tf/token.h>
#include <pxr/usd/sdf/copyUtils.h>
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/stage.h>
#include <ufe/hierarchy.h>
#include <ufe/log.h>
#include <ufe/path.h>
#include <ufe/scene.h>
#include <ufe/sceneNotification.h>
#include <algorithm>
namespace MAYAUSD_NS_DEF {
namespace ufe {
UsdUndoDuplicateCommand::UsdUndoDuplicateCommand(const UsdSceneItem::Ptr& srcItem)
#ifdef UFE_V4_FEATURES_AVAILABLE
: Ufe::SceneItemResultUndoableCommand()
#else
: Ufe::UndoableCommand()
#endif
, _ufeSrcPath(srcItem->path())
{
auto srcPrim = srcItem->prim();
auto parentPrim = srcPrim.GetParent();
auto newName = uniqueChildName(parentPrim, srcPrim.GetName());
_usdDstPath = parentPrim.GetPath().AppendChild(TfToken(newName));
auto primSpec = UsdUfe::getDefiningPrimSpec(srcPrim);
if (primSpec)
_srcLayer = primSpec->GetLayer();
}
UsdUndoDuplicateCommand::~UsdUndoDuplicateCommand() { }
UsdUndoDuplicateCommand::Ptr UsdUndoDuplicateCommand::create(const UsdSceneItem::Ptr& srcItem)
{
return std::make_shared<UsdUndoDuplicateCommand>(srcItem);
}
UsdSceneItem::Ptr UsdUndoDuplicateCommand::duplicatedItem() const
{
return createSiblingSceneItem(_ufeSrcPath, _usdDstPath.GetElementString());
}
void UsdUndoDuplicateCommand::execute()
{
UsdUfe::InAddOrDeleteOperation ad;
UsdUndoBlock undoBlock(&_undoableItem);
auto prim = ufePathToPrim(_ufeSrcPath);
auto path = prim.GetPath();
auto stage = prim.GetStage();
OperationEditRouterContext ctx(UsdUfe::EditRoutingTokens->RouteDuplicate, prim);
_dstLayer = stage->GetEditTarget().GetLayer();
auto item = Ufe::Hierarchy::createItem(_ufeSrcPath);
MayaUsd::ufe::ReplicateExtrasToUSD extras;
extras.initRecursive(item);
// The loaded state of a model is controlled by the load rules of the stage.
// When duplicating a node, we want the new node to be in the same loaded
// state.
duplicateLoadRules(*stage, path, _usdDstPath);
// Make sure all necessary parent exists in the target layer, at least as over,
// otherwise SdfCopySepc will fail.
SdfJustCreatePrimInLayer(_dstLayer, _usdDstPath.GetParentPath());
// Retrieve the local layers around where the prim is defined and order them
// from weak to strong. That weak-to-strong order allows us to copy the weakest
// opinions first, so that they will get over-written by the stronger opinions.
SdfPrimSpecHandleVector authLayerAndPaths = getDefiningPrimStack(prim);
std::reverse(authLayerAndPaths.begin(), authLayerAndPaths.end());
MayaUsdUtils::MergePrimsOptions options;
options.verbosity = MayaUsdUtils::MergeVerbosity::None;
options.mergeChildren = true;
bool isFirst = true;
for (const SdfPrimSpecHandle& layerAndPath : authLayerAndPaths) {
const auto layer = layerAndPath->GetLayer();
const auto path = layerAndPath->GetPath();
const bool result = isFirst
? SdfCopySpec(layer, path, _dstLayer, _usdDstPath)
: mergePrims(stage, layer, path, stage, _dstLayer, _usdDstPath, options);
TF_VERIFY(
result,
"Failed to copy the USD prim at '%s' in layer '%s' to '%s'",
path.GetText(),
layer->GetDisplayName().c_str(),
_usdDstPath.GetText());
isFirst = false;
}
extras.finalize(MayaUsd::ufe::stagePath(stage), &path, &_usdDstPath);
}
void UsdUndoDuplicateCommand::undo()
{
UsdUfe::InAddOrDeleteOperation ad;
_undoableItem.undo();
}
void UsdUndoDuplicateCommand::redo()
{
UsdUfe::InAddOrDeleteOperation ad;
_undoableItem.redo();
}
} // namespace ufe
} // namespace MAYAUSD_NS_DEF