HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
primRange.h
Go to the documentation of this file.
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_USD_PRIM_RANGE_H
25 #define PXR_USD_USD_PRIM_RANGE_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/usd/api.h"
29 #include "pxr/usd/usd/common.h"
30 #include "pxr/usd/usd/prim.h"
31 #include "pxr/usd/usd/primFlags.h"
32 
33 #include <vector>
34 #include <iterator>
35 
37 
38 /// \class UsdPrimRange
39 ///
40 /// An forward-iterable range that traverses a subtree of prims rooted at a
41 /// given prim in depth-first order.
42 ///
43 /// In addition to depth-first order, UsdPrimRange provides the optional ability
44 /// to traverse in depth-first pre- and post-order wher prims appear twice in
45 /// the range; first before all descendants and then again immediately after all
46 /// descendants. This is useful for maintaining state associated with subtrees,
47 /// in a stack-like fashion. See UsdPrimRange::iterator::IsPostVisit() to
48 /// detect when an iterator is visiting a prim for the second time.
49 ///
50 /// There are several constructors providing different levels of
51 /// configurability; ultimately, one can provide a prim predicate for a custom
52 /// iteration, just as one would use UsdPrim::GetFilteredChildren() in a custom
53 /// recursion.
54 ///
55 /// Why would one want to use a UsdPrimRange rather than just iterating
56 /// over the results of UsdPrim::GetFilteredDescendants() ? Primarily, if
57 /// one of the following applies:
58 /// \li You need to perform pre-and-post-order processing
59 /// \li You may want to prune sub-trees from processing (see UsdPrimRange::iterator::PruneChildren())
60 /// \li You want to treat the root prim itself uniformly with its
61 /// descendents (GetFilteredDescendants() will not return the root prim itself,
62 /// while UsdPrimRange will - see UsdPrimRange::Stage for an exception).
63 ///
64 /// <b>Using UsdPrimRange in C++</b>
65 ///
66 /// UsdPrimRange provides standard container-like semantics. For example:
67 /// \code
68 /// // simple range-for iteration
69 /// for (UsdPrim prim: UsdPrimRange(rootPrim)) {
70 /// ProcessPrim(prim);
71 /// }
72 ///
73 /// // using stl algorithms
74 /// std::vector<UsdPrim> meshes;
75 /// auto range = stage->Traverse();
76 /// std::copy_if(range.begin(), range.end(), std::back_inserter(meshes),
77 /// [](UsdPrim const &) { return prim.IsA<UsdGeomMesh>(); });
78 ///
79 /// // iterator-based iterating, with subtree pruning
80 /// UsdPrimRange range(rootPrim);
81 /// for (auto iter = range.begin(); iter != range.end(); ++iter) {
82 /// if (UsdModelAPI(*iter).GetKind() == KindTokens->component) {
83 /// iter.PruneChildren();
84 /// }
85 /// else {
86 /// nonComponents.push_back(*iter);
87 /// }
88 /// }
89 /// \endcode
90 ///
91 /// <b>Using Usd.PrimRange in python</b>
92 ///
93 /// The python wrapping for PrimRange is python-iterable, so it can
94 /// used directly as the object of a "for x in..." clause; however in that
95 /// usage one loses access to PrimRange methods such as PruneChildren() and
96 /// IsPostVisit(). Simply create the iterator outside the loop to overcome
97 /// this limitation. Finally, in python, prim predicates must be combined
98 /// with bit-wise operators rather than logical operators because the latter
99 /// are not overridable.
100 /// \code{.py}
101 /// # simple iteration
102 /// for prim in Usd.PrimRange(rootPrim):
103 /// ProcessPrim(prim)
104 ///
105 /// # filtered range using iterator to invoke iterator methods
106 /// it = iter(Usd.PrimRange.Stage(stage, Usd.PrimIsLoaded & ~Usd.PrimIsAbstract))
107 /// for prim in it:
108 /// if Usd.ModelAPI(prim).GetKind() == Kind.Tokens.component:
109 /// it.PruneChildren()
110 /// else:
111 /// nonComponents.append(prim)
112 /// \endcode
113 ///
114 /// Finally, since iterators in python are not directly dereferencable, we
115 /// provide the \em python \em only methods GetCurrentPrim() and IsValid(),
116 /// documented in the python help system.
117 ///
119 {
120 public:
121  class iterator;
122 
123  /// \class EndSentinel
124  ///
125  /// This class lets us represent past-the-end without the full weight of an
126  /// iterator.
127  class EndSentinel {
128  private:
129  friend class UsdPrimRange;
130  explicit EndSentinel(UsdPrimRange const *range) : _range(range) {}
132  UsdPrimRange const *_range;
133  };
134 
135  /// \class iterator
136  ///
137  /// A forward iterator into a UsdPrimRange. Iterators are valid for the
138  /// range they were obtained from. An iterator \em i obtained from a range
139  /// \em r is not valid for a range \em c copied from \em r.
140  class iterator {
142  class _PtrProxy {
143  public:
144  UsdPrim* operator->() { return &_prim; }
145  private:
146  friend class iterator;
147  explicit _PtrProxy(const UsdPrim& prim) : _prim(prim) {}
148  UsdPrim _prim;
149  };
150  public:
151  using iterator_category = std::forward_iterator_tag;
154  using pointer = _PtrProxy;
155  using difference_type = std::ptrdiff_t;
156 
157  iterator() = default;
158 
159  /// Allow implicit conversion from EndSentinel.
161  : _underlyingIterator(e._range->_end)
162  , _range(e._range) {}
163 
164  reference operator*() const { return dereference(); }
165  pointer operator->() const { return pointer(dereference()); }
166 
168  increment();
169  return *this;
170  }
171 
173  iterator result = *this;
174  increment();
175  return result;
176  }
177 
178  /// Return true if the iterator points to a prim visited the second time
179  /// (in post order) for a pre- and post-order iterator, false otherwise.
180  bool IsPostVisit() const { return _isPost; }
181 
182  /// Behave as if the current prim has no children when next advanced.
183  /// Issue an error if this is a pre- and post-order iterator that
184  /// IsPostVisit().
185  USD_API void PruneChildren();
186 
187  /// Return true if this iterator is equivalent to \p other.
188  inline bool operator==(iterator const &other) const {
189  return _range == other._range &&
190  _underlyingIterator == other._underlyingIterator &&
191  _proxyPrimPath == other._proxyPrimPath &&
192  _depth == other._depth &&
193  _pruneChildrenFlag == other._pruneChildrenFlag &&
194  _isPost == other._isPost;
195  }
196 
197  /// Return true if this iterator is equivalent to \p other.
198  inline bool operator==(EndSentinel const &other) const {
199  return _range == other._range &&
200  _underlyingIterator == _range->_end;
201  }
202 
203  /// Return true if this iterator is not equivalent to \p other.
204  inline bool operator!=(iterator const &other) const {
205  return !(*this == other);
206  }
207 
208  /// Return true if this iterator is not equivalent to \p other.
209  inline bool operator!=(EndSentinel const &other) const {
210  return !(*this == other);
211  }
212 
213  private:
214  friend class UsdPrimRange;
215 
216  iterator(UsdPrimRange const *range,
218  SdfPath proxyPrimPath,
219  unsigned int depth)
220  : _underlyingIterator(prim)
221  , _range(range)
222  , _proxyPrimPath(proxyPrimPath)
223  , _depth(depth) {}
224 
225  USD_API void increment();
226 
227  inline reference dereference() const {
228  return UsdPrim(_underlyingIterator, _proxyPrimPath);
229  }
230 
231  _UnderlyingIterator _underlyingIterator = nullptr;
232  UsdPrimRange const *_range = nullptr;
233  SdfPath _proxyPrimPath;
234  unsigned int _depth = 0;
235 
236  // True when the client has asked that the next increment skips the
237  // children of the current prim.
238  bool _pruneChildrenFlag = false;
239  // True when we're on the post-side of a prim. Unused if
240  // _range->_postOrder is false.
241  bool _isPost = false;
242  };
243 
245 
247  : _begin(nullptr)
248  , _end(nullptr)
249  , _initDepth(0)
250  , _postOrder(false) {}
251 
252  /// Construct a PrimRange that traverses the subtree rooted at \p start in
253  /// depth-first order, visiting prims that pass the default predicate (as
254  /// defined by #UsdPrimDefaultPredicate).
255  explicit UsdPrimRange(const UsdPrim &start) {
257  _Init(p, p ? p->GetNextPrim() : nullptr, start._ProxyPrimPath());
258  }
259 
260  /// Construct a PrimRange that traverses the subtree rooted at \p start in
261  /// depth-first order, visiting prims that pass \p predicate.
263  const Usd_PrimFlagsPredicate &predicate) {
265  _Init(p, p ? p->GetNextPrim() : nullptr,
266  start._ProxyPrimPath(), predicate);
267  }
268 
269  /// Create a PrimRange that traverses the subtree rooted at \p start in
270  /// depth-first order, visiting prims that pass the default predicate (as
271  /// defined by #UsdPrimDefaultPredicate) with pre- and post-order
272  /// visitation.
273  ///
274  /// Pre- and post-order visitation means that each prim appears
275  /// twice in the range; not only prior to all its descendants as with an
276  /// ordinary traversal but also immediately following its descendants. This
277  /// lets client code maintain state for subtrees. See
278  /// UsdPrimRange::iterator::IsPostVisit().
279  static UsdPrimRange
281  UsdPrimRange result(start);
282  result._postOrder = true;
283  return result;
284  }
285 
286  /// Create a PrimRange that traverses the subtree rooted at \p start in
287  /// depth-first order, visiting prims that pass \p predicate with pre- and
288  /// post-order visitation.
289  ///
290  /// Pre- and post-order visitation means that each prim appears
291  /// twice in the range; not only prior to all its descendants as with an
292  /// ordinary traversal but also immediately following its descendants. This
293  /// lets client code maintain state for subtrees. See
294  /// UsdPrimRange::iterator::IsPostVisit().
295  static UsdPrimRange
297  const Usd_PrimFlagsPredicate &predicate) {
298  UsdPrimRange result(start, predicate);
299  result._postOrder = true;
300  return result;
301  }
302 
303  /// Construct a PrimRange that traverses the subtree rooted at \p start in
304  /// depth-first order, visiting all prims (including deactivated, undefined,
305  /// and abstract prims).
306  static UsdPrimRange
308  return UsdPrimRange(start, UsdPrimAllPrimsPredicate);
309  }
310 
311  /// Construct a PrimRange that traverses the subtree rooted at \p start in
312  /// depth-first order, visiting all prims (including deactivated, undefined,
313  /// and abstract prims) with pre- and post-order visitation.
314  ///
315  /// Pre- and post-order visitation means that each prim appears
316  /// twice in the range; not only prior to all its descendants as with an
317  /// ordinary traversal but also immediately following its descendants. This
318  /// lets client code maintain state for subtrees. See
319  /// UsdPrimRange::iterator::IsPostVisit().
320  static UsdPrimRange
323  }
324 
325  /// Create a PrimRange that traverses all the prims on \p stage, and
326  /// visits those that pass the default predicate (as defined by
327  /// #UsdPrimDefaultPredicate).
328  USD_API
329  static UsdPrimRange
330  Stage(const UsdStagePtr &stage,
332 
333  /// Return an iterator to the start of this range.
334  iterator begin() const {
335  return iterator(this, _begin, _initProxyPrimPath, _initDepth);
336  }
337  /// Return a const_iterator to the start of this range.
339  return iterator(this, _begin, _initProxyPrimPath, _initDepth);
340  }
341 
342  /// Return the first element of this range. The range must not be empty().
343  UsdPrim front() const { return *begin(); }
344 
345  // XXX C++11 & 14 require that c/end() return the same type as c/begin() for
346  // range-based-for loops to work correctly. C++17 relaxes that requirement.
347  // Change the return type to EndSentinel once we are on C++17.
348 
349  /// Return the past-the-end iterator for this range.
350  iterator end() const { return EndSentinel(this); }
351  /// Return the past-the-end const_iterator for this range.
352  const_iterator cend() const { return EndSentinel(this); }
353 
354  /// Modify this range by advancing the beginning by one. The range must not
355  /// be empty, and the range must not be a pre- and post-order range.
357  set_begin(++begin());
358  }
359 
360  /// Set the start of this range to \p newBegin. The \p newBegin iterator
361  /// must be within this range's begin() and end(), and must not have
362  /// UsdPrimRange::iterator::IsPostVisit() be true.
363  void set_begin(iterator const &newBegin) {
364  TF_VERIFY(!newBegin.IsPostVisit());
365  _begin = newBegin._underlyingIterator;
366  _initProxyPrimPath = newBegin._proxyPrimPath;
367  _initDepth = newBegin._depth;
368  }
369 
370  /// Return true if this range contains no prims, false otherwise.
371  bool empty() const { return begin() == end(); }
372 
373  /// Return true if this range contains one or more prims, false otherwise.
374  explicit operator bool() const { return !empty(); }
375 
376  /// Return true if this range is equivalent to \p other.
377  bool operator==(UsdPrimRange const &other) const {
378  return this == &other ||
379  (_begin == other._begin &&
380  _end == other._end &&
381  _initProxyPrimPath == other._initProxyPrimPath &&
382  _predicate == other._predicate &&
383  _postOrder == other._postOrder &&
384  _initDepth == other._initDepth);
385  }
386 
387  /// Return true if this range is not equivalent to \p other.
388  bool operator!=(UsdPrimRange const &other) const {
389  return !(*this == other);
390  }
391 
392 private:
395  const SdfPath& proxyPrimPath,
396  const Usd_PrimFlagsPredicate &predicate =
398  _Init(begin, end, proxyPrimPath, predicate);
399  }
400 
401  ////////////////////////////////////////////////////////////////////////
402  // Helpers.
403  void _Init(const Usd_PrimData *first,
404  const Usd_PrimData *last,
405  const SdfPath &proxyPrimPath,
406  const Usd_PrimFlagsPredicate &predicate =
408  _begin = first;
409  _end = last;
410  _initProxyPrimPath = proxyPrimPath;
411  _predicate = _begin ?
412  Usd_CreatePredicateForTraversal(_begin, proxyPrimPath, predicate) :
413  predicate;
414  _postOrder = false;
415  _initDepth = 0;
416 
417  // Advance to the first prim that passes the predicate.
418  iterator b = begin();
419  if (b._underlyingIterator != _end &&
420  !Usd_EvalPredicate(_predicate, b._underlyingIterator,
421  proxyPrimPath)) {
422  b._pruneChildrenFlag = true;
423  set_begin(++b);
424  }
425  }
426 
427  ////////////////////////////////////////////////////////////////////////
428  // Data members.
429 
430  // These members are fixed for the life of the range.
431  Usd_PrimDataConstPtr _begin;
433  SdfPath _initProxyPrimPath;
434  Usd_PrimFlagsPredicate _predicate;
435  unsigned int _initDepth;
436  bool _postOrder;
437 };
438 
439 
441 
442 #endif // PXR_USD_USD_PRIM_RANGE_H
void increment_begin()
Definition: primRange.h:356
GLint first
Definition: glcorearb.h:405
static USD_API UsdPrimRange Stage(const UsdStagePtr &stage, const Usd_PrimFlagsPredicate &predicate=UsdPrimDefaultPredicate)
GLenum GLint * range
Definition: glcorearb.h:1925
Usd_PrimFlagsPredicate Usd_CreatePredicateForTraversal(const PrimDataPtr &p, const SdfPath &proxyPrimPath, Usd_PrimFlagsPredicate pred)
Definition: primData.h:498
#define USD_API
Definition: api.h:40
GLuint start
Definition: glcorearb.h:475
static UsdPrimRange PreAndPostVisit(const UsdPrim &start)
Definition: primRange.h:280
reference operator*() const
Definition: primRange.h:164
**But if you need a result
Definition: thread.h:613
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:83
iterator(EndSentinel e)
Allow implicit conversion from EndSentinel.
Definition: primRange.h:160
iterator & operator++()
Definition: primRange.h:167
Usd_PrimDataPtr GetNextPrim() const
Return this prim's parent prim. Return nullptr if this is a root prim.
Definition: primData.h:223
std::forward_iterator_tag iterator_category
Definition: primRange.h:151
bool operator!=(iterator const &other) const
Return true if this iterator is not equivalent to other.
Definition: primRange.h:204
bool operator!=(UsdPrimRange const &other) const
Return true if this range is not equivalent to other.
Definition: primRange.h:388
GLuint GLuint end
Definition: glcorearb.h:475
bool operator==(UsdPrimRange const &other) const
Return true if this range is equivalent to other.
Definition: primRange.h:377
Definition: prim.h:133
const SdfPath & _ProxyPrimPath() const
Definition: object.h:734
pointer operator->() const
Definition: primRange.h:165
Definition: path.h:290
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
USD_API void PruneChildren()
std::ptrdiff_t difference_type
Definition: primRange.h:155
const Usd_PrimData * Usd_PrimDataConstPtr
static UsdPrimRange AllPrims(const UsdPrim &start)
Definition: primRange.h:307
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glcorearb.h:476
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
const Usd_PrimDataHandle & _Prim() const
Definition: object.h:728
USD_API const Usd_PrimFlagsConjunction UsdPrimDefaultPredicate
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
USD_API const Usd_PrimFlagsPredicate UsdPrimAllPrimsPredicate
UsdPrimRange(const UsdPrim &start, const Usd_PrimFlagsPredicate &predicate)
Definition: primRange.h:262
UsdPrim front() const
Return the first element of this range. The range must not be empty().
Definition: primRange.h:343
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
UsdPrimRange(const UsdPrim &start)
Definition: primRange.h:255
bool operator==(EndSentinel const &other) const
Return true if this iterator is equivalent to other.
Definition: primRange.h:198
const_iterator cbegin() const
Return a const_iterator to the start of this range.
Definition: primRange.h:338
iterator end() const
Return the past-the-end iterator for this range.
Definition: primRange.h:350
bool operator==(iterator const &other) const
Return true if this iterator is equivalent to other.
Definition: primRange.h:188
bool operator!=(EndSentinel const &other) const
Return true if this iterator is not equivalent to other.
Definition: primRange.h:209
iterator operator++(int)
Definition: primRange.h:172
void set_begin(iterator const &newBegin)
Definition: primRange.h:363
const_iterator cend() const
Return the past-the-end const_iterator for this range.
Definition: primRange.h:352
bool IsPostVisit() const
Definition: primRange.h:180
iterator begin() const
Return an iterator to the start of this range.
Definition: primRange.h:334
static UsdPrimRange PreAndPostVisit(const UsdPrim &start, const Usd_PrimFlagsPredicate &predicate)
Definition: primRange.h:296
static UsdPrimRange AllPrimsPreAndPostVisit(const UsdPrim &start)
Definition: primRange.h:321
bool empty() const
Return true if this range contains no prims, false otherwise.
Definition: primRange.h:371