primRange.h
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 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
119 {
120 public:
121  class iterator;
122 
127  class EndSentinel {
128  private:
129  friend class UsdPrimRange;
130  explicit EndSentinel(UsdPrimRange const *range) : _range(range) {}
131  friend class UsdPrimRange::iterator;
132  UsdPrimRange const *_range;
133  };
134 
140  class iterator : public boost::iterator_adaptor<
141  iterator, // crtp base.
142  Usd_PrimDataConstPtr, // base iterator.
143  UsdPrim, // value type.
144  boost::forward_traversal_tag, // traversal.
145  UsdPrim> // reference type.
146  {
147  public:
148  iterator() : iterator_adaptor_(nullptr) {}
149 
152  : iterator_adaptor_(e._range->_end)
153  , _range(e._range) {}
154 
157  bool IsPostVisit() const { return _isPost; }
158 
162  USD_API void PruneChildren();
163 
165  inline bool operator==(iterator const &other) const {
166  return _range == other._range &&
167  base() == other.base() &&
168  _proxyPrimPath == other._proxyPrimPath &&
169  _depth == other._depth &&
170  _pruneChildrenFlag == other._pruneChildrenFlag &&
171  _isPost == other._isPost;
172  }
173 
175  inline bool operator==(EndSentinel const &other) const {
176  return _range == other._range && base() == _range->_end;
177  }
178 
180  inline bool operator!=(iterator const &other) const {
181  return !(*this == other);
182  }
183 
185  inline bool operator!=(EndSentinel const &other) const {
186  return !(*this == other);
187  }
188 
189  private:
190  friend class UsdPrimRange;
191  friend class boost::iterator_core_access;
192 
193  iterator(UsdPrimRange const *range,
194  Usd_PrimDataConstPtr prim,
195  SdfPath proxyPrimPath,
196  unsigned int depth)
197  : iterator_adaptor_(prim)
198  , _range(range)
199  , _proxyPrimPath(proxyPrimPath)
200  , _depth(depth) {}
201 
202  USD_API void increment();
203 
204  inline reference dereference() const {
205  return UsdPrim(base(), _proxyPrimPath);
206  }
207 
208  UsdPrimRange const *_range = nullptr;
209  SdfPath _proxyPrimPath;
210  unsigned int _depth = 0;
211 
212  // True when the client has asked that the next increment skips the
213  // children of the current prim.
214  bool _pruneChildrenFlag = false;
215  // True when we're on the post-side of a prim. Unused if
216  // _range->_postOrder is false.
217  bool _isPost = false;
218  };
219 
220  using const_iterator = iterator;
221 
222  UsdPrimRange()
223  : _begin(nullptr)
224  , _end(nullptr)
225  , _initDepth(0)
226  , _postOrder(false) {}
227 
231  explicit UsdPrimRange(const UsdPrim &start) {
232  Usd_PrimDataConstPtr p = get_pointer(start._Prim());
233  _Init(p, p ? p->GetNextPrim() : nullptr, start._ProxyPrimPath());
234  }
235 
238  UsdPrimRange(const UsdPrim &start,
239  const Usd_PrimFlagsPredicate &predicate) {
240  Usd_PrimDataConstPtr p = get_pointer(start._Prim());
241  _Init(p, p ? p->GetNextPrim() : nullptr,
242  start._ProxyPrimPath(), predicate);
243  }
244 
255  static UsdPrimRange
256  PreAndPostVisit(const UsdPrim &start) {
257  UsdPrimRange result(start);
258  result._postOrder = true;
259  return result;
260  }
261 
271  static UsdPrimRange
272  PreAndPostVisit(const UsdPrim &start,
273  const Usd_PrimFlagsPredicate &predicate) {
274  UsdPrimRange result(start, predicate);
275  result._postOrder = true;
276  return result;
277  }
278 
282  static UsdPrimRange
283  AllPrims(const UsdPrim &start) {
284  return UsdPrimRange(start, UsdPrimAllPrimsPredicate);
285  }
286 
296  static UsdPrimRange
299  }
300 
304  USD_API
305  static UsdPrimRange
306  Stage(const UsdStagePtr &stage,
307  const Usd_PrimFlagsPredicate &predicate = UsdPrimDefaultPredicate);
308 
310  iterator begin() const {
311  return iterator(this, _begin, _initProxyPrimPath, _initDepth);
312  }
315  return iterator(this, _begin, _initProxyPrimPath, _initDepth);
316  }
317 
319  UsdPrim front() const { return *begin(); }
320 
321  // XXX C++11 & 14 require that c/end() return the same type as c/begin() for
322  // range-based-for loops to work correctly. C++17 relaxes that requirement.
323  // Change the return type to EndSentinel once we are on C++17.
324 
326  iterator end() const { return EndSentinel(this); }
328  const_iterator cend() const { return EndSentinel(this); }
329 
333  set_begin(++begin());
334  }
335 
339  void set_begin(iterator const &newBegin) {
340  TF_VERIFY(!newBegin.IsPostVisit());
341  _begin = newBegin.base();
342  _initProxyPrimPath = newBegin._proxyPrimPath;
343  _initDepth = newBegin._depth;
344  }
345 
347  bool empty() const { return begin() == end(); }
348 
350  explicit operator bool() const { return !empty(); }
351 
353  bool operator==(UsdPrimRange const &other) const {
354  return this == &other ||
355  (_begin == other._begin &&
356  _end == other._end &&
357  _initProxyPrimPath == other._initProxyPrimPath &&
358  _predicate == other._predicate &&
359  _postOrder == other._postOrder &&
360  _initDepth == other._initDepth);
361  }
362 
364  bool operator!=(UsdPrimRange const &other) const {
365  return !(*this == other);
366  }
367 
368 private:
369  UsdPrimRange(Usd_PrimDataConstPtr begin,
370  Usd_PrimDataConstPtr end,
371  const SdfPath& proxyPrimPath,
372  const Usd_PrimFlagsPredicate &predicate =
374  _Init(begin, end, proxyPrimPath, predicate);
375  }
376 
378  // Helpers.
379  void _Init(const Usd_PrimData *first,
380  const Usd_PrimData *last,
381  const SdfPath &proxyPrimPath,
382  const Usd_PrimFlagsPredicate &predicate =
384  _begin = first;
385  _end = last;
386  _initProxyPrimPath = proxyPrimPath;
387  _predicate = _begin ?
388  Usd_CreatePredicateForTraversal(_begin, proxyPrimPath, predicate) :
389  predicate;
390  _postOrder = false;
391  _initDepth = 0;
392 
393  // Advance to the first prim that passes the predicate.
394  iterator b = begin();
395  if (b.base() != _end &&
396  !Usd_EvalPredicate(_predicate, b.base(), proxyPrimPath)) {
397  b._pruneChildrenFlag = true;
398  set_begin(++b);
399  }
400  }
401 
403  // Data members.
404 
405  // These members are fixed for the life of the range.
406  Usd_PrimDataConstPtr _begin;
407  Usd_PrimDataConstPtr _end;
408  SdfPath _initProxyPrimPath;
409  Usd_PrimFlagsPredicate _predicate;
410  unsigned int _initDepth;
411  bool _postOrder;
412 };
413 
414 
415 PXR_NAMESPACE_CLOSE_SCOPE
416 
417 #endif // PXR_USD_USD_PRIM_RANGE_H
unspecified UsdPrimDefaultPredicate
The default predicate used for prim traversals in methods like UsdPrim::GetChildren,...
bool empty() const
Return true if this range contains no prims, false otherwise.
Definition: primRange.h:347
const_iterator cend() const
Return the past-the-end const_iterator for this range.
Definition: primRange.h:328
This class lets us represent past-the-end without the full weight of an iterator.
Definition: primRange.h:127
static UsdPrimRange AllPrimsPreAndPostVisit(const UsdPrim &start)
Construct a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:297
iterator end() const
Return the past-the-end iterator for this range.
Definition: primRange.h:326
void set_begin(iterator const &newBegin)
Set the start of this range to newBegin.
Definition: primRange.h:339
UsdPrimRange(const UsdPrim &start, const Usd_PrimFlagsPredicate &predicate)
Construct a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:238
const_iterator cbegin() const
Return a const_iterator to the start of this range.
Definition: primRange.h:314
static UsdPrimRange AllPrims(const UsdPrim &start)
Construct a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:283
UsdPrim front() const
Return the first element of this range. The range must not be empty().
Definition: primRange.h:319
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:283
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
Definition: prim.h:132
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:288
USD_API void PruneChildren()
Behave as if the current prim has no children when next advanced.
bool operator!=(EndSentinel const &other) const
Return true if this iterator is not equivalent to other.
Definition: primRange.h:185
static USD_API UsdPrimRange Stage(const UsdStagePtr &stage, const Usd_PrimFlagsPredicate &predicate=UsdPrimDefaultPredicate)
Create a PrimRange that traverses all the prims on stage, and visits those that pass the default pred...
UsdPrimRange(const UsdPrim &start)
Construct a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:231
bool operator==(EndSentinel const &other) const
Return true if this iterator is equivalent to other.
Definition: primRange.h:175
iterator(EndSentinel e)
Allow implicit conversion from EndSentinel.
Definition: primRange.h:151
bool operator!=(UsdPrimRange const &other) const
Return true if this range is not equivalent to other.
Definition: primRange.h:364
An forward-iterable range that traverses a subtree of prims rooted at a given prim in depth-first ord...
Definition: primRange.h:118
void increment_begin()
Modify this range by advancing the beginning by one.
Definition: primRange.h:332
bool operator==(UsdPrimRange const &other) const
Return true if this range is equivalent to other.
Definition: primRange.h:353
static UsdPrimRange PreAndPostVisit(const UsdPrim &start)
Create a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:256
unspecified UsdPrimAllPrimsPredicate
Predicate that includes all prims.
bool operator==(iterator const &other) const
Return true if this iterator is equivalent to other.
Definition: primRange.h:165
bool IsPostVisit() const
Return true if the iterator points to a prim visited the second time (in post order) for a pre- and p...
Definition: primRange.h:157
iterator begin() const
Return an iterator to the start of this range.
Definition: primRange.h:310
static UsdPrimRange PreAndPostVisit(const UsdPrim &start, const Usd_PrimFlagsPredicate &predicate)
Create a PrimRange that traverses the subtree rooted at start in depth-first order,...
Definition: primRange.h:272
bool operator!=(iterator const &other) const
Return true if this iterator is not equivalent to other.
Definition: primRange.h:180
A forward iterator into a UsdPrimRange.
Definition: primRange.h:140