All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
primData.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 USD_PRIMDATA_H
25 #define USD_PRIMDATA_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usd/api.h"
31 #include "pxr/usd/usd/common.h"
32 #include "pxr/usd/usd/primFlags.h"
33 #include "pxr/usd/sdf/types.h"
34 
35 #include "pxr/base/tf/declarePtrs.h"
36 #include "pxr/base/tf/pointerAndBits.h"
37 #include "pxr/base/tf/token.h"
38 
39 #include "pxr/usd/sdf/path.h"
40 
41 #include <boost/range/iterator_range.hpp>
42 #include <boost/iterator/iterator_adaptor.hpp>
43 #include <boost/intrusive_ptr.hpp>
44 
45 #include <atomic>
46 #include <cstdint>
47 #include <vector>
48 
49 PXR_NAMESPACE_OPEN_SCOPE
50 
51 
53 
54 // Private class that stores cached prim information and defines the prim tree
55 // on a UsdStage.
56 //
57 // Usd_PrimData objects are arranged in a tree structure, represented as a
58 // binary tree. See the _firstChild and _nextSiblingOrParent members.
59 //
60 // UsdStage builds and manages the tree structure of Usd_PrimData objects. The
61 // Usd_PrimData objects lifetimes are governed by an internal reference count
62 // (see _refCount). Two objects mutate this reference count: UsdStage owns
63 // references to all the Usd_PrimData objects that represent the scene graph,
64 // and UsdObject (and by inheritance its subclasses) owns a reference to its
65 // prim data object via Usd_PrimDataHandle.
66 //
67 // Usd_PrimData has a 'dead' flag (see _IsDead and _MarkDead). UsdStage sets
68 // this when a prim data object is removed from the scene graph.
69 // Usd_PrimDataHandle, which is a smart pointer to Usd_PrimData consults this
70 // dead flag to determine prim validity, and to issue informative crash messages
71 // on invalid use. See USD_CHECK_ALL_PRIM_ACCESSES.
72 //
73 class Usd_PrimData
74 {
75 public:
76 
77  // --------------------------------------------------------------------- //
79  // --------------------------------------------------------------------- //
80 
87  const SdfPath &GetPath() const { return _path; }
88 
89  const TfToken &GetName() const { return GetPath().GetNameToken(); }
90 
91  UsdStage *GetStage() const { return _stage; }
92 
95  const TfToken &GetTypeName() const { return _typeName; };
96 
99  bool IsActive() const { return _flags[Usd_PrimActiveFlag]; }
100 
104  bool IsLoaded() const { return _flags[Usd_PrimLoadedFlag]; }
105 
108  bool IsModel() const { return _flags[Usd_PrimModelFlag]; }
109 
113  bool IsGroup() const { return _flags[Usd_PrimGroupFlag]; }
114 
116  bool IsAbstract() const { return _flags[Usd_PrimAbstractFlag]; }
117 
120  bool IsDefined() const { return _flags[Usd_PrimDefinedFlag]; }
121 
124  bool HasDefiningSpecifier() const {
125  return _flags[Usd_PrimHasDefiningSpecifierFlag];
126  }
127 
129  bool HasPayload() const { return _flags[Usd_PrimHasPayloadFlag]; }
130 
134  bool MayHaveOpinionsInClips() const { return _flags[Usd_PrimClipsFlag]; }
135 
137  USD_API
138  SdfSpecifier GetSpecifier() const;
139 
140  // --------------------------------------------------------------------- //
142  // --------------------------------------------------------------------- //
143 
145  USD_API
146  Usd_PrimDataConstPtr GetParent() const;
147 
148  // --------------------------------------------------------------------- //
149  // PrimIndex access.
150  // --------------------------------------------------------------------- //
151 
168  USD_API
169  const class PcpPrimIndex &GetPrimIndex() const;
170 
177  USD_API
178  const class PcpPrimIndex &GetSourcePrimIndex() const;
179 
180  // --------------------------------------------------------------------- //
181  // Tree Structure
182  // --------------------------------------------------------------------- //
183 
184  // Return this prim data's first child if it has one, nullptr otherwise.
185  Usd_PrimDataPtr GetFirstChild() const { return _firstChild; }
186 
187  // Return this prim data's next sibling if it has one, nullptr otherwise.
188  Usd_PrimDataPtr GetNextSibling() const {
189  return !_nextSiblingOrParent.BitsAs<bool>() ?
190  _nextSiblingOrParent.Get() : nullptr;
191  }
192 
193  // Return this prim data's parent if this prim data is the last in its chain
194  // of siblings. That is, if the _nextSiblingOrParent field is pointing to
195  // its parent. Return nullptr otherwise.
196  Usd_PrimDataPtr GetParentLink() const {
197  return _nextSiblingOrParent.BitsAs<bool>() ?
198  _nextSiblingOrParent.Get() : nullptr;
199  }
200 
201  // Return the next prim data "to the right" of this one. That is, this
202  // prim's next sibling if it has one, otherwise the next sibling of the
203  // nearest ancestor with a sibling, if there is one, otherwise null.
204  inline Usd_PrimDataPtr GetNextPrim() const {
205  if (Usd_PrimDataPtr sibling = GetNextSibling())
206  return sibling;
207  for (Usd_PrimDataPtr p = GetParentLink(); p; p = p->GetParentLink()) {
208  if (Usd_PrimDataPtr sibling = p->GetNextSibling())
209  return sibling;
210  }
211  return nullptr;
212  }
213 
214  // Return the prim data at \p path. If \p path indicates a prim
215  // beneath an instance, return the prim data for the corresponding
216  // prim in the instance's master.
217  USD_API Usd_PrimDataConstPtr
218  GetPrimDataAtPathOrInMaster(const SdfPath &path) const;
219 
220  // --------------------------------------------------------------------- //
221  // Instancing
222  // --------------------------------------------------------------------- //
223 
226  bool IsInstance() const { return _flags[Usd_PrimInstanceFlag]; }
227 
229  bool IsMaster() const { return IsInMaster() && GetPath().IsRootPrimPath(); }
230 
233  bool IsInMaster() const { return _flags[Usd_PrimMasterFlag]; }
234 
237  USD_API Usd_PrimDataConstPtr GetMaster() const;
238 
239  // --------------------------------------------------------------------- //
240  // Private Members
241  // --------------------------------------------------------------------- //
242 private:
243 
244  USD_API
245  Usd_PrimData(UsdStage *stage, const SdfPath& path);
246  USD_API
247  ~Usd_PrimData();
248 
249  // Compute and store cached flags.
250  void _ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim);
251 
252  // Flags direct access for Usd_PrimFlagsPredicate.
253  friend class Usd_PrimFlagsPredicate;
254  const Usd_PrimFlagBits &_GetFlags() const {
255  return _flags;
256  }
257 
258  // --------------------------------------------------------------------- //
259  // Prim Children
260  // --------------------------------------------------------------------- //
261 
262  // Composes the prim children, reporting errors as they occur. Returns true
263  // on success false on failure.
264  bool _ComposePrimChildNames(TfTokenVector* nameOrder);
265 
266  void _SetSiblingLink(Usd_PrimDataPtr sibling) {
267  _nextSiblingOrParent.Set(sibling, /* isParent */ false);
268  }
269 
270  void _SetParentLink(Usd_PrimDataPtr parent) {
271  _nextSiblingOrParent.Set(parent, /* isParent */ true);
272  }
273 
274  void _AddChild(Usd_PrimDataPtr child) {
275  // Add \a child as the first child. If _firstChild is nullptr, we are
276  // adding this primdata's first child so we instead set its parent link
277  // to this.
278  if (_firstChild)
279  child->_SetSiblingLink(_firstChild);
280  else
281  child->_SetParentLink(this);
282  _firstChild = child;
283  };
284 
285  // Set the dead bit on this prim data object.
286  void _MarkDead() {
287  _flags[Usd_PrimDeadFlag] = true;
288  _stage = nullptr;
289  _primIndex = nullptr;
290  }
291 
292  // Return true if this prim's dead flag is set, false otherwise.
293  bool _IsDead() const { return _flags[Usd_PrimDeadFlag]; }
294 
295  // Set whether this prim or any of its namespace ancestors had clips
296  // specified.
297  void _SetMayHaveOpinionsInClips(bool hasClips) {
298  _flags[Usd_PrimClipsFlag] = hasClips;
299  }
300 
301  typedef boost::iterator_range<
302  class Usd_PrimDataSiblingIterator> SiblingRange;
303 
304  inline class Usd_PrimDataSiblingIterator _ChildrenBegin() const;
305  inline class Usd_PrimDataSiblingIterator _ChildrenEnd() const;
306  inline SiblingRange _GetChildrenRange() const;
307 
308  typedef boost::iterator_range<
309  class Usd_PrimDataSubtreeIterator> SubtreeRange;
310 
311  inline class Usd_PrimDataSubtreeIterator _SubtreeBegin() const;
312  inline class Usd_PrimDataSubtreeIterator _SubtreeEnd() const;
313  inline SubtreeRange _GetSubtreeRange() const;
314 
315  // Data members.
316  UsdStage *_stage;
317  const PcpPrimIndex *_primIndex;
318  SdfPath _path;
319  TfToken _typeName;
320  Usd_PrimData *_firstChild;
321  TfPointerAndBits<Usd_PrimData> _nextSiblingOrParent;
322  mutable std::atomic<int64_t> _refCount;
323  Usd_PrimFlagBits _flags;
324 
325  // intrusive_ptr core primitives implementation.
326  friend void intrusive_ptr_add_ref(const Usd_PrimData *prim) {
327  prim->_refCount.fetch_add(1, std::memory_order_relaxed);
328  }
329  friend void intrusive_ptr_release(const Usd_PrimData *prim) {
330  if (prim->_refCount.fetch_sub(1, std::memory_order_release) == 1)
331  delete prim;
332  }
333 
334  USD_API
335  friend void Usd_IssueFatalPrimAccessError(Usd_PrimData const *p);
336  friend std::string
337  Usd_DescribePrimData(const Usd_PrimData *p, SdfPath const &proxyPrimPath);
338 
339  friend inline bool Usd_IsDead(Usd_PrimData const *p) {
340  return p->_IsDead();
341  }
342 
343  friend class UsdPrim;
344  friend class UsdStage;
345 };
346 
347 // Sibling iterator class.
348 class Usd_PrimDataSiblingIterator : public boost::iterator_adaptor<
349  Usd_PrimDataSiblingIterator, // crtp.
350  Usd_PrimData *, // base iterator.
351  Usd_PrimData *, // value.
352  boost::forward_traversal_tag, // traversal.
353  Usd_PrimData * // reference.
354  >
355 {
356 public:
357  // Default ctor.
358  Usd_PrimDataSiblingIterator() {}
359 
360 private:
361  friend class Usd_PrimData;
362 
363  // Constructor used by Prim.
364  Usd_PrimDataSiblingIterator(const base_type &i)
365  : iterator_adaptor_(i) {}
366 
367  // Core primitives implementation.
368  friend class boost::iterator_core_access;
369  reference dereference() const { return base(); }
370  void increment() {
371  base_reference() = base_reference()->GetNextSibling();
372  }
373 };
374 
375 // Sibling range.
376 typedef boost::iterator_range<
377  class Usd_PrimDataSiblingIterator> Usd_PrimDataSiblingRange;
378 
379 // Inform TfIterator it should feel free to make copies of the range type.
380 template <>
381 struct Tf_ShouldIterateOverCopy<
382  Usd_PrimDataSiblingRange> : boost::true_type {};
383 template <>
384 struct Tf_ShouldIterateOverCopy<
385  const Usd_PrimDataSiblingRange> : boost::true_type {};
386 
387 Usd_PrimDataSiblingIterator
388 Usd_PrimData::_ChildrenBegin() const
389 {
390  return Usd_PrimDataSiblingIterator(_firstChild);
391 }
392 
393 Usd_PrimDataSiblingIterator
394 Usd_PrimData::_ChildrenEnd() const
395 {
396  return Usd_PrimDataSiblingIterator(0);
397 }
398 
399 Usd_PrimData::SiblingRange
400 Usd_PrimData::_GetChildrenRange() const
401 {
402  return Usd_PrimData::SiblingRange(_ChildrenBegin(), _ChildrenEnd());
403 }
404 
405 
406 // Tree iterator class.
407 class Usd_PrimDataSubtreeIterator : public boost::iterator_adaptor<
408  Usd_PrimDataSubtreeIterator, // crtp.
409  Usd_PrimData *, // base iterator.
410  Usd_PrimData *, // value.
411  boost::forward_traversal_tag, // traversal.
412  Usd_PrimData * // reference.
413  >
414 {
415 public:
416  // Default ctor.
417  Usd_PrimDataSubtreeIterator() {}
418 
419 private:
420  friend class Usd_PrimData;
421  friend class UsdPrimSubtreeIterator;
422 
423  // Constructor used by Prim.
424  Usd_PrimDataSubtreeIterator(const base_type &i)
425  : iterator_adaptor_(i) {}
426 
427  // Core primitives implementation.
428  friend class boost::iterator_core_access;
429  reference dereference() const { return base(); }
430  void increment() {
431  base_type &b = base_reference();
432  b = b->GetFirstChild() ? b->GetFirstChild() : b->GetNextPrim();
433  }
434 };
435 
436 // Tree range.
437 typedef boost::iterator_range<
438  class Usd_PrimDataSubtreeIterator> Usd_PrimDataSubtreeRange;
439 
440 // Inform TfIterator it should feel free to make copies of the range type.
441 template <>
442 struct Tf_ShouldIterateOverCopy<
443  Usd_PrimDataSubtreeRange> : boost::true_type {};
444 template <>
445 struct Tf_ShouldIterateOverCopy<
446  const Usd_PrimDataSubtreeRange> : boost::true_type {};
447 
448 Usd_PrimDataSubtreeIterator
449 Usd_PrimData::_SubtreeBegin() const
450 {
451  return Usd_PrimDataSubtreeIterator(
452  _firstChild ? _firstChild : GetNextPrim());
453 }
454 
455 Usd_PrimDataSubtreeIterator
456 Usd_PrimData::_SubtreeEnd() const
457 {
458  return Usd_PrimDataSubtreeIterator(GetNextPrim());
459 }
460 
461 Usd_PrimData::SubtreeRange
462 Usd_PrimData::_GetSubtreeRange() const
463 {
464  return Usd_PrimData::SubtreeRange(_SubtreeBegin(), _SubtreeEnd());
465 }
466 
467 // Helpers for instance proxies.
468 
469 // Return true if the prim with prim data \p p and proxy prim path
470 // \p proxyPrimPath represents an instance proxy.
471 template <class PrimDataPtr>
472 inline bool
473 Usd_IsInstanceProxy(const PrimDataPtr &p, const SdfPath &proxyPrimPath)
474 {
475  return !proxyPrimPath.IsEmpty();
476 }
477 
478 // Helpers for subtree traversals.
479 
480 // Create a predicate based on \p pred for use when traversing the
481 // siblings or descendants of the prim with prim data \p p and proxy
482 // prim path \p proxyPrimPath. This is used by prim traversal functions
483 // like UsdPrim::GetFilteredChildren, UsdPrim::GetFilteredDescendants,
484 // UsdPrim::GetFilteredNextSibling, and UsdPrimRange.
485 template <class PrimDataPtr>
486 inline Usd_PrimFlagsPredicate
487 Usd_CreatePredicateForTraversal(const PrimDataPtr &p,
488  const SdfPath &proxyPrimPath,
489  Usd_PrimFlagsPredicate pred)
490 {
491  // Don't allow traversals beneath instances unless the client has
492  // explicitly requested it or the starting point is already beneath
493  // an instance (i.e., the starting point is an instance proxy).
494  if (!Usd_IsInstanceProxy(p, proxyPrimPath) &&
495  !pred.IncludeInstanceProxiesInTraversal()) {
496  pred.TraverseInstanceProxies(false);
497  }
498  return pred;
499 }
500 
501 // Move \p p to its parent. If \p proxyPrimPath is not empty, set it to
502 // its parent path. If after this \p p is a master prim, move \p p to
503 // the prim indicated by \p proxyPrimPath. If \p p's path is then equal
504 // to \p proxyPrimPath, set \p proxyPrimPath to the empty path.
505 template <class PrimDataPtr>
506 inline void
507 Usd_MoveToParent(PrimDataPtr &p, SdfPath &proxyPrimPath)
508 {
509  p = p->GetParent();
510 
511  if (!proxyPrimPath.IsEmpty()) {
512  proxyPrimPath = proxyPrimPath.GetParentPath();
513 
514  if (p && p->IsMaster()) {
515  p = p->GetPrimDataAtPathOrInMaster(proxyPrimPath);
516  if (TF_VERIFY(p, "No prim at <%s>", proxyPrimPath.GetText()) &&
517  p->GetPath() == proxyPrimPath) {
518  proxyPrimPath = SdfPath();
519  }
520  }
521  }
522 }
523 
524 // Search for the next sibling that matches \p pred (up to \p end). If such a
525 // sibling exists, move \p p to it and return false. If no such sibling exists
526 // then move \p p to its parent and return true. If \p end is reached while
527 // looking for siblings, move \p p to \p end and return false.
528 //
529 // If \p proxyPrimPath is not empty, update it based on the new value of \p p:
530 // - If \p p was moved to \p end, set \p proxyPrimPath to the empty path.
531 // - If \p p was moved to a sibling, set the prim name for \p proxyPrimPath
532 // to the sibling's name.
533 // - If \p p was moved to a parent, set \p proxyPrimPath and \p p the same
534 // way as Usd_MoveToParent.
535 template <class PrimDataPtr>
536 inline bool
537 Usd_MoveToNextSiblingOrParent(PrimDataPtr &p, SdfPath &proxyPrimPath,
538  PrimDataPtr end,
539  const Usd_PrimFlagsPredicate &pred)
540 {
541  // Either all siblings are instance proxies or none are. We can just
542  // compute this once and reuse it as we scan for the next sibling.
543  const bool isInstanceProxy = Usd_IsInstanceProxy(p, proxyPrimPath);
544 
545  PrimDataPtr next = p->GetNextSibling();
546  while (next && next != end &&
547  !Usd_EvalPredicate(pred, next, isInstanceProxy)) {
548  p = next;
549  next = p->GetNextSibling();
550  }
551  p = next ? next : p->GetParentLink();
552 
553  if (!proxyPrimPath.IsEmpty()) {
554  if (p == end) {
555  proxyPrimPath = SdfPath();
556  }
557  else if (p == next) {
558  proxyPrimPath =
559  proxyPrimPath.GetParentPath().AppendChild(p->GetName());
560  }
561  else {
562  proxyPrimPath = proxyPrimPath.GetParentPath();
563  if (p && p->IsMaster()) {
564  p = p->GetPrimDataAtPathOrInMaster(proxyPrimPath);
565  if (TF_VERIFY(p, "No prim at <%s>", proxyPrimPath.GetText()) &&
566  p->GetPath() == proxyPrimPath) {
567  proxyPrimPath = SdfPath();
568  }
569  }
570  }
571  }
572 
573  // Return true if we successfully moved to a parent, otherwise false.
574  return !next && p;
575 }
576 
577 // Convenience method for calling the above with \p end = \c nullptr.
578 template <class PrimDataPtr>
579 inline bool
580 Usd_MoveToNextSiblingOrParent(PrimDataPtr &p, SdfPath &proxyPrimPath,
581  const Usd_PrimFlagsPredicate &pred)
582 {
583  return Usd_MoveToNextSiblingOrParent(p, proxyPrimPath,
584  PrimDataPtr(nullptr), pred);
585 }
586 
587 // Search for the first direct child of \p p that matches \p pred (up to
588 // \p end). If the given \p p is an instance, search for direct children
589 // on the corresponding master prim. If such a direct child exists,
590 // move \p p to it, and return true. Otherwise leave the iterator
591 // unchanged and return false.
592 template <class PrimDataPtr>
593 inline bool
594 Usd_MoveToChild(PrimDataPtr &p, SdfPath &proxyPrimPath,
595  PrimDataPtr end,
596  const Usd_PrimFlagsPredicate &pred)
597 {
598  bool isInstanceProxy = Usd_IsInstanceProxy(p, proxyPrimPath);
599 
600  PrimDataPtr src = p;
601  if (src->IsInstance()) {
602  src = src->GetMaster();
603  isInstanceProxy = true;
604  }
605 
606  if (PrimDataPtr child = src->GetFirstChild()) {
607  if (isInstanceProxy) {
608  proxyPrimPath = proxyPrimPath.IsEmpty() ?
609  p->GetPath().AppendChild(child->GetName()) :
610  proxyPrimPath.AppendChild(child->GetName());
611  }
612 
613  p = child;
614 
615  if (Usd_EvalPredicate(pred, p, isInstanceProxy) ||
616  !Usd_MoveToNextSiblingOrParent(p, proxyPrimPath, end, pred)) {
617  return true;
618  }
619  }
620  return false;
621 }
622 
623 // Convenience method for calling the above with \p end = \c nullptr.
624 template <class PrimDataPtr>
625 inline bool
626 Usd_MoveToChild(PrimDataPtr &p, SdfPath &proxyPrimPath,
627  const Usd_PrimFlagsPredicate &pred)
628 {
629  return Usd_MoveToChild(p, proxyPrimPath, PrimDataPtr(nullptr), pred);
630 }
631 
632 PXR_NAMESPACE_CLOSE_SCOPE
633 
634 #endif // USD_PRIMDATA_H
PcpPrimIndex is an index of the all sites of scene description that contribute opinions to a specific...
Definition: primIndex.h:77
#define TF_DECLARE_WEAK_PTRS(type)
Define standard weak pointer types.
Definition: declarePtrs.h:62
SDF_API SdfPath GetParentPath() const
Return the path that identifies this path&#39;s namespace parent.
The outermost container for scene description, which owns and presents composed prims as a scenegraph...
Definition: stage.h:142
PCP_API const SdfPath & GetPath() const
Returns the path of the prim whose opinions are represented by this prim index.
SDF_API SdfPath AppendChild(TfToken const &childName) const
Creates a path by appending an element for childName to this path.
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:89
This class stores a T * and a small integer in the space of a T *.
SdfSpecifier
An enum that identifies the possible specifiers for an SdfPrimSpec.
Definition: types.h:123
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:289
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a &quot;Prim&quot; as ...
Definition: prim.h:131
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:438
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:287
Forward traversal iterator of sibling UsdPrim s.
Definition: prim.h:1445
SDF_API bool IsRootPrimPath() const
Returns whether the path identifies a root prim.
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:409
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.