HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
containerDataSourceEditor.h
Go to the documentation of this file.
1 //
2 // Copyright 2021 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_IMAGING_HD_CONTAINER_DATA_SOURCE_EDITOR_H
8 #define PXR_IMAGING_HD_CONTAINER_DATA_SOURCE_EDITOR_H
9 
11 
13 
15 
16 /// Utility for lazily constructing and composing data source hierarchies.
17 ///
18 /// \note
19 /// Scene indices can use this facility to override/overlay data sources at
20 /// various data source locators for a prim.
21 ///
22 /// Example:
23 /// Let's say we have a scene index that updates the color of a prim </Foo>
24 /// based on the frame number.
25 ///
26 /// \code
27 ///
28 /// MyColorfulFilteringSceneIndex::GetPrim(const SdfPath &primPath) {
29 /// HdSceneIndexPrim prim = ...;
30 /// if (primPath == SdfPath("/Foo")) {
31 /// size_t frameNumber = ...; // Query scene index for the frame number
32 /// HdContainerDataSourceEditor editor(prim.dataSource);
33 /// editor.Set(HdDataSourceLocator("primvars", "color", "primvarValue"),
34 /// HdRetainedTypedSampledDataSource<GfVec4f>(
35 /// ComputeColor(frameNumber)));
36 /// prim.dataSource = editor.Finish();
37 /// )
38 /// return prim;
39 /// }
40 /// \endcode
41 ///
42 /// Because Finish() returns a new prim container handle each time, any scene
43 /// index using this facility to set/overlay *retained data sources* needs to
44 /// provide the necessary invalidation so that downstream observers can see the
45 /// new value(s).
46 ///
47 /// So, in the example above, we would need to send a dirty notice invalidating
48 /// the chain of container handles leading to the data source, as well as the
49 /// contents of that data source.
50 ///
51 /// \code
52 /// // Determine if the frameNumber data source was invalidated.
53 /// const bool dirtyFrameNumber = ...;
54 /// if (dirtyFrameNumber) {
55 /// HdDataSourceLocatorSet dirtyLocators;
56 /// dirtyLocators.insert(
57 /// // Prim container handle needs to be refetched.
58 /// HdDataSourceLocator(
59 /// HdDataSourceSentinelTokens->container),
60 /// // primvars container handle needs to be refetched.
61 /// HdDataSourceLocator(
62 /// "primvars", HdDataSourceSentinelTokens->container),
63 /// // primvars/color container handle needs to be refetched.
64 /// HdDataSourceLocator(
65 /// "primvars", "color", HdDataSourceSentinelTokens->container),
66 /// // Data source at primvars/color/primvarValue needs to be refetched.
67 /// HdDataSourceLocator(
68 /// "primvars", "color", "primvarValue")
69 /// );
70 ///
71 /// _SendPrimsDirtied(
72 /// HdSceneIndexObserver::DirtiedPrimEntries{
73 /// { SdfPath("/Foo"), dirtyLocators } });
74 /// }
75 ///
76 /// This may be easily accomplished using the utility function
77 /// ComputeDirtyLocators(locatorSet).
78 ///
79 class HdContainerDataSourceEditor
80 {
81 public:
82 
83  HdContainerDataSourceEditor() {}
84  HdContainerDataSourceEditor(
85  HdContainerDataSourceHandle initialContainer)
86  : _initialContainer(initialContainer) {}
87 
88  // Replaces data source at given locator and descending locations
89  // (if given a container data source) by given data source.
90  HD_API
91  HdContainerDataSourceEditor &Set(
92  const HdDataSourceLocator &locator,
93  const HdDataSourceBaseHandle &dataSource);
94 
95  // Overlays data source at given location by given data source so that
96  // data sources in the initial container at descending locations can
97  // still come through.
98  HD_API
99  HdContainerDataSourceEditor &Overlay(
100  const HdDataSourceLocator &locator,
101  const HdContainerDataSourceHandle &containerDataSource);
102 
103  // Returns final container data source with all edits applied.
104  HD_API
105  HdContainerDataSourceHandle Finish();
106 
107  /// Computes the set of locators that need to be invalidated given
108  /// \param locatorSet which is the set of locators for which data sources
109  /// are being set or overlaid.
110  HD_API
111  static HdDataSourceLocatorSet ComputeDirtyLocators(
112  const HdDataSourceLocatorSet &locatorSet);
113 
114 private:
115  HdContainerDataSourceHandle _FinishWithNoInitialContainer();
116 
117  struct _Node;
118  using _NodeSharedPtr = std::shared_ptr<_Node>;
119 
120  struct _Entry
121  {
122  HdDataSourceBaseHandle dataSource;
123  _NodeSharedPtr childNode;
124  };
125 
126  struct _Node
127  {
128  using EntryMap = TfDenseHashMap<TfToken, _Entry,
129  TfToken::HashFunctor, std::equal_to<TfToken>, 8>;
130  EntryMap entries;
131  };
132 
133  _NodeSharedPtr _root;
134  HdContainerDataSourceHandle _initialContainer;
135 
136  // Calling Set with a container data source should mask any existing
137  // container child values coming from _initialContainer. If that's defined,
138  // record the paths for which containers have been set in order to build
139  // a hierarchy with HdBlockDataSources as leaves to place between.
140  TfSmallVector<HdDataSourceLocator, 4> _directContainerSets;
141 
142  _NodeSharedPtr _GetNode(const HdDataSourceLocator & locator);
143 
144  class _NodeContainerDataSource : public HdContainerDataSource
145  {
146  public:
147  HD_DECLARE_DATASOURCE(_NodeContainerDataSource);
148  _NodeContainerDataSource(_NodeSharedPtr node);
149 
150  TfTokenVector GetNames() override;
151  HdDataSourceBaseHandle Get(const TfToken &name) override;
152 
153  private:
154  _NodeSharedPtr _node;
155  };
156 };
157 
159 
160 #endif
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
#define HD_API
Definition: api.h:23
Functor to use for hash maps from tokens to other things.
Definition: token.h:149
#define HD_DECLARE_DATASOURCE(type)
Definition: dataSource.h:53
Definition: token.h:70
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
GLuint const GLchar * name
Definition: glcorearb.h:786
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74