1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "pxr/pxr.h"
26 #include "pxr/usd/pcp/node.h"
27 #include "pxr/usd/pcp/primIndex_Graph.h"
28
29 PXR_NAMESPACE_OPEN_SCOPE
30
31 static inline int _GetNonVariantPathElementCount(const SdfPath &path);
32
33 bool
operator <(const PcpNodeRef & rhs) const34 PcpNodeRef::operator<(const PcpNodeRef& rhs) const
35 {
36 if (_nodeIdx < rhs._nodeIdx)
37 return true;
38 if (_nodeIdx > rhs._nodeIdx)
39 return false;
40
41 return _graph < rhs._graph;
42 }
43
44 PcpPrimIndex_GraphPtr
GetOwningGraph() const45 PcpNodeRef::GetOwningGraph() const
46 {
47 return TfCreateWeakPtr(_graph);
48 }
49
50 void*
GetUniqueIdentifier() const51 PcpNodeRef::GetUniqueIdentifier() const
52 {
53 return _graph + _nodeIdx;
54 }
55
56 PcpNodeRef
InsertChildSubgraph(const PcpPrimIndex_GraphPtr & subgraph,const PcpArc & arc,PcpErrorBasePtr * error)57 PcpNodeRef::InsertChildSubgraph(
58 const PcpPrimIndex_GraphPtr& subgraph, const PcpArc& arc,
59 PcpErrorBasePtr *error)
60 {
61 return _graph->InsertChildSubgraph(*this, subgraph, arc, error);
62 }
63
64 PcpNodeRef
InsertChild(const PcpLayerStackSite & site,const PcpArc & arc,PcpErrorBasePtr * error)65 PcpNodeRef::InsertChild(const PcpLayerStackSite& site, const PcpArc& arc,
66 PcpErrorBasePtr *error)
67 {
68 return _graph->InsertChildNode(*this, site, arc, error);
69 }
70
71 PcpNodeRef
GetRootNode() const72 PcpNodeRef::GetRootNode() const
73 {
74 return _graph->GetRootNode();
75 }
76
77 PcpNodeRef
GetOriginRootNode() const78 PcpNodeRef::GetOriginRootNode() const
79 {
80 PcpNodeRef root(*this);
81 while (root.GetOriginNode() &&
82 root.GetOriginNode() != root.GetParentNode())
83 root = root.GetOriginNode();
84
85 return root;
86 }
87
88 #define PCP_DEFINE_GET_API(typeName, getter, varName) \
89 typeName PcpNodeRef::getter() const { \
90 const PcpPrimIndex_Graph::_Node& graphNode = \
91 _graph->_GetNode(_nodeIdx); \
92 return graphNode.varName; \
93 }
94
95 // Same as PCP_DEFINE_GET_API() except specifically for retrieving
96 // node indices. Consumers expect this to return -1 for an invalid
97 // node, so we need to specifically check for the _invalidNodeIndex
98 // value.
99 #define PCP_DEFINE_GET_NODE_API(typeName, getter, varName) \
100 typeName PcpNodeRef::getter() const { \
101 const PcpPrimIndex_Graph::_Node& graphNode = \
102 _graph->_GetNode(_nodeIdx); \
103 if (graphNode.varName == \
104 PcpPrimIndex_Graph::_Node::_invalidNodeIndex) \
105 return (typeName)-1; \
106 return graphNode.varName; \
107 }
108
109 #define PCP_DEFINE_SET_API(typeName, setter, varName) \
110 void PcpNodeRef::setter(typeName val) { \
111 const PcpPrimIndex_Graph::_Node& graphNode = \
112 _graph->_GetNode(_nodeIdx); \
113 if (graphNode.varName != val) { \
114 PcpPrimIndex_Graph::_Node& writeableGraphNode = \
115 _graph->_GetWriteableNode(_nodeIdx); \
116 writeableGraphNode.varName = val; \
117 } \
118 }
119
120 #define PCP_DEFINE_API(typeName, getter, setter, varName) \
121 PCP_DEFINE_GET_API(typeName, getter, varName) \
122 PCP_DEFINE_SET_API(typeName, setter, varName)
123
124 PCP_DEFINE_GET_API(PcpArcType, GetArcType, smallInts.arcType);
125 PCP_DEFINE_GET_API(int, GetNamespaceDepth, smallInts.arcNamespaceDepth);
126 PCP_DEFINE_GET_API(int, GetSiblingNumAtOrigin, smallInts.arcSiblingNumAtOrigin);
127 PCP_DEFINE_GET_API(const PcpMapExpression&, GetMapToParent, mapToParent);
128 PCP_DEFINE_GET_API(const PcpMapExpression&, GetMapToRoot, mapToRoot);
129
130 PCP_DEFINE_API(bool, HasSymmetry, SetHasSymmetry, smallInts.hasSymmetry);
131 PCP_DEFINE_API(SdfPermission, GetPermission, SetPermission, smallInts.permission);
132 PCP_DEFINE_API(bool, IsCulled, SetCulled, smallInts.culled);
133 PCP_DEFINE_API(bool, IsRestricted, SetRestricted, smallInts.permissionDenied);
134
135 PCP_DEFINE_SET_API(bool, SetInert, smallInts.inert);
136
137 PCP_DEFINE_GET_NODE_API(size_t, _GetParentIndex, smallInts.arcParentIndex);
138 PCP_DEFINE_GET_NODE_API(size_t, _GetOriginIndex, smallInts.arcOriginIndex);
139 PCP_DEFINE_GET_API(const PcpLayerStackRefPtr&, GetLayerStack, layerStack);
140
141 bool
HasSpecs() const142 PcpNodeRef::HasSpecs() const
143 {
144 // XXX: This VERIFY is too expensive here.
145 //TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size());
146 return _graph->_nodeHasSpecs[_nodeIdx];
147 }
148
149 void
SetHasSpecs(bool hasSpecs)150 PcpNodeRef::SetHasSpecs(bool hasSpecs)
151 {
152 TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size());
153 _graph->_nodeHasSpecs[_nodeIdx] = hasSpecs;
154 }
155
156 const SdfPath&
GetPath() const157 PcpNodeRef::GetPath() const
158 {
159 TF_VERIFY(_nodeIdx < _graph->_nodeSitePaths.size());
160 return _graph->_nodeSitePaths[_nodeIdx];
161 }
162
163 PcpLayerStackSite
GetSite() const164 PcpNodeRef::GetSite() const
165 {
166 return PcpLayerStackSite(GetLayerStack(), GetPath());
167 }
168
169 bool
IsRootNode() const170 PcpNodeRef::IsRootNode() const
171 {
172 return GetArcType() == PcpArcTypeRoot;
173 }
174
175 bool
IsInert() const176 PcpNodeRef::IsInert() const
177 {
178 const PcpPrimIndex_Graph::_Node& node = _graph->_GetNode(_nodeIdx);
179 bool inert = node.smallInts.inert, culled = node.smallInts.culled;
180 return inert || culled;
181 }
182
183 bool
CanContributeSpecs() const184 PcpNodeRef::CanContributeSpecs() const
185 {
186 // No permissions in Usd mode, so skip restriction check.
187 //
188 // The logic here is equivalent to:
189 // (!IsInert() and (IsUsd() or not IsRestricted()))
190 //
191 // but it looks at the bits directly instead of going through those public
192 // methods to avoid some unnecessary overhead. This method is heavily used
193 // so avoiding that overhead for the slight obfuscation is justified.
194
195 const PcpPrimIndex_Graph::_Node& node = _graph->_GetNode(_nodeIdx);
196 return !(node.smallInts.inert || node.smallInts.culled) &&
197 (!node.smallInts.permissionDenied || _graph->_data->usd);
198 }
199
200 int
GetDepthBelowIntroduction() const201 PcpNodeRef::GetDepthBelowIntroduction() const
202 {
203 const PcpNodeRef parent = GetParentNode();
204 if (!parent)
205 return 0;
206
207 return _GetNonVariantPathElementCount(parent.GetPath())
208 - GetNamespaceDepth();
209 }
210
211 bool
IsDueToAncestor() const212 PcpNodeRef::IsDueToAncestor() const
213 {
214 return GetDepthBelowIntroduction() > 0;
215 }
216
217 SdfPath
GetPathAtIntroduction() const218 PcpNodeRef::GetPathAtIntroduction() const
219 {
220 SdfPath pathAtIntroduction = GetPath();
221 for (int depth = GetDepthBelowIntroduction(); depth; --depth) {
222 while (pathAtIntroduction.IsPrimVariantSelectionPath()) {
223 // Skip over variant selections, since they do not
224 // constitute levels of namespace depth. We do not simply
225 // strip all variant selections here, because we want to
226 // retain variant selections ancestral to the path where
227 // this node was introduced.
228 pathAtIntroduction = pathAtIntroduction.GetParentPath();
229 }
230 pathAtIntroduction = pathAtIntroduction.GetParentPath();
231 }
232
233 return pathAtIntroduction;
234 }
235
236 SdfPath
GetIntroPath() const237 PcpNodeRef::GetIntroPath() const
238 {
239 // Start with the parent node's current path.
240 const PcpNodeRef parent = GetParentNode();
241 if (!parent)
242 return SdfPath::AbsoluteRootPath();
243 SdfPath introPath = parent.GetPath();
244
245 // Walk back up to the depth where this child was introduced.
246 for (int depth = GetDepthBelowIntroduction(); depth; --depth) {
247 while (introPath.IsPrimVariantSelectionPath()) {
248 // Skip over variant selections, since they do not
249 // constitute levels of namespace depth. We do not simply
250 // strip all variant selections here, because we want to
251 // retain variant selections ancestral to the path where
252 // this node was introduced.
253 introPath = introPath.GetParentPath();
254 }
255 introPath = introPath.GetParentPath();
256 }
257
258 return introPath;
259 }
260
261 PcpNodeRef::child_const_range
GetChildrenRange() const262 PcpNodeRef::GetChildrenRange() const
263 {
264 PcpNodeRef node(_graph, _nodeIdx);
265 return child_const_range(child_const_iterator(node, /* end = */ false),
266 child_const_iterator(node, /* end = */ true));
267 }
268
269 PcpNodeRef
GetParentNode() const270 PcpNodeRef::GetParentNode() const
271 {
272 const size_t parentIndex = _GetParentIndex();
273 return (parentIndex == PCP_INVALID_INDEX ?
274 PcpNodeRef() : PcpNodeRef(_graph, parentIndex));
275 }
276
277 PcpNodeRef
GetOriginNode() const278 PcpNodeRef::GetOriginNode() const
279 {
280 const size_t originIndex = _GetOriginIndex();
281 return (originIndex == PCP_INVALID_INDEX ?
282 PcpNodeRef() : PcpNodeRef(_graph, originIndex));
283 }
284
285 ////////////////////////////////////////////////////////////
286
PcpNodeRef_ChildrenIterator()287 PcpNodeRef_ChildrenIterator::PcpNodeRef_ChildrenIterator() :
288 _index(PcpPrimIndex_Graph::_Node::_invalidNodeIndex)
289 {
290 // Do nothing
291 }
292
PcpNodeRef_ChildrenIterator(const PcpNodeRef & node,bool end)293 PcpNodeRef_ChildrenIterator::PcpNodeRef_ChildrenIterator(
294 const PcpNodeRef& node, bool end) :
295 _node(node),
296 _index(!end ?
297 _node._graph->_GetNode(_node).smallInts.firstChildIndex :
298 PcpPrimIndex_Graph::_Node::_invalidNodeIndex)
299 {
300 // Do nothing
301 }
302
303 void
increment()304 PcpNodeRef_ChildrenIterator::increment()
305 {
306 _index = _node._graph->_GetNode(_index).smallInts.nextSiblingIndex;
307 }
308
PcpNodeRef_ChildrenReverseIterator()309 PcpNodeRef_ChildrenReverseIterator::PcpNodeRef_ChildrenReverseIterator() :
310 _index(PcpPrimIndex_Graph::_Node::_invalidNodeIndex)
311 {
312 // Do nothing
313 }
314
PcpNodeRef_ChildrenReverseIterator(const PcpNodeRef_ChildrenIterator & i)315 PcpNodeRef_ChildrenReverseIterator::PcpNodeRef_ChildrenReverseIterator(
316 const PcpNodeRef_ChildrenIterator& i) :
317 _node(i._node),
318 _index(i._index)
319 {
320 if (_index == PcpPrimIndex_Graph::_Node::_invalidNodeIndex) {
321 _index = _node._graph->_GetNode(_node).smallInts.lastChildIndex;
322 }
323 else {
324 increment();
325 }
326 }
327
PcpNodeRef_ChildrenReverseIterator(const PcpNodeRef & node,bool end)328 PcpNodeRef_ChildrenReverseIterator::PcpNodeRef_ChildrenReverseIterator(
329 const PcpNodeRef& node, bool end) :
330 _node(node),
331 _index(!end ?
332 _node._graph->_GetNode(_node).smallInts.lastChildIndex :
333 PcpPrimIndex_Graph::_Node::_invalidNodeIndex)
334 {
335 // Do nothing
336 }
337
338 void
increment()339 PcpNodeRef_ChildrenReverseIterator::increment()
340 {
341 _index = _node._graph->_GetNode(_index).smallInts.prevSiblingIndex;
342 }
343
344 int
PcpNode_GetNonVariantPathElementCount(const SdfPath & path)345 PcpNode_GetNonVariantPathElementCount(const SdfPath &path)
346 {
347 return _GetNonVariantPathElementCount(path);
348 }
349
350 static inline int
_GetNonVariantPathElementCount(const SdfPath & path)351 _GetNonVariantPathElementCount(const SdfPath &path)
352 {
353 //return path.StripAllVariantSelections().GetPathElementCount();
354 if (ARCH_UNLIKELY(path.ContainsPrimVariantSelection())) {
355 SdfPath cur(path);
356 int result = (!cur.IsPrimVariantSelectionPath());
357 cur = cur.GetParentPath();
358 for (; cur.ContainsPrimVariantSelection(); cur = cur.GetParentPath())
359 result += (!cur.IsPrimVariantSelectionPath());
360 return result + static_cast<int>(cur.GetPathElementCount());
361 } else {
362 return static_cast<int>(path.GetPathElementCount());
363 }
364 }
365
366 PXR_NAMESPACE_CLOSE_SCOPE
367