primFlags.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_FLAGS_H
25 #define PXR_USD_USD_PRIM_FLAGS_H
26 
74 
75 #include "pxr/pxr.h"
76 #include "pxr/usd/usd/api.h"
77 #include "pxr/base/arch/hints.h"
78 #include "pxr/base/tf/bitUtils.h"
79 
80 #include <boost/functional/hash.hpp>
81 
82 #include <bitset>
83 
84 PXR_NAMESPACE_OPEN_SCOPE
85 
86 class SdfPath;
87 
88 // Enum for cached flags on prims.
89 enum Usd_PrimFlags {
90  // Flags for use with predicates.
91  Usd_PrimActiveFlag,
92  Usd_PrimLoadedFlag,
93  Usd_PrimModelFlag,
94  Usd_PrimGroupFlag,
95  Usd_PrimAbstractFlag,
96  Usd_PrimDefinedFlag,
97  Usd_PrimHasDefiningSpecifierFlag,
98  Usd_PrimInstanceFlag,
99 
100  // Flags for internal use.
101  Usd_PrimHasPayloadFlag,
102  Usd_PrimClipsFlag,
103  Usd_PrimDeadFlag,
104  Usd_PrimPrototypeFlag,
105  Usd_PrimInstanceProxyFlag,
106  Usd_PrimPseudoRootFlag,
107 
108  Usd_PrimNumFlags
109 };
110 
111 typedef std::bitset<Usd_PrimNumFlags> Usd_PrimFlagBits;
112 
113 // Term class. This class exists merely to allow building up conjunctions or
114 // disjunctions of terms. See Usd_PrimFlagsPredicate, Usd_PrimFlagsConjunction,
115 // Usd_PrimFlagsDisjunction which provide the logcial operators.
116 struct Usd_Term {
117  Usd_Term(Usd_PrimFlags flag) : flag(flag), negated(false) {}
118  Usd_Term(Usd_PrimFlags flag, bool negated) : flag(flag), negated(negated) {}
119  Usd_Term operator!() const { return Usd_Term(flag, !negated); }
120  bool operator==(Usd_Term other) const {
121  return flag == other.flag && negated == other.negated;
122  }
123  bool operator!=(Usd_Term other) const {
124  return !(*this == other);
125  }
126  Usd_PrimFlags flag;
127  bool negated;
128 };
129 
130 inline Usd_Term
131 operator!(Usd_PrimFlags flag) {
132  return Usd_Term(flag, /*negated=*/true);
133 }
134 
135 // Predicate functor class that tests a prim's flags against desired values.
136 class Usd_PrimFlagsPredicate
137 {
138 public:
139  // Functor result type.
140  typedef bool result_type;
141 
142  // Default ctor produces a tautology.
143  Usd_PrimFlagsPredicate() : _negate(false) {}
144 
145  Usd_PrimFlagsPredicate(Usd_PrimFlags flag)
146  : _negate(false) {
147  _mask[flag] = 1;
148  _values[flag] = true;
149  }
150 
151  // Implicit conversion from a single term.
152  Usd_PrimFlagsPredicate(Usd_Term term)
153  : _negate(false) {
154  _mask[term.flag] = 1;
155  _values[term.flag] = !term.negated;
156  }
157 
158  // Convenience to produce a tautological predicate. Returns a
159  // default-constructed predicate.
160  static Usd_PrimFlagsPredicate Tautology() {
161  return Usd_PrimFlagsPredicate();
162  }
163 
164  // Convenience to produce a contradictory predicate. Returns a negated
165  // default-constructed predicate.
166  static Usd_PrimFlagsPredicate Contradiction() {
167  return Usd_PrimFlagsPredicate()._Negate();
168  }
169 
170  // Set flag to indicate whether prim traversal functions using this
171  // predicate should traverse beneath instances and return descendants
172  // that pass this predicate as instance proxy prims.
173  Usd_PrimFlagsPredicate &TraverseInstanceProxies(bool traverse) {
174  if (traverse) {
175  _mask[Usd_PrimInstanceProxyFlag] = 0;
176  _values[Usd_PrimInstanceProxyFlag] = 1;
177  }
178  else {
179  _mask[Usd_PrimInstanceProxyFlag] = 1;
180  _values[Usd_PrimInstanceProxyFlag] = 0;
181  }
182  return *this;
183  }
184 
185  // Returns true if this predicate was explicitly set to include
186  // instance proxies, false otherwise.
187  bool IncludeInstanceProxiesInTraversal() const {
188  return !_mask[Usd_PrimInstanceProxyFlag] &&
189  _values[Usd_PrimInstanceProxyFlag];
190  }
191 
192  // Invoke boolean predicate on UsdPrim \p prim.
193  USD_API
194  bool operator()(const class UsdPrim &prim) const;
195 
196 protected:
197 
198  // Return true if this predicate is a tautology, false otherwise.
199  bool _IsTautology() const { return *this == Tautology(); }
200 
201  // Set this predicate to be a tautology.
202  void _MakeTautology() { *this = Tautology(); }
203 
204  // Return true if this predicate is a contradiction, false otherwise.
205  bool _IsContradiction() const { return *this == Contradiction(); }
206 
207  // Set this predicate to be a contradiction.
208  void _MakeContradiction() { *this = Contradiction(); }
209 
210  // Negate this predicate.
211  Usd_PrimFlagsPredicate &_Negate() {
212  _negate = !_negate;
213  return *this;
214  }
215 
216  // Return a negated copy of this predicate.
217  Usd_PrimFlagsPredicate _GetNegated() const {
218  return Usd_PrimFlagsPredicate(*this)._Negate();
219  }
220 
221  // Mask indicating which flags are of interest.
222  Usd_PrimFlagBits _mask;
223 
224  // Desired values for prim flags.
225  Usd_PrimFlagBits _values;
226 
227 private:
228  // Evaluate this predicate with prim data \p prim. \p isInstanceProxy
229  // should be true if this is being evaluated for an instance proxy prim.
230  template <class PrimPtr>
231  bool _Eval(const PrimPtr &prim, bool isInstanceProxy) const {
232  // Manually set the instance proxy bit, since instance proxy
233  // state is never stored in Usd_PrimData's flags.
234  const Usd_PrimFlagBits primFlags = Usd_PrimFlagBits(prim->_GetFlags())
235  .set(Usd_PrimInstanceProxyFlag, isInstanceProxy);
236 
237  // Mask the prim's flags, compare to desired values, then optionally
238  // negate the result.
239  return ((primFlags & _mask) == (_values & _mask)) ^ _negate;
240  }
241 
242  // Evaluate the predicate \p pred with prim data \p prim. \p isInstanceProxy
243  // should be true if this is being evaluated for an instance proxy prim.
244  template <class PrimPtr>
245  friend bool
246  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
247  bool isInstanceProxy) {
248  return pred._Eval(prim, isInstanceProxy);
249  }
250 
251  // Convenience method for evaluating \p pred using \p prim and
252  // \p proxyPrimPath to determine whether this is for an instance proxy
253  // prim.
254  template <class PrimPtr>
255  friend bool
256  Usd_EvalPredicate(const Usd_PrimFlagsPredicate &pred, const PrimPtr &prim,
257  const SdfPath &proxyPrimPath) {
258  return pred._Eval(prim, Usd_IsInstanceProxy(prim, proxyPrimPath));
259  }
260 
261  // Equality comparison.
262  friend bool
263  operator==(const Usd_PrimFlagsPredicate &lhs,
264  const Usd_PrimFlagsPredicate &rhs) {
265  return lhs._mask == rhs._mask &&
266  lhs._values == rhs._values &&
267  lhs._negate == rhs._negate;
268  }
269  // Inequality comparison.
270  friend bool
271  operator!=(const Usd_PrimFlagsPredicate &lhs,
272  const Usd_PrimFlagsPredicate &rhs) {
273  return !(lhs == rhs);
274  }
275 
276  // hash overload.
277  friend size_t hash_value(const Usd_PrimFlagsPredicate &p) {
278  size_t hash = p._mask.to_ulong();
279  boost::hash_combine(hash, p._values.to_ulong());
280  boost::hash_combine(hash, p._negate);
281  return hash;
282  }
283 
284  // Whether or not to negate the predicate's result.
285  bool _negate;
286 
287 };
288 
289 
300 class Usd_PrimFlagsConjunction : public Usd_PrimFlagsPredicate {
301 public:
303  Usd_PrimFlagsConjunction() {};
304 
306  explicit Usd_PrimFlagsConjunction(Usd_Term term) {
307  *this &= term;
308  }
309 
311  Usd_PrimFlagsConjunction &operator&=(Usd_Term term) {
312  // If this conjunction is a contradiction, do nothing.
313  if (ARCH_UNLIKELY(_IsContradiction()))
314  return *this;
315 
316  // If we don't have the bit, set it in _mask and _values (if needed).
317  if (!_mask[term.flag]) {
318  _mask[term.flag] = 1;
319  _values[term.flag] = !term.negated;
320  } else if (_values[term.flag] != !term.negated) {
321  // If we do have the bit and the values disagree, then this entire
322  // conjunction becomes a contradiction. If the values agree, it's
323  // redundant and we do nothing.
324  _MakeContradiction();
325  }
326  return *this;
327  }
328 
346  USD_API
347  class Usd_PrimFlagsDisjunction operator!() const;
348 
349 private:
350 
351  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated
352  friend class Usd_PrimFlagsDisjunction;
353  Usd_PrimFlagsConjunction(const Usd_PrimFlagsPredicate &base) :
354  Usd_PrimFlagsPredicate(base) {}
355 
357  friend Usd_PrimFlagsConjunction
358  operator&&(Usd_Term lhs, Usd_Term rhs);
359 
361  friend Usd_PrimFlagsConjunction
362  operator&&(const Usd_PrimFlagsConjunction &conjunction, Usd_Term rhs);
363 
365  friend Usd_PrimFlagsConjunction
366  operator&&(Usd_Term lhs, const Usd_PrimFlagsConjunction &conjunction);
367 };
368 
369 inline Usd_PrimFlagsConjunction
370 operator&&(Usd_Term lhs, Usd_Term rhs) {
371  // Apparently gcc 4.8.x doesn't like this as:
372  // return (Usd_PrimFlagsConjunction() && lhs) && rhs;
373  Usd_PrimFlagsConjunction tmp;
374  return (tmp && lhs) && rhs;
375 }
376 
377 inline Usd_PrimFlagsConjunction
378 operator&&(const Usd_PrimFlagsConjunction &conjunction, Usd_Term rhs) {
379  return Usd_PrimFlagsConjunction(conjunction) &= rhs;
380 }
381 
382 inline Usd_PrimFlagsConjunction
383 operator&&(Usd_Term lhs, const Usd_PrimFlagsConjunction &conjunction) {
384  return Usd_PrimFlagsConjunction(conjunction) &= lhs;
385 }
386 
387 inline Usd_PrimFlagsConjunction
388 operator&&(Usd_PrimFlags lhs, Usd_PrimFlags rhs) {
389  return Usd_Term(lhs) && Usd_Term(rhs);
390 }
391 
392 
403 class Usd_PrimFlagsDisjunction : public Usd_PrimFlagsPredicate {
404 public:
405  // Default constructed disjunction is a contradiction.
406  Usd_PrimFlagsDisjunction() { _Negate(); };
407 
408  // Construct with a term.
409  explicit Usd_PrimFlagsDisjunction(Usd_Term term) {
410  _Negate();
411  *this |= term;
412  }
413 
415  Usd_PrimFlagsDisjunction &operator|=(Usd_Term term) {
416  // If this disjunction is a tautology, do nothing.
417  if (ARCH_UNLIKELY(_IsTautology()))
418  return *this;
419 
420  // If we don't have the bit, set it in _mask and _values (if needed).
421  if (!_mask[term.flag]) {
422  _mask[term.flag] = 1;
423  _values[term.flag] = term.negated;
424  } else if (_values[term.flag] != term.negated) {
425  // If we do have the bit and the values disagree, then this entire
426  // disjunction becomes a tautology. If the values agree, it's
427  // redundant and we do nothing.
428  _MakeTautology();
429  }
430  return *this;
431  }
432 
450  USD_API
451  class Usd_PrimFlagsConjunction operator!() const;
452 
453 private:
454 
455  // Let Usd_PrimFlagsDisjunction produce conjunctions when negated.
456  friend class Usd_PrimFlagsConjunction;
457  Usd_PrimFlagsDisjunction(const Usd_PrimFlagsPredicate &base) :
458  Usd_PrimFlagsPredicate(base) {}
459 
461  friend Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs);
462 
464  friend Usd_PrimFlagsDisjunction
465  operator||(const Usd_PrimFlagsDisjunction &disjunction, Usd_Term rhs);
466 
468  friend Usd_PrimFlagsDisjunction
469  operator||(Usd_Term lhs, const Usd_PrimFlagsDisjunction &disjunction);
470 };
471 
472 inline Usd_PrimFlagsDisjunction
473 operator||(Usd_Term lhs, Usd_Term rhs) {
474  return (Usd_PrimFlagsDisjunction() || lhs) || rhs;
475 }
476 
477 inline Usd_PrimFlagsDisjunction
478 operator||(const Usd_PrimFlagsDisjunction &disjunction, Usd_Term rhs) {
479  return Usd_PrimFlagsDisjunction(disjunction) |= rhs;
480 }
481 
482 inline Usd_PrimFlagsDisjunction
483 operator||(Usd_Term lhs, const Usd_PrimFlagsDisjunction &disjunction) {
484  return Usd_PrimFlagsDisjunction(disjunction) |= lhs;
485 }
486 
487 inline Usd_PrimFlagsDisjunction
488 operator||(Usd_PrimFlags lhs, Usd_PrimFlags rhs) {
489  return Usd_Term(lhs) || Usd_Term(rhs);
490 }
491 
492 #ifdef doxygen
493 
495 extern unspecified UsdPrimIsActive;
497 extern unspecified UsdPrimIsLoaded;
499 extern unspecified UsdPrimIsModel;
501 extern unspecified UsdPrimIsGroup;
503 extern unspecified UsdPrimIsAbstract;
505 extern unspecified UsdPrimIsDefined;
507 extern unspecified UsdPrimIsInstance;
509 extern unspecified UsdPrimHasDefiningSpecifier;
510 
523 extern unspecified UsdPrimDefaultPredicate;
524 
528 extern unspecified UsdPrimAllPrimsPredicate;
529 
530 #else
531 
532 static const Usd_PrimFlags UsdPrimIsActive = Usd_PrimActiveFlag;
533 static const Usd_PrimFlags UsdPrimIsLoaded = Usd_PrimLoadedFlag;
534 static const Usd_PrimFlags UsdPrimIsModel = Usd_PrimModelFlag;
535 static const Usd_PrimFlags UsdPrimIsGroup = Usd_PrimGroupFlag;
536 static const Usd_PrimFlags UsdPrimIsAbstract = Usd_PrimAbstractFlag;
537 static const Usd_PrimFlags UsdPrimIsDefined = Usd_PrimDefinedFlag;
538 static const Usd_PrimFlags UsdPrimIsInstance = Usd_PrimInstanceFlag;
539 static const Usd_PrimFlags UsdPrimHasDefiningSpecifier
540  = Usd_PrimHasDefiningSpecifierFlag;
541 
542 USD_API extern const Usd_PrimFlagsConjunction UsdPrimDefaultPredicate;
543 USD_API extern const Usd_PrimFlagsPredicate UsdPrimAllPrimsPredicate;
544 
545 #endif // doxygen
546 
577 inline Usd_PrimFlagsPredicate
578 UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
579 {
580  return predicate.TraverseInstanceProxies(true);
581 }
582 
587 inline Usd_PrimFlagsPredicate
589 {
591 }
592 
593 PXR_NAMESPACE_CLOSE_SCOPE
594 
595 #endif // PXR_USD_USD_PRIM_FLAGS_H
unspecified UsdPrimDefaultPredicate
The default predicate used for prim traversals in methods like UsdPrim::GetChildren,...
unspecified UsdPrimIsAbstract
Tests UsdPrim::IsAbstract()
unspecified UsdPrimHasDefiningSpecifier
Tests UsdPrim::HasDefiningSpecifier()
Compiler hints.
unspecified UsdPrimIsModel
Tests UsdPrim::IsModel()
unspecified UsdPrimIsActive
Tests UsdPrim::IsActive()
unspecified UsdPrimIsLoaded
Tests UsdPrim::IsLoaded()
unspecified UsdPrimIsDefined
Tests UsdPrim::IsDefined()
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
Definition: prim.h:134
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
This function is used to allow the prim traversal functions listed under Prim predicate flags to trav...
Definition: primFlags.h:578
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
std::enable_if< std::is_same< Half, half >::value, size_t >::type hash_value(const Half &h)
Overload hash_value for half.
Definition: half.h:50
unspecified UsdPrimAllPrimsPredicate
Predicate that includes all prims.
unspecified UsdPrimIsInstance
Tests UsdPrim::IsInstance()
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
unspecified UsdPrimIsGroup
Tests UsdPrim::IsGroup()