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