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_PCP_CHANGES_H
25 #define PXR_USD_PCP_CHANGES_H
26 
27 /// \file pcp/changes.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/pcp/api.h"
31 #include "pxr/usd/sdf/changeList.h"
32 #include "pxr/usd/sdf/declareHandles.h"
33 #include "pxr/usd/sdf/path.h"
34 #include "pxr/usd/sdf/types.h"
35 #include "pxr/base/tf/declarePtrs.h"
36 #include "pxr/base/tf/span.h"
37 
38 #include <map>
39 #include <set>
40 
41 PXR_NAMESPACE_OPEN_SCOPE
42 
43 SDF_DECLARE_HANDLES(SdfLayer);
44 TF_DECLARE_WEAK_AND_REF_PTRS(PcpLayerStack);
45 
46 class PcpCache;
47 class PcpSite;
48 
49 /// \class PcpLayerStackChanges
50 ///
51 /// Types of changes per layer stack.
52 ///
53 class PcpLayerStackChanges {
54 public:
55     /// Must rebuild the layer tree.  Implies didChangeLayerOffsets.
56     bool didChangeLayers;
57 
58     /// Must rebuild the layer offsets.
59     bool didChangeLayerOffsets;
60 
61     /// Must rebuild the relocation tables.
62     bool didChangeRelocates;
63 
64     /// A significant layer stack change means the composed opinions of
65     /// the layer stack may have changed in arbitrary ways.  This
66     /// represents a coarse invalidation. By way of contrast, an example
67     /// of an insignificant change is adding or removing a layer empty
68     /// of opinions.
69     bool didChangeSignificantly;
70 
71     /// New relocation maps for this layer stack.
72     /// If didChangeRelocates is true, these fields will be populated
73     /// as part of determining the changes to this layer stack.
74     /// However, we do not immediately apply those changes to the
75     /// layer stack; we store them here and commit them in Apply().
76     SdfRelocatesMap newRelocatesTargetToSource;
77     SdfRelocatesMap newRelocatesSourceToTarget;
78     SdfRelocatesMap newIncrementalRelocatesSourceToTarget;
79     SdfRelocatesMap newIncrementalRelocatesTargetToSource;
80     SdfPathVector newRelocatesPrimPaths;
81 
82     /// Paths that are affected by the above relocation changes.
83     SdfPathSet pathsAffectedByRelocationChanges;
84 
PcpLayerStackChanges()85     PcpLayerStackChanges() :
86         didChangeLayers(false),
87         didChangeLayerOffsets(false),
88         didChangeRelocates(false),
89         didChangeSignificantly(false)
90     {}
91 };
92 
93 /// \class PcpCacheChanges
94 ///
95 /// Types of changes per cache.
96 ///
97 class PcpCacheChanges {
98 public:
99     enum TargetType {
100         TargetTypeConnection         = 1 << 0,
101         TargetTypeRelationshipTarget = 1 << 1
102     };
103 
104     /// Must rebuild the indexes at and below each path.  This
105     /// implies rebuilding the prim/property stacks at
106     /// and below each path.
107     SdfPathSet didChangeSignificantly;
108 
109     /// Must rebuild the prim/property stacks at each path.
110     SdfPathSet didChangeSpecs;
111 
112     /// Must rebuild the prim indexes at each path.  This implies rebuilding
113     /// the prim stack at each path.
114     SdfPathSet didChangePrims;
115 
116     /// Must rebuild the connections/targets at each path.
117     std::map<SdfPath, int, SdfPath::FastLessThan> didChangeTargets;
118 
119     /// Must update the path on every namespace object at and below each
120     /// given path. The first path is the old path to the object and the
121     /// second path is the new path. The order of the vector matters and
122     /// indicates the order in which the namespace edits occur.
123     std::vector<std::pair<SdfPath, SdfPath>> didChangePath;
124 
125     /// Layers used in the composition may have changed.
126     bool didMaybeChangeLayers = false;
127 
128 private:
129     friend class PcpCache;
130     friend class PcpChanges;
131 
132     // Must rebuild the prim/property stacks at each path due to a change
133     // that only affects the internal representation of the stack and
134     // not its contents.  Because this causes no externally-observable
135     // changes in state, clients do not need to be aware of these changes.
136     SdfPathSet _didChangeSpecsInternal;
137 };
138 
139 /// Structure used to temporarily retain layers and layerStacks within
140 /// a code block.  Analogous to the autorelease pool in obj-c.
141 class PcpLifeboat {
142 public:
143     PcpLifeboat();
144     ~PcpLifeboat();
145 
146     /// Ensure that \p layer exists until this object is destroyed.
147     void Retain(const SdfLayerRefPtr& layer);
148 
149     /// Ensure that \p layerStack exists until this object is destroyed.
150     void Retain(const PcpLayerStackRefPtr& layerStack);
151 
152     /// Returns reference to the set of layer stacks currently being held
153     /// in the lifeboat.
154     const std::set<PcpLayerStackRefPtr>& GetLayerStacks() const;
155 
156     /// Swap the contents of this and \p other.
157     void Swap(PcpLifeboat& other);
158 
159 private:
160     std::set<SdfLayerRefPtr> _layers;
161     std::set<PcpLayerStackRefPtr> _layerStacks;
162 };
163 
164 /// \class PcpChanges
165 ///
166 /// Describes Pcp changes.
167 ///
168 /// Collects changes to Pcp necessary to reflect changes in Sd.  It does
169 /// not cause any changes to any Pcp caches, layer stacks, etc;  it only
170 /// computes what changes would be necessary to Pcp to reflect the Sd
171 /// changes.
172 ///
173 class PcpChanges {
174 public:
175     PCP_API PcpChanges();
176     PCP_API ~PcpChanges();
177 
178     /// Breaks down \p changes into individual changes on the caches in
179     /// \p caches.  This simply translates data in \p changes into other
180     /// Did...() calls on this object.
181     ///
182     /// Clients will typically call this method once then call \c Apply() or
183     /// get the changes using \c GetLayerStackChanges() and
184     /// \c GetCacheChanges().
185     PCP_API
186     void DidChange(const TfSpan<const PcpCache*> &caches,
187                    const SdfLayerChangeListVec& changes);
188 
189     /// Tries to load the sublayer of \p layer at \p sublayerPath.  If
190     /// successful, any layer stack using \p layer is marked as having changed
191     /// and all prims in \p cache using any prim in any of those layer stacks
192     /// are marked as changed.
193     PCP_API
194     void DidMaybeFixSublayer(const PcpCache* cache,
195                              const SdfLayerHandle& layer,
196                              const std::string& assetPath);
197 
198     /// Tries to load the asset at \p assetPath.  If successful, any prim
199     /// in \p cache using the site \p site is marked as changed.
200     PCP_API
201     void DidMaybeFixAsset(const PcpCache* cache,
202                           const PcpSite& site,
203                           const SdfLayerHandle& srcLayer,
204                           const std::string& assetPath);
205 
206     /// The layer identified by \p layerId was muted in \p cache.
207     PCP_API
208     void DidMuteLayer(const PcpCache* cache, const std::string& layerId);
209 
210     /// The layer identified by \p layerId was unmuted in \p cache.
211     PCP_API
212     void DidUnmuteLayer(const PcpCache* cache, const std::string& layerId);
213 
214     /// The sublayer tree changed.  This often, but doesn't always, imply that
215     /// anything and everything may have changed.  If clients want to indicate
216     /// that anything and everything may have changed they should call this
217     /// method and \c DidChangePrimGraph() with the absolute root path.
218     PCP_API
219     void DidChangeLayers(const PcpCache* cache);
220 
221     /// The sublayer offsets changed.
222     PCP_API
223     void DidChangeLayerOffsets(const PcpCache* cache);
224 
225     /// The object at \p path changed significantly enough to require
226     /// recomputing the entire prim or property index.  A significant change
227     /// implies changes to every namespace descendant's index, specs, and
228     /// dependencies.
229     PCP_API
230     void DidChangeSignificantly(const PcpCache* cache, const SdfPath& path);
231 
232     /// The spec stack for the prim or property has changed, due to the
233     /// addition or removal of the spec in \p changedLayer at \p changedPath.
234     /// This is used when inert prims/properties are added or removed or when
235     /// any change requires rebuilding the property stack.  It implies that
236     /// dependencies on those specs has changed.
237     PCP_API
238     void DidChangeSpecs(const PcpCache* cache, const SdfPath& path,
239                         const SdfLayerHandle& changedLayer,
240                         const SdfPath& changedPath);
241 
242     /// The spec stack for the prim or property at \p path in \p cache has
243     /// changed.
244     PCP_API
245     void DidChangeSpecStack(const PcpCache* cache, const SdfPath& path);
246 
247     /// The connections on the attribute or targets on the relationship have
248     /// changed.
249     PCP_API
250     void DidChangeTargets(const PcpCache* cache, const SdfPath& path,
251                           PcpCacheChanges::TargetType targetType);
252 
253     /// The relocates that affect prims and properties at and below
254     /// the given cache path have changed.
255     PCP_API
256     void DidChangeRelocates(const PcpCache* cache, const SdfPath& path);
257 
258     /// The composed object at \p oldPath was moved to \p newPath.  This
259     /// implies every corresponding Sd change.  This object will subsume
260     /// those Sd changes under this higher-level move.  Sd path changes
261     /// that are not so subsumed will be converted to DidChangePrimGraph()
262     /// and/or DidChangeSpecs() changes.
263     PCP_API
264     void DidChangePaths(const PcpCache* cache,
265                         const SdfPath& oldPath, const SdfPath& newPath);
266 
267     /// Remove any changes for \p cache.
268     PCP_API
269     void DidDestroyCache(const PcpCache* cache);
270 
271     /// The asset resolver has changed, invalidating previously-resolved
272     /// asset paths. This function will check all prim indexes in \p cache
273     /// for composition arcs that may now refer to a different asset and
274     /// mark them as needing significant resyncs.
275     PCP_API
276     void DidChangeAssetResolver(const PcpCache* cache);
277 
278     /// Swap the contents of this and \p other.
279     PCP_API
280     void Swap(PcpChanges& other);
281 
282     /// Returns \c true iff there are no changes.
283     PCP_API
284     bool IsEmpty() const;
285 
286     typedef std::map<PcpLayerStackPtr, PcpLayerStackChanges> LayerStackChanges;
287     typedef std::map<PcpCache*, PcpCacheChanges> CacheChanges;
288 
289     /// Returns a map of all of the layer stack changes.  Note that some
290     /// keys may be to expired layer stacks.
291     PCP_API
292     const LayerStackChanges& GetLayerStackChanges() const;
293 
294     /// Returns a map of all of the cache changes.
295     PCP_API
296     const CacheChanges& GetCacheChanges() const;
297 
298     /// Returns the lifeboat responsible for maintaining the lifetime of
299     /// layers and layer stacks during change processing. Consumers may
300     /// inspect this object to determine which of these objects, if any,
301     /// had their lifetimes affected during change processing.
302     PCP_API
303     const PcpLifeboat& GetLifeboat() const;
304 
305     /// Applies the changes to the layer stacks and caches.
306     PCP_API
307     void Apply() const;
308 
309 private:
310     // Internal data types for namespace edits from Sd.
311     typedef std::map<SdfPath, SdfPath> _PathEditMap;
312     typedef std::map<PcpCache*, _PathEditMap> _RenameChanges;
313 
314     // Returns the PcpLayerStackChanges for the given cache's layer stack.
315     PcpLayerStackChanges& _GetLayerStackChanges(const PcpCache* cache);
316 
317     // Returns the PcpLayerStackChanges for the given layer stack.
318     PcpLayerStackChanges& _GetLayerStackChanges(const PcpLayerStackPtr&);
319 
320     // Returns the PcpCacheChanges for the given cache.
321     PcpCacheChanges& _GetCacheChanges(const PcpCache* cache);
322 
323     // Returns the _PathEditMap for the given cache.
324     _PathEditMap& _GetRenameChanges(const PcpCache* cache);
325 
326 
327     // Optimize the changes.
328     void _Optimize() const;
329 
330     // Optimize the changes.
331     void _Optimize();
332 
333     // Optimize the changes for a given cache.
334     void _Optimize(PcpCacheChanges*);
335 
336     // Optimize path changes.
337     void _OptimizePathChanges(const PcpCache* cache, PcpCacheChanges* changes,
338                               const _PathEditMap* pathChanges);
339 
340     // Sublayer change type for _DidChangeSublayer.
341     enum _SublayerChangeType {
342         _SublayerAdded,
343         _SublayerRemoved
344     };
345 
346     // Helper function for loading a sublayer of \p layer at \p sublayerPath
347     // for processing changes described by \p sublayerChange.
348     SdfLayerRefPtr _LoadSublayerForChange(const PcpCache* cache,
349                                           const SdfLayerHandle& layer,
350                                           const std::string& sublayerPath,
351                                           _SublayerChangeType changeType) const;
352 
353     // Helper function for loading a sublayer at \p sublayerPath
354     // for processing changes described by \p sublayerChange.
355     SdfLayerRefPtr _LoadSublayerForChange(const PcpCache* cache,
356                                           const std::string& sublayerPath,
357                                           _SublayerChangeType changeType) const;
358 
359     // Propagates changes to \p sublayer specified by \p sublayerChange to
360     // the dependents of that sublayer.  This includes all layer stacks
361     // that include the sublayer.
362     void _DidChangeSublayerAndLayerStacks(const PcpCache* cache,
363                                           const PcpLayerStackPtrVector& stacks,
364                                           const std::string& sublayerPath,
365                                           const SdfLayerHandle& sublayer,
366                                           _SublayerChangeType sublayerChange,
367                                           std::string* debugSummary);
368 
369     // Propagates changes to \p sublayer specified by \p sublayerChange to
370     // the dependents of that sublayer.
371     void _DidChangeSublayer(const PcpCache* cache,
372                             const PcpLayerStackPtrVector& layerStacks,
373                             const std::string& sublayerPath,
374                             const SdfLayerHandle& sublayer,
375                             _SublayerChangeType sublayerChange,
376                             std::string* debugSummary,
377                             bool *significant);
378 
379     // Mark the layer stack as having changed.
380     void _DidChangeLayerStack(
381         const TfSpan<const PcpCache*>& caches,
382         const PcpLayerStackPtr& layerStack,
383         bool requiresLayerStackChange,
384         bool requiresLayerStackOffsetsChange,
385         bool requiresSignificantChange);
386 
387     // Mark the layer stack's relocations as having changed.
388     // Recompute the new relocations, storing the result in the Changes,
389     // so that change-processing can determine which other caches it
390     // needs to invalidate.
391     void _DidChangeLayerStackRelocations(
392         const TfSpan<const PcpCache*>& caches,
393         const PcpLayerStackPtr & layerStack,
394         std::string* debugSummary);
395 
396     // Register changes to any prim indexes in \p caches that are affected
397     // by a change to a layer's resolved path used by \p layerStack.
398     void _DidChangeLayerStackResolvedPath(
399         const TfSpan<const PcpCache*>& caches,
400         const PcpLayerStackPtr& layerStack,
401         bool requiresLayerStackChange,
402         std::string* debugSummary);
403 
404     // The spec stack for the prim or property index at \p path must be
405     // recomputed due to a change that affects only the internal representation
406     // of the stack and not its contents.
407     void _DidChangeSpecStackInternal(
408         const PcpCache* cache, const SdfPath& path);
409 
410 private:
411     LayerStackChanges _layerStackChanges;
412     CacheChanges _cacheChanges;
413     _RenameChanges _renameChanges;
414     mutable PcpLifeboat _lifeboat;
415 };
416 
417 PXR_NAMESPACE_CLOSE_SCOPE
418 
419 #endif // PXR_USD_PCP_CHANGES_H
420