All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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
57
58#include "pxr/pxr.h"
59#include "pxr/usd/usd/api.h"
60#include "pxr/base/arch/hints.h"
62#include "pxr/base/tf/hash.h"
63
64#include <bitset>
65
66PXR_NAMESPACE_OPEN_SCOPE
67
68class SdfPath;
69
70// Enum for cached flags on prims.
71enum Usd_PrimFlags {
72 // Flags for use with predicates.
73 Usd_PrimActiveFlag,
74 Usd_PrimLoadedFlag,
75 Usd_PrimModelFlag,
76 Usd_PrimGroupFlag,
77 Usd_PrimComponentFlag,
78 Usd_PrimAbstractFlag,
79 Usd_PrimDefinedFlag,
80 Usd_PrimHasDefiningSpecifierFlag,
81 Usd_PrimInstanceFlag,
82
83 // Flags for internal use.
84 Usd_PrimHasPayloadFlag,
85 Usd_PrimClipsFlag,
86 Usd_PrimDeadFlag,
87 Usd_PrimPrototypeFlag,
88 Usd_PrimInstanceProxyFlag,
89 Usd_PrimPseudoRootFlag,
90
91 Usd_PrimNumFlags
92};
93
94typedef 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.
99struct 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 }
109 Usd_PrimFlags flag;
110 bool negated;
111};
112
113inline Usd_Term
114operator!(Usd_PrimFlags flag) {
115 return Usd_Term(flag, /*negated=*/true);
116}
117
118// Predicate functor class that tests a prim's flags against desired values.
119class Usd_PrimFlagsPredicate
120{
121public:
122 // Functor result type.
123 typedef bool result_type;
124
125 // Default ctor produces a tautology.
126 Usd_PrimFlagsPredicate() : _negate(false) {}
127
128 Usd_PrimFlagsPredicate(Usd_PrimFlags flag)
129 : _negate(false) {
130 _mask[flag] = 1;
131 _values[flag] = true;
132 }
133
134 // Implicit conversion from a single term.
135 Usd_PrimFlagsPredicate(Usd_Term 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.
143 static Usd_PrimFlagsPredicate Tautology() {
144 return Usd_PrimFlagsPredicate();
145 }
146
147 // Convenience to produce a contradictory predicate. Returns a negated
148 // default-constructed predicate.
149 static Usd_PrimFlagsPredicate Contradiction() {
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.
156 Usd_PrimFlagsPredicate &TraverseInstanceProxies(bool traverse) {
157 if (traverse) {
158 _mask[Usd_PrimInstanceProxyFlag] = 0;
159 _values[Usd_PrimInstanceProxyFlag] = 1;
160 }
161 else {
162 _mask[Usd_PrimInstanceProxyFlag] = 1;
163 _values[Usd_PrimInstanceProxyFlag] = 0;
164 }
165 return *this;
166 }
167
168 // Returns true if this predicate was explicitly set to include
169 // instance proxies, false otherwise.
170 bool IncludeInstanceProxiesInTraversal() const {
171 return !_mask[Usd_PrimInstanceProxyFlag] &&
172 _values[Usd_PrimInstanceProxyFlag];
173 }
174
175 // Invoke boolean predicate on UsdPrim \p prim.
176 USD_API
177 bool operator()(const class UsdPrim &prim) const;
178
179protected:
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.
194 Usd_PrimFlagsPredicate &_Negate() {
195 _negate = !_negate;
196 return *this;
197 }
198
199 // Return a negated copy of this predicate.
200 Usd_PrimFlagsPredicate _GetNegated() const {
201 return Usd_PrimFlagsPredicate(*this)._Negate();
202 }
203
204 // Mask indicating which flags are of interest.
205 Usd_PrimFlagBits _mask;
206
207 // Desired values for prim flags.
208 Usd_PrimFlagBits _values;
209
210private:
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
246 operator==(const Usd_PrimFlagsPredicate &lhs,
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
254 operator!=(const Usd_PrimFlagsPredicate &lhs,
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
282class Usd_PrimFlagsConjunction : public Usd_PrimFlagsPredicate {
283public:
285 Usd_PrimFlagsConjunction() {};
286
288 explicit Usd_PrimFlagsConjunction(Usd_Term term) {
289 *this &= term;
290 }
291
293 Usd_PrimFlagsConjunction &operator&=(Usd_Term term) {
294 // If this conjunction is a contradiction, do nothing.
295 if (ARCH_UNLIKELY(_IsContradiction()))
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.
306 _MakeContradiction();
307 }
308 return *this;
309 }
310
328 USD_API
329 class Usd_PrimFlagsDisjunction operator!() const;
330
331private:
332
333 // Let Usd_PrimFlagsDisjunction produce conjunctions when negated
334 friend class Usd_PrimFlagsDisjunction;
335 Usd_PrimFlagsConjunction(const Usd_PrimFlagsPredicate &base) :
336 Usd_PrimFlagsPredicate(base) {}
337
339 friend Usd_PrimFlagsConjunction
340 operator&&(Usd_Term lhs, Usd_Term rhs);
341
343 friend Usd_PrimFlagsConjunction
344 operator&&(const Usd_PrimFlagsConjunction &conjunction, Usd_Term rhs);
345
347 friend Usd_PrimFlagsConjunction
348 operator&&(Usd_Term lhs, const Usd_PrimFlagsConjunction &conjunction);
349};
350
351inline Usd_PrimFlagsConjunction
352operator&&(Usd_Term lhs, Usd_Term rhs) {
353 // Apparently gcc 4.8.x doesn't like this as:
354 // return (Usd_PrimFlagsConjunction() && lhs) && rhs;
355 Usd_PrimFlagsConjunction tmp;
356 return (tmp && lhs) && rhs;
357}
358
359inline Usd_PrimFlagsConjunction
360operator&&(const Usd_PrimFlagsConjunction &conjunction, Usd_Term rhs) {
361 return Usd_PrimFlagsConjunction(conjunction) &= rhs;
362}
363
364inline Usd_PrimFlagsConjunction
365operator&&(Usd_Term lhs, const Usd_PrimFlagsConjunction &conjunction) {
366 return Usd_PrimFlagsConjunction(conjunction) &= lhs;
367}
368
369inline Usd_PrimFlagsConjunction
370operator&&(Usd_PrimFlags lhs, Usd_PrimFlags rhs) {
371 return Usd_Term(lhs) && Usd_Term(rhs);
372}
373
374
385class Usd_PrimFlagsDisjunction : public Usd_PrimFlagsPredicate {
386public:
387 // Default constructed disjunction is a contradiction.
388 Usd_PrimFlagsDisjunction() { _Negate(); };
389
390 // Construct with a term.
391 explicit Usd_PrimFlagsDisjunction(Usd_Term term) {
392 _Negate();
393 *this |= term;
394 }
395
397 Usd_PrimFlagsDisjunction &operator|=(Usd_Term term) {
398 // If this disjunction is a tautology, do nothing.
399 if (ARCH_UNLIKELY(_IsTautology()))
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
432 USD_API
433 class Usd_PrimFlagsConjunction operator!() const;
434
435private:
436
437 // Let Usd_PrimFlagsDisjunction produce conjunctions when negated.
438 friend class Usd_PrimFlagsConjunction;
439 Usd_PrimFlagsDisjunction(const Usd_PrimFlagsPredicate &base) :
440 Usd_PrimFlagsPredicate(base) {}
441
443 friend Usd_PrimFlagsDisjunction operator||(Usd_Term lhs, Usd_Term rhs);
444
446 friend Usd_PrimFlagsDisjunction
447 operator||(const Usd_PrimFlagsDisjunction &disjunction, Usd_Term rhs);
448
450 friend Usd_PrimFlagsDisjunction
451 operator||(Usd_Term lhs, const Usd_PrimFlagsDisjunction &disjunction);
452};
453
454inline Usd_PrimFlagsDisjunction
455operator||(Usd_Term lhs, Usd_Term rhs) {
456 return (Usd_PrimFlagsDisjunction() || lhs) || rhs;
457}
458
459inline Usd_PrimFlagsDisjunction
460operator||(const Usd_PrimFlagsDisjunction &disjunction, Usd_Term rhs) {
461 return Usd_PrimFlagsDisjunction(disjunction) |= rhs;
462}
463
464inline Usd_PrimFlagsDisjunction
465operator||(Usd_Term lhs, const Usd_PrimFlagsDisjunction &disjunction) {
466 return Usd_PrimFlagsDisjunction(disjunction) |= lhs;
467}
468
469inline Usd_PrimFlagsDisjunction
470operator||(Usd_PrimFlags lhs, Usd_PrimFlags rhs) {
471 return Usd_Term(lhs) || Usd_Term(rhs);
472}
473
474#ifdef doxygen
475
477extern unspecified UsdPrimIsActive;
479extern unspecified UsdPrimIsLoaded;
481extern unspecified UsdPrimIsModel;
483extern unspecified UsdPrimIsGroup;
485extern unspecified UsdPrimIsAbstract;
487extern unspecified UsdPrimIsDefined;
489extern unspecified UsdPrimIsInstance;
491extern unspecified UsdPrimHasDefiningSpecifier;
492
505extern unspecified UsdPrimDefaultPredicate;
506
510extern unspecified UsdPrimAllPrimsPredicate;
511
512#else
513
514static const Usd_PrimFlags UsdPrimIsActive = Usd_PrimActiveFlag;
515static const Usd_PrimFlags UsdPrimIsLoaded = Usd_PrimLoadedFlag;
516static const Usd_PrimFlags UsdPrimIsModel = Usd_PrimModelFlag;
517static const Usd_PrimFlags UsdPrimIsGroup = Usd_PrimGroupFlag;
518static const Usd_PrimFlags UsdPrimIsAbstract = Usd_PrimAbstractFlag;
519static const Usd_PrimFlags UsdPrimIsDefined = Usd_PrimDefinedFlag;
520static const Usd_PrimFlags UsdPrimIsInstance = Usd_PrimInstanceFlag;
521static const Usd_PrimFlags UsdPrimHasDefiningSpecifier
522 = Usd_PrimHasDefiningSpecifierFlag;
523
524USD_API extern const Usd_PrimFlagsConjunction UsdPrimDefaultPredicate;
525USD_API extern const Usd_PrimFlagsPredicate UsdPrimAllPrimsPredicate;
526
527#endif // doxygen
528
559inline Usd_PrimFlagsPredicate
560UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
561{
562 return predicate.TraverseInstanceProxies(true);
563}
564
569inline Usd_PrimFlagsPredicate
571{
573}
574
575PXR_NAMESPACE_CLOSE_SCOPE
576
577#endif // PXR_USD_USD_PRIM_FLAGS_H
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:274
static size_t Combine(Args &&... args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:475
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
Definition: prim.h:117
size_t hash_value(const half h)
Overload hash_value for half.
Definition: half.h:28
Compiler hints.
unspecified UsdPrimIsGroup
Tests UsdPrim::IsGroup()
unspecified UsdPrimIsActive
Tests UsdPrim::IsActive()
unspecified UsdPrimIsDefined
Tests UsdPrim::IsDefined()
unspecified UsdPrimIsInstance
Tests UsdPrim::IsInstance()
unspecified UsdPrimIsLoaded
Tests UsdPrim::IsLoaded()
unspecified UsdPrimDefaultPredicate
The default predicate used for prim traversals in methods like UsdPrim::GetChildren,...
unspecified UsdPrimIsAbstract
Tests UsdPrim::IsAbstract()
unspecified UsdPrimIsModel
Tests UsdPrim::IsModel()
unspecified UsdPrimHasDefiningSpecifier
Tests UsdPrim::HasDefiningSpecifier()
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: primFlags.h:570
unspecified UsdPrimAllPrimsPredicate
Predicate that includes all prims.