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 #ifndef PXR_USD_PCP_NODE_H
25 #define PXR_USD_PCP_NODE_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/pcp/api.h"
29 #include "pxr/usd/pcp/types.h"
30 #include "pxr/usd/sdf/types.h"
31 #include "pxr/base/tf/iterator.h"
32 #include "pxr/base/tf/hashset.h"
33 
34 #include <boost/operators.hpp>
35 #include <boost/iterator/iterator_facade.hpp>
36 #include <boost/iterator/reverse_iterator.hpp>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 class PcpArc;
41 class PcpLayerStackSite;
42 class PcpMapExpression;
43 class PcpNodeRef;
44 class PcpNodeRef_ChildrenIterator;
45 class PcpNodeRef_ChildrenReverseIterator;
46 class PcpErrorBase;
47 typedef std::shared_ptr<PcpErrorBase> PcpErrorBasePtr;
48 
49 TF_DECLARE_WEAK_PTRS(PcpPrimIndex_Graph);
50 
51 /// \class PcpNodeRef
52 ///
53 /// PcpNode represents a node in an expression tree for compositing
54 /// scene description.
55 ///
56 /// A node represents the opinions from a particular site.  In addition,
57 /// it may have child nodes, representing nested expressions that are
58 /// composited over/under this node.
59 ///
60 /// Child nodes are stored and composited in strength order.
61 ///
62 /// Each node holds information about the arc to its parent.
63 /// This captures both the relative strength of the sub-expression
64 /// as well as any value-mapping needed, such as to rename opinions
65 /// from a model to use in a particular instance.
66 ///
67 class PcpNodeRef :
68     public boost::totally_ordered<PcpNodeRef>
69 {
70 public:
71     typedef PcpNodeRef_ChildrenIterator child_const_iterator;
72     typedef PcpNodeRef_ChildrenReverseIterator child_const_reverse_iterator;
73     typedef std::pair<child_const_iterator,
74                       child_const_iterator> child_const_range;
75 
PcpNodeRef()76     PcpNodeRef() : _graph(0), _nodeIdx(PCP_INVALID_INDEX) {}
77 
78     /// \name Operators / Miscellaneous
79     /// @{
80 
81     /// Returns true if this is a valid node reference, false otherwise.
82     typedef size_t PcpNodeRef::*UnspecifiedBoolType;
UnspecifiedBoolType()83     inline operator UnspecifiedBoolType() const {
84         return (_graph && _nodeIdx != PCP_INVALID_INDEX) ? &PcpNodeRef::_nodeIdx : 0;
85     }
86 
87     /// Returns true if this references the same node as \p rhs.
88     inline bool operator==(const PcpNodeRef& rhs) const {
89         return _nodeIdx == rhs._nodeIdx && _graph == rhs._graph;
90     }
91 
92     /// Returns true if this node is 'less' than \p rhs.
93     /// The ordering of nodes is arbitrary and does not indicate the relative
94     /// strength of the nodes.
95     PCP_API
96     bool operator<(const PcpNodeRef& rhs) const;
97 
98     /// Hash functor.
99     struct Hash {
operatorHash100         size_t operator()(const PcpNodeRef& rhs) const
101         { return (size_t)rhs.GetUniqueIdentifier(); }
102     };
103 
104     /// Returns the graph that this node belongs to.
105     PcpPrimIndex_GraphPtr GetOwningGraph() const;
106 
107     /// Returns a value that uniquely identifies this node.
108     PCP_API
109     void* GetUniqueIdentifier() const;
110 
111     /// @}
112 
113     /// \name Arc information
114     /// Information pertaining to the arcs connecting this node to its
115     /// parent and child nodes.
116     /// @{
117 
118     /// Returns the type of arc connecting this node to its parent node.
119     PCP_API
120     PcpArcType GetArcType() const;
121 
122     /// Returns this node's immediate parent node. Will return NULL if this
123     /// node is a root node.
124     PCP_API
125     PcpNodeRef GetParentNode() const;
126 
127     /// Returns an iterator range over the children nodes in strongest to
128     /// weakest order.
129     PCP_API
130     child_const_range GetChildrenRange() const;
131 
132     /// Inserts a new child node for \p site, connected to this node via
133     /// \p arc.
134     PCP_API
135     PcpNodeRef InsertChild(const PcpLayerStackSite& site, const PcpArc& arc,
136         PcpErrorBasePtr *error);
137 
138     /// Inserts \p subgraph as a child of this node, with the root node of
139     /// \p subtree connected to this node via \p arc.
140     PCP_API
141     PcpNodeRef InsertChildSubgraph(
142         const PcpPrimIndex_GraphPtr& subgraph, const PcpArc& arc,
143         PcpErrorBasePtr *error);
144 
145     /// Returns the immediate origin node for this node. The origin node
146     /// is the node that caused this node to be brought into the prim index.
147     /// In most cases, this is the same as the parent node. For implied
148     /// inherits, the origin is the node from which this node was propagated.
149     PCP_API
150     PcpNodeRef GetOriginNode() const;
151 
152     /// Walk up to the root origin node for this node. This is the very
153     /// first node that caused this node to be added to the graph. For
154     /// instance, the root origin node of an implied inherit is the
155     /// original inherit node.
156     PCP_API
157     PcpNodeRef GetOriginRootNode() const;
158 
159     /// Walk up to the root node of this expression.
160     PCP_API
161     PcpNodeRef GetRootNode() const;
162 
163     /// Returns mapping function used to translate paths and values from
164     /// this node to its parent node.
165     PCP_API
166     const PcpMapExpression& GetMapToParent() const;
167 
168     /// Returns mapping function used to translate paths and values from
169     /// this node directly to the root node.
170     PCP_API
171     const PcpMapExpression& GetMapToRoot() const;
172 
173     /// Returns this node's index among siblings with the same arc type
174     /// at this node's origin.
175     PCP_API
176     int GetSiblingNumAtOrigin() const;
177 
178     /// Returns the absolute namespace depth of the node that introduced
179     /// this node. Note that this does *not* count any variant selections.
180     PCP_API
181     int GetNamespaceDepth() const;
182 
183     /// Return the number of levels of namespace this node's site is
184     /// below the level at which it was introduced by an arc.
185     PCP_API
186     int GetDepthBelowIntroduction() const;
187 
188     /// Returns the path for this node's site when it was introduced.
189     PCP_API
190     SdfPath GetPathAtIntroduction() const;
191 
192     /// Get the path that introduced this node.
193     /// Specifically, this is the path the parent node had at the level
194     /// of namespace where this node was added as a child.
195     /// For a root node, this returns the absolute root path.
196     /// See also GetDepthBelowIntroduction().
197     PCP_API
198     SdfPath GetIntroPath() const;
199 
200     /// @}
201 
202     /// \name Node information
203     /// Information pertaining specifically to this node and the opinions
204     /// that it may or may not provide.
205     /// @{
206 
207     /// Get the site this node represents.
208     PCP_API
209     PcpLayerStackSite GetSite() const;
210 
211     /// Returns the path for the site this node represents.
212     PCP_API
213     const SdfPath& GetPath() const;
214 
215     /// Returns the layer stack for the site this node represents.
216     PCP_API
217     const PcpLayerStackRefPtr& GetLayerStack() const;
218 
219     /// Returns true if this node is the root node of the prim index graph.
220     PCP_API
221     bool IsRootNode() const;
222 
223     /// Returns true if this node is due to an ancestral opinion.
224     PCP_API
225     bool IsDueToAncestor() const;
226 
227     /// Get/set whether this node provides any symmetry opinions, either
228     /// directly or from a namespace ancestor.
229     PCP_API
230     void SetHasSymmetry(bool hasSymmetry);
231     PCP_API
232     bool HasSymmetry() const;
233 
234     /// Get/set the permission for this node. This indicates whether specs
235     /// on this node can be accessed from other nodes.
236     PCP_API
237     void SetPermission(SdfPermission perm);
238     PCP_API
239     SdfPermission GetPermission() const;
240 
241     /// Get/set whether this node is inert. An inert node never provides
242     /// any opinions to a prim index. Such a node may exist purely as a
243     /// marker to represent certain composition structure, but should never
244     /// contribute opinions.
245     PCP_API
246     void SetInert(bool inert);
247     PCP_API
248     bool IsInert() const;
249 
250     /// Get/set whether this node is culled. If a node is culled, it and
251     /// all descendant nodes provide no opinions to the index. A culled
252     /// node is also considered inert.
253     PCP_API
254     void SetCulled(bool culled);
255     PCP_API
256     bool IsCulled() const;
257 
258     /// Get/set whether this node is restricted. A restricted node is a
259     /// node that cannot contribute opinions to the index due to permissions.
260     PCP_API
261     void SetRestricted(bool restricted);
262     PCP_API
263     bool IsRestricted() const;
264 
265     /// Returns true if this node is allowed to contribute opinions
266     /// for composition, false otherwise.
267     PCP_API
268     bool CanContributeSpecs() const;
269 
270     /// Returns true if this node has opinions authored
271     /// for composition, false otherwise.
272     PCP_API
273     void SetHasSpecs(bool hasSpecs);
274     PCP_API
275     bool HasSpecs() const;
276 
277     /// @}
278 
279     // Returns a compressed Sd site.  For internal use only.
GetCompressedSdSite(size_t layerIndex)280     Pcp_CompressedSdSite GetCompressedSdSite(size_t layerIndex) const
281     {
282         return Pcp_CompressedSdSite(_nodeIdx, layerIndex);
283     }
284 
285 private:
286     friend class PcpPrimIndex_Graph;
287     friend class PcpNodeIterator;
288     friend class PcpNodeRef_ChildrenIterator;
289     friend class PcpNodeRef_ChildrenReverseIterator;
290     friend class PcpNodeRef_PrivateChildrenConstIterator;
291     friend class PcpNodeRef_PrivateChildrenConstReverseIterator;
292 
293     // Private constructor for internal use.
PcpNodeRef(PcpPrimIndex_Graph * graph,size_t idx)294     PcpNodeRef(PcpPrimIndex_Graph* graph, size_t idx)
295         : _graph(graph), _nodeIdx(idx)
296     {}
297 
_GetNodeIndex()298     size_t _GetNodeIndex() const { return _nodeIdx; }
299 
300     size_t _GetParentIndex() const;
301     size_t _GetOriginIndex() const;
302 
303 private: // Data
304     PcpPrimIndex_Graph* _graph;
305     size_t _nodeIdx;
306 };
307 
308 /// Typedefs and support functions
309 inline
310 size_t
hash_value(const PcpNodeRef & x)311 hash_value(const PcpNodeRef& x)
312 {
313     return (size_t)x.GetUniqueIdentifier();
314 }
315 
316 typedef TfHashSet<PcpNodeRef, PcpNodeRef::Hash> PcpNodeRefHashSet;
317 typedef std::vector<PcpNodeRef> PcpNodeRefVector;
318 
319 /// \class PcpNodeRef_ChildrenIterator
320 ///
321 /// Object used to iterate over child nodes (not all descendant nodes) of a
322 /// node in the prim index graph in strong-to-weak order.
323 ///
324 class PcpNodeRef_ChildrenIterator
325     : public boost::iterator_facade<
326                  /* Derived =   */ PcpNodeRef_ChildrenIterator,
327                  /* ValueType = */ PcpNodeRef,
328                  /* Category =  */ boost::forward_traversal_tag,
329                  /* RefType =   */ PcpNodeRef
330              >
331 {
332 public:
333     /// Constructs an invalid iterator.
334     PCP_API
335     PcpNodeRef_ChildrenIterator();
336 
337     /// Constructs an iterator pointing to \p node. Passing a NULL value
338     /// for \p node constructs an end iterator.
339     PCP_API
340     PcpNodeRef_ChildrenIterator(const PcpNodeRef& node, bool end = false);
341 
342 private:
343     friend class boost::iterator_core_access;
344     PCP_API
345     void increment();
equal(const PcpNodeRef_ChildrenIterator & other)346     bool equal(const PcpNodeRef_ChildrenIterator& other) const
347     {
348         // Note: The default constructed iterator is *not* equal to any
349         //       other iterator.
350         return (_node == other._node && _index == other._index);
351     }
dereference()352     reference dereference() const
353     {
354         return reference(_node._graph, _index);
355     }
356 
357 private:
358     // Current graph node this iterator is pointing at.
359     PcpNodeRef _node;
360 
361     // Index of current child.
362     size_t _index;
363 
364     friend class PcpNodeRef_ChildrenReverseIterator;
365 };
366 
367 /// \class PcpNodeRef_ChildrenReverseIterator
368 ///
369 /// Object used to iterate over nodes in the prim index graph in weak-to-strong
370 /// order.
371 ///
372 class PcpNodeRef_ChildrenReverseIterator
373     : public boost::iterator_facade<
374                  /* Derived =   */ PcpNodeRef_ChildrenReverseIterator,
375                  /* ValueType = */ PcpNodeRef,
376                  /* Category =  */ boost::forward_traversal_tag,
377                  /* RefType =   */ PcpNodeRef
378              >
379 {
380 public:
381     /// Constructs an invalid iterator.
382     PCP_API
383     PcpNodeRef_ChildrenReverseIterator();
384 
385     /// Constructs a reverse iterator from a forward iterator.
386     PCP_API
387     PcpNodeRef_ChildrenReverseIterator(const PcpNodeRef_ChildrenIterator&);
388 
389     /// Constructs an iterator pointing to \p node. Passing a NULL value
390     /// for \p node constructs an end iterator.
391     PCP_API
392     PcpNodeRef_ChildrenReverseIterator(const PcpNodeRef& node,bool end = false);
393 
394 private:
395     friend class boost::iterator_core_access;
396     PCP_API
397     void increment();
equal(const PcpNodeRef_ChildrenReverseIterator & other)398     bool equal(const PcpNodeRef_ChildrenReverseIterator& other) const
399     {
400         // Note: The default constructed iterator is *not* equal to any
401         //       other iterator.
402         return (_node == other._node && _index == other._index);
403     }
dereference()404     reference dereference() const
405     {
406         return reference(_node._graph, _index);
407     }
408 
409 private:
410     // Current graph node this iterator is pointing at.
411     PcpNodeRef _node;
412 
413     // Index of current child.
414     size_t _index;
415 };
416 
417 template <>
418 struct Tf_IteratorInterface<PcpNodeRef::child_const_range, false> {
419     typedef PcpNodeRef::child_const_iterator IteratorType;
420     static IteratorType Begin(PcpNodeRef::child_const_range const &c)
421     {
422         return c.first;
423     }
424     static IteratorType End(PcpNodeRef::child_const_range const &c)
425     {
426         return c.second;
427     }
428 };
429 
430 template <>
431 struct Tf_IteratorInterface<PcpNodeRef::child_const_range, true> {
432     typedef PcpNodeRef::child_const_reverse_iterator IteratorType;
433     static IteratorType Begin(PcpNodeRef::child_const_range const &c)
434     {
435         return c.second;
436     }
437     static IteratorType End(PcpNodeRef::child_const_range const &c)
438     {
439         return c.first;
440     }
441 };
442 
443 template <>
444 struct Tf_ShouldIterateOverCopy<PcpNodeRef::child_const_range> :
445     boost::true_type {};
446 
447 // Helper to count the non-variant path components of a path; equivalent
448 // to path.StripAllVariantSelections().GetPathElementCount() except
449 // this method avoids constructing a new SdfPath value.
450 int PcpNode_GetNonVariantPathElementCount(const SdfPath &path);
451 
452 PXR_NAMESPACE_CLOSE_SCOPE
453 
454 #endif // PXR_USD_PCP_NODE_H
455