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