HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
primFlags.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_USD_PRIM_FLAGS_H
8 #define PXR_USD_USD_PRIM_FLAGS_H
9 
10 /// \file usd/primFlags.h
11 ///
12 /// \anchor Usd_PrimFlags
13 ///
14 /// Provides terms for UsdPrim flags that can be combined to form either a
15 /// conjunction (via &&) or a disjunction (via ||). The result is a
16 /// predicate functor object that tests those flags on the passed prim.
17 /// Currently UsdPrim::GetFilteredChildren(), UsdPrim::GetNextFilteredSibling(),
18 /// UsdPrim::GetFilteredDescendants(), and UsdPrimRange() accept these
19 /// predicates to filter out unwanted prims.
20 ///
21 /// For example:
22 /// \code
23 /// // Get only loaded model children.
24 /// prim.GetFilteredChildren(UsdPrimIsModel && UsdPrimIsLoaded)
25 /// \endcode
26 ///
27 /// For performance, these predicates are implemented by a bitwise test, so
28 /// arbitrary boolean expressions cannot be represented. The set of boolean
29 /// expressions that can be represented are conjunctions with possibly negated
30 /// terms (or disjunctions, by De Morgan's law). Here are some examples of
31 /// valid expressions:
32 /// \code
33 /// // simple conjunction.
34 /// (UsdPrimIsLoaded && UsdPrimIsGroup)
35 /// // conjunction with negated term.
36 /// (UsdPrimIsDefined && !UsdPrimIsAbstract)
37 /// // disjunction with negated term.
38 /// (!UsdPrimIsDefined || !UsdPrimIsActive)
39 /// // negated conjunction gives a disjunction.
40 /// !(UsdPrimIsLoaded && UsdPrimIsModel)
41 /// // negated conjunction gives a disjunction, which is further extended.
42 /// (!(UsdPrimIsLoaded && UsdPrimIsModel) || UsdPrimIsAbstract)
43 /// // equivalent to above.
44 /// (!UsdPrimIsLoaded || !UsdPrimIsModel || UsdPrimIsAbstract)
45 /// \endcode
46 /// Here are some examples of invalid expressions:
47 /// \code
48 /// // error: cannot || a term with a conjunction.
49 /// (UsdPrimIsLoaded && UsdPrimIsModel) || UsdPrimIsAbstract
50 /// // error: cannot && disjunctions.
51 /// (!UsdPrimIsDefined || UsdPrimIsAbstract) && (UsdPrimIsModel || !UsdPrimIsActive)
52 /// \endcode
53 ///
54 ///
55 /// The following variables provide the clauses that can be combined and
56 /// negated to produce predicates:
57 
58 #include "pxr/pxr.h"
59 #include "pxr/usd/usd/api.h"
60 #include "pxr/base/arch/hints.h"
61 #include "pxr/base/tf/bitUtils.h"
62 #include "pxr/base/tf/hash.h"
63 
64 #include <bitset>
65 
67 
68 class SdfPath;
69 
70 // Enum for cached flags on prims.
72  // Flags for use with predicates.
82 
83  // Flags for internal use.
90 
92 };
93 
94 typedef std::bitset<Usd_PrimNumFlags> Usd_PrimFlagBits;
95 
96 // Term class. This class exists merely to allow building up conjunctions or
97 // disjunctions of terms. See Usd_PrimFlagsPredicate, Usd_PrimFlagsConjunction,
98 // Usd_PrimFlagsDisjunction which provide the logcial operators.
99 struct Usd_Term {
100  Usd_Term(Usd_PrimFlags flag) : flag(flag), negated(false) {}
101  Usd_Term(Usd_PrimFlags flag, bool negated) : flag(flag), negated(negated) {}
102  Usd_Term operator!() const { return Usd_Term(flag, !negated); }
103  bool operator==(Usd_Term other) const {
104  return flag == other.flag && negated == other.negated;
105  }
106  bool operator!=(Usd_Term other) const {
107  return !(*this == other);
108  }
110  bool negated;
111 };
112 
113 inline Usd_Term
115  return Usd_Term(flag, /*negated=*/true);
116 }
117 
118 // Predicate functor class that tests a prim's flags against desired values.
120 {
121 public:
122  // Functor result type.
123  typedef bool result_type;
124 
125  // Default ctor produces a tautology.
126  Usd_PrimFlagsPredicate() : _negate(false) {}
127 
129  : _negate(false) {
130  _mask[flag] = 1;
131  _values[flag] = true;
132  }
133 
134  // Implicit conversion from a single term.
136  : _negate(false) {
137  _mask[term.flag] = 1;
138  _values[term.flag] = !term.negated;
139  }
140 
141  // Convenience to produce a tautological predicate. Returns a
142  // default-constructed predicate.
144  return Usd_PrimFlagsPredicate();
145  }
146 
147  // Convenience to produce a contradictory predicate. Returns a negated
148  // default-constructed predicate.
150  return Usd_PrimFlagsPredicate()._Negate();
151  }
152 
153  // Set flag to indicate whether prim traversal functions using this
154  // predicate should traverse beneath instances and return descendants
155  // that pass this predicate as instance proxy prims.
157  if (traverse) {
160  }
161  else {
164  }
165  return *this;
166  }
167 
168  // Returns true if this predicate was explicitly set to include
169  // instance proxies, false otherwise.
171  return !_mask[Usd_PrimInstanceProxyFlag] &&
173  }
174 
175  // Invoke boolean predicate on UsdPrim \p prim.
176  USD_API
177  bool operator()(const class UsdPrim &prim) const;
178 
179 protected:
180 
181  // Return true if this predicate is a tautology, false otherwise.
182  bool _IsTautology() const { return *this == Tautology(); }
183 
184  // Set this predicate to be a tautology.
185  void _MakeTautology() { *this = Tautology(); }
186 
187  // Return true if this predicate is a contradiction, false otherwise.
188  bool _IsContradiction() const { return *this == Contradiction(); }
189 
190  // Set this predicate to be a contradiction.
191  void _MakeContradiction() { *this = Contradiction(); }
192 
193  // Negate this predicate.
195  _negate = !_negate;
196  return *this;
197  }
198 
199  // Return a negated copy of this predicate.
201  return Usd_PrimFlagsPredicate(*this)._Negate();
202  }
203 
204  // Mask indicating which flags are of interest.
206 
207  // Desired values for prim flags.
209 
210 private:
211  // Evaluate this predicate with prim data \p prim. \p isInstanceProxy
212  // should be true if this is being evaluated for an instance proxy prim.
213  template <class PrimPtr>
214  bool _Eval(const PrimPtr &prim, bool isInstanceProxy) const {
215  // Manually set the instance proxy bit, since instance proxy
216  // state is never stored in Usd_PrimData's flags.
217  const Usd_PrimFlagBits primFlags = Usd_PrimFlagBits(prim->_GetFlags())
218  .set(Usd_PrimInstanceProxyFlag, isInstanceProxy);
219 
220  // Mask the prim's flags, compare to desired values, then optionally
221  // negate the result.
222  return ((primFlags & _mask) == (_values & _mask)) ^ _negate;
223  }
224 
225  // Evaluate the predicate \p pred with prim data \p prim. \p isInstanceProxy
226  // should be true if this is being evaluated for an instance proxy prim.
227  template <class PrimPtr>
228  friend bool
229  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
230  bool isInstanceProxy) {
231  return pred._Eval(prim, isInstanceProxy);
232  }
233 
234  // Convenience method for evaluating \p pred using \p prim and
235  // \p proxyPrimPath to determine whether this is for an instance proxy
236  // prim.
237  template <class PrimPtr>
238  friend bool
239  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
240  const SdfPath &proxyPrimPath) {
241  return pred._Eval(prim, Usd_IsInstanceProxy(prim, proxyPrimPath));
242  }
243 
244  // Equality comparison.
245  friend bool
247  const Usd_PrimFlagsPredicate &rhs) {
248  return lhs._mask == rhs._mask &&
249  lhs._values == rhs._values &&
250  lhs._negate == rhs._negate;
251  }
252  // Inequality comparison.
253  friend bool
255  const Usd_PrimFlagsPredicate &rhs) {
256  return !(lhs == rhs);
257  }
258 
259  // hash overload.
260  friend size_t hash_value(const Usd_PrimFlagsPredicate &p) {
261  return TfHash::Combine(
262  p._mask.to_ulong(), p._values.to_ulong(), p._negate
263  );
264  }
265 
266  // Whether or not to negate the predicate's result.
267  bool _negate;
268 
269 };
270 
271 
272 /// Conjunction of prim flag predicate terms.
273 ///
274 /// Usually clients will implicitly create conjunctions by &&-ing together flag
275 /// predicate terms. For example:
276 /// \code
277 /// // Get all loaded model children.
278 /// prim.GetFilteredChildren(UsdPrimIsModel && UsdPrimIsLoaded)
279 /// \endcode
280 ///
281 /// See primFlags.h for more details.
283 public:
284  /// Default constructed conjunction is a tautology.
286 
287  /// Construct with a term.
289  *this &= term;
290  }
291 
292  /// Add an additional term to this conjunction.
294  // If this conjunction is a contradiction, do nothing.
296  return *this;
297 
298  // If we don't have the bit, set it in _mask and _values (if needed).
299  if (!_mask[term.flag]) {
300  _mask[term.flag] = 1;
301  _values[term.flag] = !term.negated;
302  } else if (_values[term.flag] != !term.negated) {
303  // If we do have the bit and the values disagree, then this entire
304  // conjunction becomes a contradiction. If the values agree, it's
305  // redundant and we do nothing.
307  }
308  return *this;
309  }
310 
311  /// Negate this conjunction, producing a disjunction by De Morgan's law.
312  /// For instance:
313  ///
314  /// \code
315  /// !(UsdPrimIsLoaded && UsdPrimIsModel)
316  /// \endcode
317  ///
318  /// Will negate the conjunction in parens to produce a disjunction
319  /// equivalent to:
320  ///
321  /// \code
322  /// (!UsdPrimIsLoaded || !UsdPrimIsModel)
323  /// \endcode
324  ///
325  /// Every expression may be formulated as either a disjunction or a
326  /// conjuction, but allowing both affords increased expressiveness.
327  ///
328  USD_API
329  class Usd_PrimFlagsDisjunction operator!() const;
330 
331 private:
332 
333  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated
336  Usd_PrimFlagsPredicate(base) {}
337 
338  /// Combine two terms to make a conjunction.
340  operator&&(Usd_Term lhs, Usd_Term rhs);
341 
342  /// Create a new conjunction with the term \p rhs added.
345 
346  /// Create a new conjunction with the term \p lhs added.
349 };
350 
353  // Apparently gcc 4.8.x doesn't like this as:
354  // return (Usd_PrimFlagsConjunction() && lhs) && rhs;
356  return (tmp && lhs) && rhs;
357 }
358 
361  return Usd_PrimFlagsConjunction(conjunction) &= rhs;
362 }
363 
366  return Usd_PrimFlagsConjunction(conjunction) &= lhs;
367 }
368 
371  return Usd_Term(lhs) && Usd_Term(rhs);
372 }
373 
374 
375 /// Disjunction of prim flag predicate terms.
376 ///
377 /// Usually clients will implicitly create disjunctions by ||-ing together flag
378 /// predicate terms. For example:
379 /// \code
380 /// // Get all deactivated or undefined children.
381 /// prim.GetFilteredChildren(!UsdPrimIsActive || !UsdPrimIsDefined)
382 /// \endcode
383 ///
384 /// See primFlags.h for more details.
386 public:
387  // Default constructed disjunction is a contradiction.
389 
390  // Construct with a term.
392  _Negate();
393  *this |= term;
394  }
395 
396  /// Add an additional term to this disjunction.
398  // If this disjunction is a tautology, do nothing.
400  return *this;
401 
402  // If we don't have the bit, set it in _mask and _values (if needed).
403  if (!_mask[term.flag]) {
404  _mask[term.flag] = 1;
405  _values[term.flag] = term.negated;
406  } else if (_values[term.flag] != term.negated) {
407  // If we do have the bit and the values disagree, then this entire
408  // disjunction becomes a tautology. If the values agree, it's
409  // redundant and we do nothing.
410  _MakeTautology();
411  }
412  return *this;
413  }
414 
415  /// Negate this disjunction, producing a disjunction by De Morgan's law.
416  /// For instance:
417  ///
418  /// \code
419  /// !(UsdPrimIsLoaded || UsdPrimIsModel)
420  /// \endcode
421  ///
422  /// Will negate the disjunction in parens to produce a conjunction
423  /// equivalent to:
424  ///
425  /// \code
426  /// (!UsdPrimIsLoaded && !UsdPrimIsModel)
427  /// \endcode
428  ///
429  /// Every expression may be formulated as either a disjunction or a
430  /// conjuction, but allowing both affords increased expressiveness.
431  ///
432  USD_API
433  class Usd_PrimFlagsConjunction operator!() const;
434 
435 private:
436 
437  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated.
440  Usd_PrimFlagsPredicate(base) {}
441 
442  /// Combine two terms to make a disjunction.
444 
445  /// Create a new disjunction with the term \p rhs added.
448 
449  /// Create a new disjunction with the term \p lhs added.
452 };
453 
456  return (Usd_PrimFlagsDisjunction() || lhs) || rhs;
457 }
458 
461  return Usd_PrimFlagsDisjunction(disjunction) |= rhs;
462 }
463 
466  return Usd_PrimFlagsDisjunction(disjunction) |= lhs;
467 }
468 
471  return Usd_Term(lhs) || Usd_Term(rhs);
472 }
473 
474 #ifdef doxygen
475 
476 /// Tests UsdPrim::IsActive()
477 extern unspecified UsdPrimIsActive;
478 /// Tests UsdPrim::IsLoaded()
479 extern unspecified UsdPrimIsLoaded;
480 /// Tests UsdPrim::IsModel()
481 extern unspecified UsdPrimIsModel;
482 /// Tests UsdPrim::IsGroup()
483 extern unspecified UsdPrimIsGroup;
484 /// Tests UsdPrim::IsAbstract()
485 extern unspecified UsdPrimIsAbstract;
486 /// Tests UsdPrim::IsDefined()
487 extern unspecified UsdPrimIsDefined;
488 /// Tests UsdPrim::IsInstance()
489 extern unspecified UsdPrimIsInstance;
490 /// Tests UsdPrim::HasDefiningSpecifier()
491 extern unspecified UsdPrimHasDefiningSpecifier;
492 
493 /// The default predicate used for prim traversals in methods like
494 /// UsdPrim::GetChildren, UsdStage::Traverse, and by UsdPrimRange.
495 /// This is a conjunction that includes all active, loaded, defined,
496 /// non-abstract prims, equivalent to:
497 /// \code
498 /// UsdPrimIsActive && UsdPrimIsDefined && UsdPrimIsLoaded && !UsdPrimIsAbstract
499 /// \endcode
500 ///
501 /// This represents the prims on a stage that a processor would typically
502 /// consider present, meaningful, and needful of consideration.
503 ///
504 /// See \ref Usd_PrimFlags "Prim predicate flags" for more information.
506 
507 /// Predicate that includes all prims.
508 ///
509 /// See \ref Usd_PrimFlags "Prim predicate flags" for more information.
511 
512 #else
513 
514 static const Usd_PrimFlags UsdPrimIsActive = Usd_PrimActiveFlag;
515 static const Usd_PrimFlags UsdPrimIsLoaded = Usd_PrimLoadedFlag;
516 static const Usd_PrimFlags UsdPrimIsModel = Usd_PrimModelFlag;
517 static const Usd_PrimFlags UsdPrimIsGroup = Usd_PrimGroupFlag;
518 static const Usd_PrimFlags UsdPrimIsAbstract = Usd_PrimAbstractFlag;
519 static const Usd_PrimFlags UsdPrimIsDefined = Usd_PrimDefinedFlag;
520 static const Usd_PrimFlags UsdPrimIsInstance = Usd_PrimInstanceFlag;
521 static const Usd_PrimFlags UsdPrimHasDefiningSpecifier
523 
526 
527 #endif // doxygen
528 
529 /// This function is used to allow the prim traversal functions listed under
530 /// \ref Usd_PrimFlags "Prim predicate flags" to traverse beneath instance
531 /// prims and return descendants that pass the specified \p predicate
532 /// as instance proxy prims. For example:
533 ///
534 /// \code
535 /// // Return all children of the specified prim.
536 /// // If prim is an instance, return all children as instance proxy prims.
537 /// prim.GetFilteredChildren(
538 /// UsdTraverseInstanceProxies(UsdPrimAllPrimsPredicate))
539 ///
540 /// // Return children of the specified prim that pass the default predicate.
541 /// // If prim is an instance, return the children that pass this predicate
542 /// // as instance proxy prims.
543 /// prim.GetFilteredChildren(UsdTraverseInstanceProxies());
544 ///
545 /// // Return all model or group children of the specified prim.
546 /// // If prim is an instance, return the children that pass this predicate
547 /// // as instance proxy prims.
548 /// prim.GetFilteredChildren(UsdTraverseInstanceProxies(UsdPrimIsModel || UsdPrimIsGroup));
549 /// \endcode
550 ///
551 /// Users may also call Usd_PrimFlagsPredicate::TraverseInstanceProxies to
552 /// enable traversal beneath instance prims. This function is equivalent to:
553 /// \code
554 /// predicate.TraverseInstanceProxies(true);
555 /// \endcode
556 ///
557 /// However, this function may be more convenient, especially when calling
558 /// a prim traversal function with a default-constructed tautology predicate.
561 {
562  return predicate.TraverseInstanceProxies(true);
563 }
564 
565 /// \overload
566 /// Convenience method equivalent to calling UsdTraverseInstanceProxies
567 /// with the UsdPrimDefaultPredicate that is used by default for prim
568 /// traversals.
571 {
573 }
574 
576 
577 #endif // PXR_USD_USD_PRIM_FLAGS_H
bool operator!=(Usd_Term other) const
Definition: primFlags.h:106
Usd_Term(Usd_PrimFlags flag, bool negated)
Definition: primFlags.h:101
Usd_PrimFlagsDisjunction & operator|=(Usd_Term term)
Add an additional term to this disjunction.
Definition: primFlags.h:397
bool _IsContradiction() const
Definition: primFlags.h:188
friend Usd_PrimFlagsConjunction operator&&(Usd_Term lhs, Usd_Term rhs)
Combine two terms to make a conjunction.
Definition: primFlags.h:352
#define USD_API
Definition: api.h:23
bool _IsTautology() const
Definition: primFlags.h:182
Usd_PrimFlagsConjunction operator&&(Usd_Term lhs, Usd_Term rhs)
Definition: primFlags.h:352
Usd_PrimFlagsConjunction(Usd_Term term)
Construct with a term.
Definition: primFlags.h:288
friend size_t hash_value(const Usd_PrimFlagsPredicate &p)
Definition: primFlags.h:260
Usd_PrimFlagsPredicate & _Negate()
Definition: primFlags.h:194
Usd_PrimFlagsConjunction()
Default constructed conjunction is a tautology.
Definition: primFlags.h:285
Usd_PrimFlags
Definition: primFlags.h:71
Usd_PrimFlagBits _mask
Definition: primFlags.h:205
Usd_PrimFlagsPredicate _GetNegated() const
Definition: primFlags.h:200
Usd_PrimFlags flag
Definition: primFlags.h:109
Usd_PrimFlagsPredicate & TraverseInstanceProxies(bool traverse)
Definition: primFlags.h:156
friend class Usd_PrimFlagsDisjunction
Definition: primFlags.h:334
Usd_PrimFlagsPredicate(Usd_PrimFlags flag)
Definition: primFlags.h:128
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
Usd_PrimFlagBits _values
Definition: primFlags.h:208
static Usd_PrimFlagsPredicate Tautology()
Definition: primFlags.h:143
constexpr auto set(type rhs) -> int
Definition: core.h:610
bool Usd_IsInstanceProxy(const PrimDataPtr &p, const SdfPath &proxyPrimPath)
Definition: primData.h:465
bool IncludeInstanceProxiesInTraversal() const
Definition: primFlags.h:170
friend bool Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim, const SdfPath &proxyPrimPath)
Definition: primFlags.h:239
Definition: prim.h:116
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
Definition: primFlags.h:560
friend bool Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim, bool isInstanceProxy)
Definition: primFlags.h:229
friend Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs)
Combine two terms to make a disjunction.
Definition: primFlags.h:455
Definition: path.h:273
void traverse(T &func, const char *path, bool sort_contents=false, bool directories_first=true)
Definition: FS_Traverse.h:70
Usd_Term operator!(Usd_PrimFlags flag)
Definition: primFlags.h:114
static Usd_PrimFlagsPredicate Contradiction()
Definition: primFlags.h:149
static size_t Combine(Args &&...args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:487
USD_API const Usd_PrimFlagsConjunction UsdPrimDefaultPredicate
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
Usd_Term(Usd_PrimFlags flag)
Definition: primFlags.h:100
USD_API const Usd_PrimFlagsPredicate UsdPrimAllPrimsPredicate
Usd_PrimFlagsDisjunction(Usd_Term term)
Definition: primFlags.h:391
friend bool operator==(const Usd_PrimFlagsPredicate &lhs, const Usd_PrimFlagsPredicate &rhs)
Definition: primFlags.h:246
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
friend bool operator!=(const Usd_PrimFlagsPredicate &lhs, const Usd_PrimFlagsPredicate &rhs)
Definition: primFlags.h:254
Usd_Term operator!() const
Definition: primFlags.h:102
Usd_PrimFlagsConjunction & operator&=(Usd_Term term)
Add an additional term to this conjunction.
Definition: primFlags.h:293
bool operator==(Usd_Term other) const
Definition: primFlags.h:103
USD_API bool operator()(const class UsdPrim &prim) const
std::bitset< Usd_PrimNumFlags > Usd_PrimFlagBits
Definition: primFlags.h:94
Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs)
Definition: primFlags.h:455
bool negated
Definition: primFlags.h:110
Usd_PrimFlagsPredicate(Usd_Term term)
Definition: primFlags.h:135
friend class Usd_PrimFlagsConjunction
Definition: primFlags.h:438