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.
83 
84  // Flags for internal use.
91 
93 };
94 
95 typedef std::bitset<Usd_PrimNumFlags> Usd_PrimFlagBits;
96 
97 // Term class. This class exists merely to allow building up conjunctions or
98 // disjunctions of terms. See Usd_PrimFlagsPredicate, Usd_PrimFlagsConjunction,
99 // Usd_PrimFlagsDisjunction which provide the logcial operators.
100 struct Usd_Term {
101  Usd_Term(Usd_PrimFlags flag) : flag(flag), negated(false) {}
102  Usd_Term(Usd_PrimFlags flag, bool negated) : flag(flag), negated(negated) {}
103  Usd_Term operator!() const { return Usd_Term(flag, !negated); }
104  bool operator==(Usd_Term other) const {
105  return flag == other.flag && negated == other.negated;
106  }
107  bool operator!=(Usd_Term other) const {
108  return !(*this == other);
109  }
111  bool negated;
112 };
113 
114 inline Usd_Term
116  return Usd_Term(flag, /*negated=*/true);
117 }
118 
119 // Predicate functor class that tests a prim's flags against desired values.
121 {
122 public:
123  // Functor result type.
124  typedef bool result_type;
125 
126  // Default ctor produces a tautology.
127  Usd_PrimFlagsPredicate() : _negate(false) {}
128 
130  : _negate(false) {
131  _mask[flag] = 1;
132  _values[flag] = true;
133  }
134 
135  // Implicit conversion from a single term.
137  : _negate(false) {
138  _mask[term.flag] = 1;
139  _values[term.flag] = !term.negated;
140  }
141 
142  // Convenience to produce a tautological predicate. Returns a
143  // default-constructed predicate.
145  return Usd_PrimFlagsPredicate();
146  }
147 
148  // Convenience to produce a contradictory predicate. Returns a negated
149  // default-constructed predicate.
151  return Usd_PrimFlagsPredicate()._Negate();
152  }
153 
154  // Set flag to indicate whether prim traversal functions using this
155  // predicate should traverse beneath instances and return descendants
156  // that pass this predicate as instance proxy prims.
158  if (traverse) {
161  }
162  else {
165  }
166  return *this;
167  }
168 
169  // Returns true if this predicate was explicitly set to include
170  // instance proxies, false otherwise.
172  return !_mask[Usd_PrimInstanceProxyFlag] &&
174  }
175 
176  // Invoke boolean predicate on UsdPrim \p prim.
177  USD_API
178  bool operator()(const class UsdPrim &prim) const;
179 
180 protected:
181 
182  // Return true if this predicate is a tautology, false otherwise.
183  bool _IsTautology() const { return *this == Tautology(); }
184 
185  // Set this predicate to be a tautology.
186  void _MakeTautology() { *this = Tautology(); }
187 
188  // Return true if this predicate is a contradiction, false otherwise.
189  bool _IsContradiction() const { return *this == Contradiction(); }
190 
191  // Set this predicate to be a contradiction.
192  void _MakeContradiction() { *this = Contradiction(); }
193 
194  // Negate this predicate.
196  _negate = !_negate;
197  return *this;
198  }
199 
200  // Return a negated copy of this predicate.
202  return Usd_PrimFlagsPredicate(*this)._Negate();
203  }
204 
205  // Mask indicating which flags are of interest.
207 
208  // Desired values for prim flags.
210 
211 private:
212  // Evaluate this predicate with prim data \p prim. \p isInstanceProxy
213  // should be true if this is being evaluated for an instance proxy prim.
214  template <class PrimPtr>
215  bool _Eval(const PrimPtr &prim, bool isInstanceProxy) const {
216  // Manually set the instance proxy bit, since instance proxy
217  // state is never stored in Usd_PrimData's flags.
218  const Usd_PrimFlagBits primFlags = Usd_PrimFlagBits(prim->_GetFlags())
219  .set(Usd_PrimInstanceProxyFlag, isInstanceProxy);
220 
221  // Mask the prim's flags, compare to desired values, then optionally
222  // negate the result.
223  return ((primFlags & _mask) == (_values & _mask)) ^ _negate;
224  }
225 
226  // Evaluate the predicate \p pred with prim data \p prim. \p isInstanceProxy
227  // should be true if this is being evaluated for an instance proxy prim.
228  template <class PrimPtr>
229  friend bool
230  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
231  bool isInstanceProxy) {
232  return pred._Eval(prim, isInstanceProxy);
233  }
234 
235  // Convenience method for evaluating \p pred using \p prim and
236  // \p proxyPrimPath to determine whether this is for an instance proxy
237  // prim.
238  template <class PrimPtr>
239  friend bool
240  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
241  const SdfPath &proxyPrimPath) {
242  return pred._Eval(prim, Usd_IsInstanceProxy(prim, proxyPrimPath));
243  }
244 
245  // Equality comparison.
246  friend bool
248  const Usd_PrimFlagsPredicate &rhs) {
249  return lhs._mask == rhs._mask &&
250  lhs._values == rhs._values &&
251  lhs._negate == rhs._negate;
252  }
253  // Inequality comparison.
254  friend bool
256  const Usd_PrimFlagsPredicate &rhs) {
257  return !(lhs == rhs);
258  }
259 
260  // hash overload.
261  friend size_t hash_value(const Usd_PrimFlagsPredicate &p) {
262  return TfHash::Combine(
263  p._mask.to_ulong(), p._values.to_ulong(), p._negate
264  );
265  }
266 
267  // Whether or not to negate the predicate's result.
268  bool _negate;
269 
270 };
271 
272 
273 /// Conjunction of prim flag predicate terms.
274 ///
275 /// Usually clients will implicitly create conjunctions by &&-ing together flag
276 /// predicate terms. For example:
277 /// \code
278 /// // Get all loaded model children.
279 /// prim.GetFilteredChildren(UsdPrimIsModel && UsdPrimIsLoaded)
280 /// \endcode
281 ///
282 /// See primFlags.h for more details.
284 public:
285  /// Default constructed conjunction is a tautology.
287 
288  /// Construct with a term.
290  *this &= term;
291  }
292 
293  /// Add an additional term to this conjunction.
295  // If this conjunction is a contradiction, do nothing.
297  return *this;
298 
299  // If we don't have the bit, set it in _mask and _values (if needed).
300  if (!_mask[term.flag]) {
301  _mask[term.flag] = 1;
302  _values[term.flag] = !term.negated;
303  } else if (_values[term.flag] != !term.negated) {
304  // If we do have the bit and the values disagree, then this entire
305  // conjunction becomes a contradiction. If the values agree, it's
306  // redundant and we do nothing.
308  }
309  return *this;
310  }
311 
312  /// Negate this conjunction, producing a disjunction by De Morgan's law.
313  /// For instance:
314  ///
315  /// \code
316  /// !(UsdPrimIsLoaded && UsdPrimIsModel)
317  /// \endcode
318  ///
319  /// Will negate the conjunction in parens to produce a disjunction
320  /// equivalent to:
321  ///
322  /// \code
323  /// (!UsdPrimIsLoaded || !UsdPrimIsModel)
324  /// \endcode
325  ///
326  /// Every expression may be formulated as either a disjunction or a
327  /// conjuction, but allowing both affords increased expressiveness.
328  ///
329  USD_API
330  class Usd_PrimFlagsDisjunction operator!() const;
331 
332 private:
333 
334  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated
337  Usd_PrimFlagsPredicate(base) {}
338 
339  /// Combine two terms to make a conjunction.
341  operator&&(Usd_Term lhs, Usd_Term rhs);
342 
343  /// Create a new conjunction with the term \p rhs added.
346 
347  /// Create a new conjunction with the term \p lhs added.
350 };
351 
354  // Apparently gcc 4.8.x doesn't like this as:
355  // return (Usd_PrimFlagsConjunction() && lhs) && rhs;
357  return (tmp && lhs) && rhs;
358 }
359 
362  return Usd_PrimFlagsConjunction(conjunction) &= rhs;
363 }
364 
367  return Usd_PrimFlagsConjunction(conjunction) &= lhs;
368 }
369 
372  return Usd_Term(lhs) && Usd_Term(rhs);
373 }
374 
375 
376 /// Disjunction of prim flag predicate terms.
377 ///
378 /// Usually clients will implicitly create disjunctions by ||-ing together flag
379 /// predicate terms. For example:
380 /// \code
381 /// // Get all deactivated or undefined children.
382 /// prim.GetFilteredChildren(!UsdPrimIsActive || !UsdPrimIsDefined)
383 /// \endcode
384 ///
385 /// See primFlags.h for more details.
387 public:
388  // Default constructed disjunction is a contradiction.
390 
391  // Construct with a term.
393  _Negate();
394  *this |= term;
395  }
396 
397  /// Add an additional term to this disjunction.
399  // If this disjunction is a tautology, do nothing.
401  return *this;
402 
403  // If we don't have the bit, set it in _mask and _values (if needed).
404  if (!_mask[term.flag]) {
405  _mask[term.flag] = 1;
406  _values[term.flag] = term.negated;
407  } else if (_values[term.flag] != term.negated) {
408  // If we do have the bit and the values disagree, then this entire
409  // disjunction becomes a tautology. If the values agree, it's
410  // redundant and we do nothing.
411  _MakeTautology();
412  }
413  return *this;
414  }
415 
416  /// Negate this disjunction, producing a disjunction by De Morgan's law.
417  /// For instance:
418  ///
419  /// \code
420  /// !(UsdPrimIsLoaded || UsdPrimIsModel)
421  /// \endcode
422  ///
423  /// Will negate the disjunction in parens to produce a conjunction
424  /// equivalent to:
425  ///
426  /// \code
427  /// (!UsdPrimIsLoaded && !UsdPrimIsModel)
428  /// \endcode
429  ///
430  /// Every expression may be formulated as either a disjunction or a
431  /// conjuction, but allowing both affords increased expressiveness.
432  ///
433  USD_API
434  class Usd_PrimFlagsConjunction operator!() const;
435 
436 private:
437 
438  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated.
441  Usd_PrimFlagsPredicate(base) {}
442 
443  /// Combine two terms to make a disjunction.
445 
446  /// Create a new disjunction with the term \p rhs added.
449 
450  /// Create a new disjunction with the term \p lhs added.
453 };
454 
457  return (Usd_PrimFlagsDisjunction() || lhs) || rhs;
458 }
459 
462  return Usd_PrimFlagsDisjunction(disjunction) |= rhs;
463 }
464 
467  return Usd_PrimFlagsDisjunction(disjunction) |= lhs;
468 }
469 
472  return Usd_Term(lhs) || Usd_Term(rhs);
473 }
474 
475 #ifdef doxygen
476 
477 /// Tests UsdPrim::IsActive()
478 extern unspecified UsdPrimIsActive;
479 /// Tests UsdPrim::IsLoaded()
480 extern unspecified UsdPrimIsLoaded;
481 /// Tests UsdPrim::IsModel()
482 extern unspecified UsdPrimIsModel;
483 /// Tests UsdPrim::IsGroup()
484 extern unspecified UsdPrimIsGroup;
485 /// Tests UsdPrim::IsAbstract()
486 extern unspecified UsdPrimIsAbstract;
487 /// Tests UsdPrim::IsDefined()
488 extern unspecified UsdPrimIsDefined;
489 /// Tests UsdPrim::IsInstance()
490 extern unspecified UsdPrimIsInstance;
491 /// Tests UsdPrim::HasClassSpecifier()
492 extern unspecified UsdPrimHasClassSpecifier;
493 /// Tests UsdPrim::HasDefiningSpecifier()
494 extern unspecified UsdPrimHasDefiningSpecifier;
495 
496 /// The default predicate used for prim traversals in methods like
497 /// UsdPrim::GetChildren, UsdStage::Traverse, and by UsdPrimRange.
498 /// This is a conjunction that includes all active, loaded, defined,
499 /// non-abstract prims, equivalent to:
500 /// \code
501 /// UsdPrimIsActive && UsdPrimIsDefined && UsdPrimIsLoaded && !UsdPrimIsAbstract
502 /// \endcode
503 ///
504 /// This represents the prims on a stage that a processor would typically
505 /// consider present, meaningful, and needful of consideration.
506 ///
507 /// See \ref Usd_PrimFlags "Prim predicate flags" for more information.
509 
510 /// Predicate that includes all prims.
511 ///
512 /// See \ref Usd_PrimFlags "Prim predicate flags" for more information.
514 
515 #else
516 
517 static const Usd_PrimFlags UsdPrimIsActive = Usd_PrimActiveFlag;
518 static const Usd_PrimFlags UsdPrimIsLoaded = Usd_PrimLoadedFlag;
519 static const Usd_PrimFlags UsdPrimIsModel = Usd_PrimModelFlag;
520 static const Usd_PrimFlags UsdPrimIsGroup = Usd_PrimGroupFlag;
521 static const Usd_PrimFlags UsdPrimIsAbstract = Usd_PrimAbstractFlag;
522 static const Usd_PrimFlags UsdPrimIsDefined = Usd_PrimDefinedFlag;
523 static const Usd_PrimFlags UsdPrimIsInstance = Usd_PrimInstanceFlag;
524 static const Usd_PrimFlags UsdPrimHasClassSpecifier
526 static const Usd_PrimFlags UsdPrimHasDefiningSpecifier
528 
531 
532 #endif // doxygen
533 
534 /// This function is used to allow the prim traversal functions listed under
535 /// \ref Usd_PrimFlags "Prim predicate flags" to traverse beneath instance
536 /// prims and return descendants that pass the specified \p predicate
537 /// as instance proxy prims. For example:
538 ///
539 /// \code
540 /// // Return all children of the specified prim.
541 /// // If prim is an instance, return all children as instance proxy prims.
542 /// prim.GetFilteredChildren(
543 /// UsdTraverseInstanceProxies(UsdPrimAllPrimsPredicate))
544 ///
545 /// // Return children of the specified prim that pass the default predicate.
546 /// // If prim is an instance, return the children that pass this predicate
547 /// // as instance proxy prims.
548 /// prim.GetFilteredChildren(UsdTraverseInstanceProxies());
549 ///
550 /// // Return all model or group children of the specified prim.
551 /// // If prim is an instance, return the children that pass this predicate
552 /// // as instance proxy prims.
553 /// prim.GetFilteredChildren(UsdTraverseInstanceProxies(UsdPrimIsModel || UsdPrimIsGroup));
554 /// \endcode
555 ///
556 /// Users may also call Usd_PrimFlagsPredicate::TraverseInstanceProxies to
557 /// enable traversal beneath instance prims. This function is equivalent to:
558 /// \code
559 /// predicate.TraverseInstanceProxies(true);
560 /// \endcode
561 ///
562 /// However, this function may be more convenient, especially when calling
563 /// a prim traversal function with a default-constructed tautology predicate.
566 {
567  return predicate.TraverseInstanceProxies(true);
568 }
569 
570 /// \overload
571 /// Convenience method equivalent to calling UsdTraverseInstanceProxies
572 /// with the UsdPrimDefaultPredicate that is used by default for prim
573 /// traversals.
576 {
578 }
579 
581 
582 #endif // PXR_USD_USD_PRIM_FLAGS_H
bool operator!=(Usd_Term other) const
Definition: primFlags.h:107
Usd_Term(Usd_PrimFlags flag, bool negated)
Definition: primFlags.h:102
Usd_PrimFlagsDisjunction & operator|=(Usd_Term term)
Add an additional term to this disjunction.
Definition: primFlags.h:398
bool _IsContradiction() const
Definition: primFlags.h:189
friend Usd_PrimFlagsConjunction operator&&(Usd_Term lhs, Usd_Term rhs)
Combine two terms to make a conjunction.
Definition: primFlags.h:353
#define USD_API
Definition: api.h:23
bool _IsTautology() const
Definition: primFlags.h:183
Usd_PrimFlagsConjunction operator&&(Usd_Term lhs, Usd_Term rhs)
Definition: primFlags.h:353
Usd_PrimFlagsConjunction(Usd_Term term)
Construct with a term.
Definition: primFlags.h:289
friend size_t hash_value(const Usd_PrimFlagsPredicate &p)
Definition: primFlags.h:261
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
Usd_PrimFlagsPredicate & _Negate()
Definition: primFlags.h:195
Usd_PrimFlagsConjunction()
Default constructed conjunction is a tautology.
Definition: primFlags.h:286
Usd_PrimFlags
Definition: primFlags.h:71
Usd_PrimFlagBits _mask
Definition: primFlags.h:206
Usd_PrimFlagsPredicate _GetNegated() const
Definition: primFlags.h:201
Usd_PrimFlags flag
Definition: primFlags.h:110
Usd_PrimFlagsPredicate & TraverseInstanceProxies(bool traverse)
Definition: primFlags.h:157
friend class Usd_PrimFlagsDisjunction
Definition: primFlags.h:335
Usd_PrimFlagsPredicate(Usd_PrimFlags flag)
Definition: primFlags.h:129
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
Usd_PrimFlagBits _values
Definition: primFlags.h:209
static Usd_PrimFlagsPredicate Tautology()
Definition: primFlags.h:144
constexpr auto set(type rhs) -> int
Definition: core.h:610
bool Usd_IsInstanceProxy(const PrimDataPtr &p, const SdfPath &proxyPrimPath)
Definition: primData.h:470
bool IncludeInstanceProxiesInTraversal() const
Definition: primFlags.h:171
friend bool Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim, const SdfPath &proxyPrimPath)
Definition: primFlags.h:240
Definition: prim.h:116
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
Definition: primFlags.h:565
friend bool Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim, bool isInstanceProxy)
Definition: primFlags.h:230
friend Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs)
Combine two terms to make a disjunction.
Definition: primFlags.h:456
Definition: path.h:280
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:115
static Usd_PrimFlagsPredicate Contradiction()
Definition: primFlags.h:150
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
Usd_Term(Usd_PrimFlags flag)
Definition: primFlags.h:101
USD_API const Usd_PrimFlagsPredicate UsdPrimAllPrimsPredicate
Usd_PrimFlagsDisjunction(Usd_Term term)
Definition: primFlags.h:392
friend bool operator==(const Usd_PrimFlagsPredicate &lhs, const Usd_PrimFlagsPredicate &rhs)
Definition: primFlags.h:247
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
friend bool operator!=(const Usd_PrimFlagsPredicate &lhs, const Usd_PrimFlagsPredicate &rhs)
Definition: primFlags.h:255
Usd_Term operator!() const
Definition: primFlags.h:103
Usd_PrimFlagsConjunction & operator&=(Usd_Term term)
Add an additional term to this conjunction.
Definition: primFlags.h:294
bool operator==(Usd_Term other) const
Definition: primFlags.h:104
USD_API bool operator()(const class UsdPrim &prim) const
std::bitset< Usd_PrimNumFlags > Usd_PrimFlagBits
Definition: primFlags.h:95
Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs)
Definition: primFlags.h:456
bool negated
Definition: primFlags.h:111
Usd_PrimFlagsPredicate(Usd_Term term)
Definition: primFlags.h:136
friend class Usd_PrimFlagsConjunction
Definition: primFlags.h:439