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 ///
25 /// \file Sdf/layer.cpp
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/sdf/layer.h"
29 #include "pxr/usd/sdf/assetPathResolver.h"
30 #include "pxr/usd/sdf/attributeSpec.h"
31 #include "pxr/usd/sdf/changeBlock.h"
32 #include "pxr/usd/sdf/changeManager.h"
33 #include "pxr/usd/sdf/childrenPolicies.h"
34 #include "pxr/usd/sdf/childrenUtils.h"
35 #include "pxr/usd/sdf/debugCodes.h"
36 #include "pxr/usd/sdf/fileFormat.h"
37 #include "pxr/usd/sdf/layerRegistry.h"
38 #include "pxr/usd/sdf/layerStateDelegate.h"
39 #include "pxr/usd/sdf/layerUtils.h"
40 #include "pxr/usd/sdf/notice.h"
41 #include "pxr/usd/sdf/path.h"
42 #include "pxr/usd/sdf/primSpec.h"
43 #include "pxr/usd/sdf/reference.h"
44 #include "pxr/usd/sdf/relationshipSpec.h"
45 #include "pxr/usd/sdf/schema.h"
46 #include "pxr/usd/sdf/specType.h"
47 #include "pxr/usd/sdf/textFileFormat.h"
48 #include "pxr/usd/sdf/types.h"
49 #include "pxr/usd/sdf/subLayerListEditor.h"
50 #include "pxr/usd/sdf/variantSetSpec.h"
51 #include "pxr/usd/sdf/variantSpec.h"
52 
53 #include "pxr/usd/ar/resolver.h"
54 #include "pxr/usd/ar/resolverContextBinder.h"
55 #include "pxr/base/arch/fileSystem.h"
56 #include "pxr/base/arch/errno.h"
57 #include "pxr/base/trace/trace.h"
58 #include "pxr/base/tf/debug.h"
59 #include "pxr/base/tf/envSetting.h"
60 #include "pxr/base/tf/fileUtils.h"
61 #include "pxr/base/tf/iterator.h"
62 #include "pxr/base/tf/mallocTag.h"
63 #include "pxr/base/tf/ostreamMethods.h"
64 #include "pxr/base/tf/pathUtils.h"
65 #include "pxr/base/tf/pyLock.h"
66 #include "pxr/base/tf/scopeDescription.h"
67 #include "pxr/base/tf/staticData.h"
68 #include "pxr/base/tf/stackTrace.h"
69 
70 #include <tbb/queuing_rw_mutex.h>
71 
72 #include <atomic>
73 #include <functional>
74 #include <fstream>
75 #include <iostream>
76 #include <set>
77 #include <thread>
78 #include <vector>
79 
80 using std::map;
81 using std::set;
82 using std::string;
83 using std::vector;
84 
85 namespace ph = std::placeholders;
86 
87 PXR_NAMESPACE_OPEN_SCOPE
88 
TF_REGISTRY_FUNCTION(TfType)89 TF_REGISTRY_FUNCTION(TfType)
90 {
91     TfType::Define<SdfLayer>();
92 }
93 
94 // Muted Layers stores the paths of layers that should be muted.  The stored
95 // paths should be asset paths, when applicable, or identifiers if no asset
96 // path exists for the desired layers.
97 typedef set<string> _MutedLayers;
98 typedef std::map<std::string, SdfAbstractDataRefPtr> _MutedLayerDataMap;
99 static TfStaticData<_MutedLayers> _mutedLayers;
100 static TfStaticData<_MutedLayerDataMap> _mutedLayerData;
101 // Global mutex protecting _mutedLayers and _mutedLayerData
102 static TfStaticData<std::mutex> _mutedLayersMutex;
103 // This is a global revision number that tracks changes to _mutedLayers.  Since
104 // we seldom mute and unmute layers, this lets layers cache their muteness and
105 // do quick validity checks without taking a lock and looking themselves up in
106 // _mutedLayers.
107 static std::atomic_size_t _mutedLayersRevision { 1 };
108 
109 
110 // A registry for loaded layers.
111 static TfStaticData<Sdf_LayerRegistry> _layerRegistry;
112 
113 // Global mutex protecting _layerRegistry.
114 static tbb::queuing_rw_mutex &
_GetLayerRegistryMutex()115 _GetLayerRegistryMutex() {
116     static tbb::queuing_rw_mutex mutex;
117     return mutex;
118 }
119 
120 TF_DEFINE_ENV_SETTING(
121     SDF_LAYER_VALIDATE_AUTHORING, false,
122     "If enabled, layers will validate new fields and specs being authored "
123     "against their schema. If the field or spec is not defined in the schema "
124     "a coding error will be issued and the authoring operation will fail.");
125 
SdfLayer(const SdfFileFormatConstPtr & fileFormat,const string & identifier,const string & realPath,const ArAssetInfo & assetInfo,const FileFormatArguments & args,bool validateAuthoring)126 SdfLayer::SdfLayer(
127     const SdfFileFormatConstPtr &fileFormat,
128     const string &identifier,
129     const string &realPath,
130     const ArAssetInfo& assetInfo,
131     const FileFormatArguments &args,
132     bool validateAuthoring)
133     : _self(this)
134     , _fileFormat(fileFormat)
135     , _fileFormatArgs(args)
136     , _idRegistry(SdfLayerHandle(this))
137     , _data(fileFormat->InitData(args))
138     , _stateDelegate(SdfSimpleLayerStateDelegate::New())
139     , _lastDirtyState(false)
140     , _assetInfo(new Sdf_AssetInfo)
141     , _mutedLayersRevisionCache(0)
142     , _isMutedCache(false)
143     , _permissionToEdit(true)
144     , _permissionToSave(true)
145     , _validateAuthoring(
146         validateAuthoring || TfGetEnvSetting<bool>(SDF_LAYER_VALIDATE_AUTHORING))
147     , _hints{/*.mightHaveRelocates =*/ false}
148 {
149     TF_DEBUG(SDF_LAYER).Msg("SdfLayer::SdfLayer('%s', '%s')\n",
150         identifier.c_str(), realPath.c_str());
151 
152     // If the identifier has the anonymous layer identifier prefix, it is a
153     // template into which the layer address must be inserted. This ensures
154     // that anonymous layers have unique identifiers, and can be referenced by
155     // Sd object reprs.
156     string layerIdentifier = Sdf_IsAnonLayerIdentifier(identifier) ?
157         Sdf_ComputeAnonLayerIdentifier(identifier, this) : identifier;
158 
159     // Indicate that this layer's initialization is not yet complete before we
160     // publish this object (i.e. add it to the registry in
161     // _InitializeFromIdentifier).  This ensures that other threads looking for
162     // this layer will block until it is fully initialized.
163     _initializationComplete = false;
164 
165     // Initialize layer asset information.
166     _InitializeFromIdentifier(
167         layerIdentifier, realPath, std::string(), assetInfo);
168 
169     // A new layer is not dirty.
170     _MarkCurrentStateAsClean();
171 }
172 
~SdfLayer()173 SdfLayer::~SdfLayer()
174 {
175     TF_DEBUG(SDF_LAYER).Msg(
176         "SdfLayer::~SdfLayer('%s')\n", GetIdentifier().c_str());
177 
178     if (IsMuted()) {
179         std::string mutedPath = _GetMutedPath();
180         SdfAbstractDataRefPtr mutedData;
181         {
182             std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
183             // Drop any in-memory edits we may have been holding for this layer.
184             // To minimize time holding the lock, swap the data out and
185             // erase the entry, then release the lock before proceeding
186             // to drop the refcount.
187             _MutedLayerDataMap::iterator i = _mutedLayerData->find(mutedPath);
188             if (i != _mutedLayerData->end()) {
189                 std::swap(mutedData, i->second);
190                 _mutedLayerData->erase(i);
191             }
192         }
193     }
194 
195     tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
196 
197     // Note that FindOrOpen may have already removed this layer from
198     // the registry, so we count on this API not emitting errors in that
199     // case.
200     _layerRegistry->Erase(_self);
201 }
202 
203 const SdfFileFormatConstPtr&
GetFileFormat() const204 SdfLayer::GetFileFormat() const
205 {
206     return _fileFormat;
207 }
208 
209 const SdfLayer::FileFormatArguments&
GetFileFormatArguments() const210 SdfLayer::GetFileFormatArguments() const
211 {
212     return _fileFormatArgs;
213 }
214 
215 SdfLayerRefPtr
_CreateNewWithFormat(const SdfFileFormatConstPtr & fileFormat,const string & identifier,const string & realPath,const ArAssetInfo & assetInfo,const FileFormatArguments & args)216 SdfLayer::_CreateNewWithFormat(
217     const SdfFileFormatConstPtr &fileFormat,
218     const string& identifier,
219     const string& realPath,
220     const ArAssetInfo& assetInfo,
221     const FileFormatArguments& args)
222 {
223     // This method should be called with the layerRegistryMutex already held.
224 
225     // Create and return a new layer with _initializationComplete set false.
226     return fileFormat->NewLayer(
227         fileFormat, identifier, realPath, assetInfo, args);
228 }
229 
230 void
_FinishInitialization(bool success)231 SdfLayer::_FinishInitialization(bool success)
232 {
233     _initializationWasSuccessful = success;
234     _initializationComplete = true; // unblock waiters.
235 }
236 
237 bool
_WaitForInitializationAndCheckIfSuccessful()238 SdfLayer::_WaitForInitializationAndCheckIfSuccessful()
239 {
240     // Note: the caller is responsible for holding a reference to this
241     // layer, to keep it from being destroyed out from under us while
242     // blocked on the mutex.
243 
244     // Drop the GIL in case we might have it -- if the layer load happening in
245     // another thread needs the GIL, we'd deadlock here.
246     TF_PY_ALLOW_THREADS_IN_SCOPE();
247 
248     // Wait until _initializationComplete is set to true.  If the layer is still
249     // being initialized, this will be false, blocking progress until
250     // initialization completes.
251     while (!_initializationComplete) {
252         std::this_thread::yield();
253     }
254 
255     // For various reasons, initialization may have failed.
256     // For example, the menva parser may have hit a syntax error,
257     // or transferring content from a source layer may have failed.
258     // In this case _initializationWasSuccessful will be set to false.
259     // The callers of this method are responsible for checking the result
260     // and dropping any references they hold.  As a convenience to them,
261     // we return the value here.
262     return _initializationWasSuccessful.get();
263 }
264 
265 // For the given layer, gets a dictionary of resolved external asset dependency
266 // paths to the timestamp for each asset.
267 static VtDictionary
_GetExternalAssetModificationTimes(const SdfLayer & layer)268 _GetExternalAssetModificationTimes(const SdfLayer& layer)
269 {
270     VtDictionary result;
271     std::set<std::string> externalAssetDependencies =
272         layer.GetExternalAssetDependencies();
273     for (const std::string& resolvedPath : externalAssetDependencies) {
274         // Get the modification timestamp for the path. Note that external
275         // asset dependencies only returns resolved paths so pass the same
276         // path for both params.
277         result[resolvedPath] = ArGetResolver().GetModificationTimestamp(
278             resolvedPath, ArResolvedPath(resolvedPath));
279     }
280     return result;
281 }
282 
283 #if AR_VERSION == 1
284 static bool
_ModificationTimesEqual(const VtValue & t1,const VtValue & t2)285 _ModificationTimesEqual(const VtValue& t1, const VtValue& t2)
286 {
287     return t1 == t2;
288 }
289 
290 static bool
_ModificationTimesEqual(const VtDictionary & t1,const VtDictionary & t2)291 _ModificationTimesEqual(const VtDictionary& t1, const VtDictionary& t2)
292 {
293     return t1 == t2;
294 }
295 #else
296 static bool
_ModificationTimesEqual(const VtValue & v1,const VtValue & v2)297 _ModificationTimesEqual(const VtValue& v1, const VtValue& v2)
298 {
299     if (!v1.IsHolding<ArTimestamp>() || !v2.IsHolding<ArTimestamp>()) {
300         return false;
301     }
302 
303     const ArTimestamp& t1 = v1.UncheckedGet<ArTimestamp>();
304     const ArTimestamp& t2 = v2.UncheckedGet<ArTimestamp>();
305     return t1.IsValid() && t2.IsValid() && t1 == t2;
306 }
307 
308 static bool
_ModificationTimesEqual(const VtDictionary & t1,const VtDictionary & t2)309 _ModificationTimesEqual(const VtDictionary& t1, const VtDictionary& t2)
310 {
311     if (t1.size() != t2.size()) {
312         return false;
313     }
314 
315     for (const auto& e1 : t1) {
316         const auto t2Iter = t2.find(e1.first);
317         if (t2Iter == t2.end() ||
318             !_ModificationTimesEqual(e1.second, t2Iter->second)) {
319             return false;
320         }
321     }
322 
323     return true;
324 }
325 #endif
326 
327 SdfLayerRefPtr
CreateAnonymous(const string & tag,const FileFormatArguments & args)328 SdfLayer::CreateAnonymous(
329     const string& tag, const FileFormatArguments& args)
330 {
331     SdfFileFormatConstPtr fileFormat;
332     string suffix = TfStringGetSuffix(tag);
333     if (!suffix.empty()) {
334         fileFormat = SdfFileFormat::FindByExtension(suffix, args);
335     }
336 
337     if (!fileFormat) {
338         fileFormat = SdfFileFormat::FindById(SdfTextFileFormatTokens->Id);
339     }
340 
341     if (!fileFormat) {
342         TF_CODING_ERROR("Cannot determine file format for anonymous SdfLayer");
343         return SdfLayerRefPtr();
344     }
345 
346     return _CreateAnonymousWithFormat(fileFormat, tag, args);
347 }
348 
349 SdfLayerRefPtr
CreateAnonymous(const string & tag,const SdfFileFormatConstPtr & format,const FileFormatArguments & args)350 SdfLayer::CreateAnonymous(
351     const string &tag, const SdfFileFormatConstPtr &format,
352     const FileFormatArguments &args)
353 {
354     if (!format) {
355         TF_CODING_ERROR("Invalid file format for anonymous SdfLayer");
356         return SdfLayerRefPtr();
357     }
358 
359     return _CreateAnonymousWithFormat(format, tag, args);
360 }
361 
362 SdfLayerRefPtr
_CreateAnonymousWithFormat(const SdfFileFormatConstPtr & fileFormat,const std::string & tag,const FileFormatArguments & args)363 SdfLayer::_CreateAnonymousWithFormat(
364     const SdfFileFormatConstPtr &fileFormat, const std::string& tag,
365     const FileFormatArguments &args)
366 {
367     if (fileFormat->IsPackage()) {
368         TF_CODING_ERROR("Cannot create anonymous layer: creating package %s "
369                         "layer is not allowed through this API.",
370                         fileFormat->GetFormatId().GetText());
371         return SdfLayerRefPtr();
372     }
373 
374     tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
375 
376     SdfLayerRefPtr layer =
377         _CreateNewWithFormat(
378             fileFormat, Sdf_GetAnonLayerIdentifierTemplate(tag),
379             string(), ArAssetInfo(), args);
380 
381     // No layer initialization required, so initialization is complete.
382     layer->_FinishInitialization(/* success = */ true);
383 
384     return layer;
385 }
386 
387 bool
IsAnonymous() const388 SdfLayer::IsAnonymous() const
389 {
390     return Sdf_IsAnonLayerIdentifier(GetIdentifier());
391 }
392 
393 bool
IsAnonymousLayerIdentifier(const string & identifier)394 SdfLayer::IsAnonymousLayerIdentifier(const string& identifier)
395 {
396     return Sdf_IsAnonLayerIdentifier(identifier);
397 }
398 
399 string
GetDisplayNameFromIdentifier(const string & identifier)400 SdfLayer::GetDisplayNameFromIdentifier(const string& identifier)
401 {
402     return Sdf_GetLayerDisplayName(identifier);
403 }
404 
405 SdfLayerRefPtr
CreateNew(const string & identifier,const FileFormatArguments & args)406 SdfLayer::CreateNew(
407     const string& identifier,
408     const FileFormatArguments &args)
409 {
410     TF_DEBUG(SDF_LAYER).Msg(
411         "SdfLayer::CreateNew('%s', '%s')\n",
412         identifier.c_str(), TfStringify(args).c_str());
413 
414     return _CreateNew(TfNullPtr, identifier, args);
415 }
416 
417 SdfLayerRefPtr
CreateNew(const SdfFileFormatConstPtr & fileFormat,const string & identifier,const FileFormatArguments & args)418 SdfLayer::CreateNew(
419     const SdfFileFormatConstPtr& fileFormat,
420     const string& identifier,
421     const FileFormatArguments &args)
422 {
423     TF_DEBUG(SDF_LAYER).Msg(
424         "SdfLayer::CreateNew('%s', '%s', '%s')\n",
425         fileFormat->GetFormatId().GetText(),
426         identifier.c_str(), TfStringify(args).c_str());
427 
428     return _CreateNew(fileFormat, identifier, args);
429 }
430 
431 SdfLayerRefPtr
_CreateNew(SdfFileFormatConstPtr fileFormat,const string & identifier,const FileFormatArguments & args)432 SdfLayer::_CreateNew(
433     SdfFileFormatConstPtr fileFormat,
434     const string& identifier,
435     const FileFormatArguments &args)
436 {
437     string whyNot;
438     if (!Sdf_CanCreateNewLayerWithIdentifier(identifier, &whyNot)) {
439         TF_CODING_ERROR("Cannot create new layer '%s': %s",
440             identifier.c_str(),
441             whyNot.c_str());
442         return TfNullPtr;
443     }
444 
445     ArResolver& resolver = ArGetResolver();
446 
447     ArAssetInfo assetInfo;
448 
449 #if AR_VERSION == 1
450     // When creating a new layer, assume that relative identifiers are
451     // relative to the current working directory.
452     const bool isRelativePath = resolver.IsRelativePath(identifier);
453     const string absIdentifier =
454         isRelativePath ? TfAbsPath(identifier) : identifier;
455 
456     // Direct newly created layers to a local path.
457     const string localPath = resolver.ComputeLocalPath(absIdentifier);
458 #else
459     string absIdentifier, localPath;
460     {
461         TfErrorMark m;
462         absIdentifier = resolver.CreateIdentifierForNewAsset(identifier);
463 
464         // Resolve the identifier to the path where new assets should go.
465         localPath = resolver.ResolveForNewAsset(absIdentifier);
466 
467         if (!m.IsClean()) {
468             std::vector<std::string> errors;
469             for (const TfError& error : m) {
470                 errors.push_back(error.GetCommentary());
471             }
472             whyNot = TfStringJoin(errors, ", ");
473             m.Clear();
474         }
475     }
476 #endif
477 
478     if (localPath.empty()) {
479         TF_CODING_ERROR(
480             "Cannot create new layer '%s': %s",
481             absIdentifier.c_str(),
482             (whyNot.empty() ? "failed to compute path for new layer"
483                 : whyNot.c_str()));
484         return TfNullPtr;
485     }
486 
487     // If not explicitly supplied one, try to determine the fileFormat
488     // based on the local path suffix,
489     if (!fileFormat) {
490         fileFormat = SdfFileFormat::FindByExtension(localPath, args);
491         // XXX: This should be a coding error, not a failed verify.
492         if (!TF_VERIFY(fileFormat))
493             return TfNullPtr;
494     }
495 
496     // Restrict creating package layers via the Sdf API. These layers
497     // are expected to be created via other libraries or external programs.
498     if (Sdf_IsPackageOrPackagedLayer(fileFormat, identifier)) {
499         TF_CODING_ERROR("Cannot create new layer '%s': creating %s %s "
500                         "layer is not allowed through this API.",
501                         identifier.c_str(),
502                         fileFormat->IsPackage() ? "package" : "packaged",
503                         fileFormat->GetFormatId().GetText());
504         return TfNullPtr;
505     }
506 
507     // In case of failure below, we want to release the layer
508     // registry mutex lock before destroying the layer.
509     SdfLayerRefPtr layer;
510     {
511         tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
512 
513         // Check for existing layer with this identifier.
514         if (_layerRegistry->Find(absIdentifier)) {
515             TF_CODING_ERROR("A layer already exists with identifier '%s'",
516                 absIdentifier.c_str());
517             return TfNullPtr;
518         }
519 
520         layer = _CreateNewWithFormat(
521             fileFormat, absIdentifier, localPath, ArAssetInfo(), args);
522 
523         if (!TF_VERIFY(layer)) {
524             return TfNullPtr;
525         }
526 
527         // Stash away the existing layer hints.  The call to _Save below will
528         // invalidate them but they should still be good.
529         SdfLayerHints hints = layer->_hints;
530 
531         // XXX 2011-08-19 Newly created layers should not be
532         // saved to disk automatically.
533         //
534         // Force the save here to ensure this new layer overwrites any
535         // existing layer on disk.
536         if (!layer->_Save(/* force = */ true)) {
537             // Dropping the layer reference will destroy it, and
538             // the destructor will remove it from the registry.
539             return TfNullPtr;
540         }
541 
542         layer->_hints = hints;
543         // Once we have saved the layer, initialization is complete.
544         layer->_FinishInitialization(/* success = */ true);
545     }
546     // Return loaded layer or special-cased in-memory layer.
547     return layer;
548 }
549 
550 SdfLayerRefPtr
New(const SdfFileFormatConstPtr & fileFormat,const string & identifier,const FileFormatArguments & args)551 SdfLayer::New(
552     const SdfFileFormatConstPtr& fileFormat,
553     const string& identifier,
554     const FileFormatArguments& args)
555 {
556     if (!fileFormat) {
557         TF_CODING_ERROR("Invalid file format");
558         return TfNullPtr;
559     }
560 
561     if (identifier.empty()) {
562         TF_CODING_ERROR("Cannot construct a layer with an empty identifier.");
563         return TfNullPtr;
564     }
565 
566     if (Sdf_IsPackageOrPackagedLayer(fileFormat, identifier)) {
567         TF_CODING_ERROR("Cannot construct new %s %s layer",
568                         fileFormat->IsPackage() ? "package" : "packaged",
569                         fileFormat->GetFormatId().GetText());
570         return TfNullPtr;
571     }
572 
573     tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
574 
575 #if AR_VERSION == 1
576     // When creating a new layer, assume that relative identifiers are
577     // relative to the current working directory.
578     const string absIdentifier = ArGetResolver().IsRelativePath(identifier) ?
579         TfAbsPath(identifier) : identifier;
580 #else
581     const string absIdentifier =
582         ArGetResolver().CreateIdentifierForNewAsset(identifier);
583 #endif
584 
585     SdfLayerRefPtr layer = _CreateNewWithFormat(
586         fileFormat, absIdentifier, std::string(), ArAssetInfo(), args);
587 
588     // No further initialization required.
589     layer->_FinishInitialization(/* success = */ true);
590 
591     return layer;
592 }
593 
594 static SdfLayer::FileFormatArguments&
_CanonicalizeFileFormatArguments(const std::string & filePath,const SdfFileFormatConstPtr & fileFormat,SdfLayer::FileFormatArguments & args)595 _CanonicalizeFileFormatArguments(const std::string& filePath,
596                                  const SdfFileFormatConstPtr& fileFormat,
597                                  SdfLayer::FileFormatArguments& args)
598 {
599     // Nothing to do if there isn't an associated file format.
600     // This is expected by _ComputeInfoToFindOrOpenLayer and isn't an error.
601     if (!fileFormat) {
602         // XXX:
603         // Sdf is unable to determine a file format for layers that are created
604         // without a file extension (which includes anonymous layers). The keys
605         // for these layers in the registry will never include a 'target'
606         // argument -- the API doesn't give you a way to do that.
607         //
608         // So, if a 'target' is specified here, we want to strip it out
609         // so Find and FindOrOpen will search the registry and find these
610         // layers. If we didn't, we would search the registry for an
611         // identifier with the 'target' arg embedded, and we'd never find
612         // it.
613         //
614         // This is a hack. I think the right thing is to either:
615         //   a) Ensure that a layer's identifier always encodes its file format
616         //   b) Do this target argument stripping in Find / FindOrOpen, find
617         //      the layer, then verify that the layer's target is the one that
618         //      was specified.
619         //
620         // These are larger changes that require updating some clients, so
621         // I don't want to do this yet.
622         if (Sdf_GetExtension(filePath).empty()) {
623             args.erase(SdfFileFormatTokens->TargetArg);
624         }
625         return args;
626     }
627 
628     SdfLayer::FileFormatArguments::iterator targetIt =
629         args.find(SdfFileFormatTokens->TargetArg);
630     if (targetIt != args.end()) {
631         if (fileFormat->IsPrimaryFormatForExtensions()) {
632             // If the file format plugin being used to open the indicated layer
633             // is the primary plugin for layers of that type, it means the
634             // 'target' argument (if any) had no effect and can be stripped
635             // from the arguments.
636             args.erase(targetIt);
637         }
638         else {
639             // The target argument may have been a comma-delimited list of
640             // targets to use. The canonical arguments should contain just
641             // the target for the file format for this layer so that subsequent
642             // lookups using the same target return the same layer. For example,
643             // a layer opened with target="x" and target="x,y" should return
644             // the same layer.
645             targetIt->second = fileFormat->GetTarget().GetString();
646         }
647     }
648 
649     // If there aren't any more args to canonicalize, we can exit early.
650     if (args.empty()) {
651         return args;
652     }
653 
654     // Strip out any arguments that match the file format's published
655     // default arguments. A layer opened without any arguments should
656     // be considered equivalent to a layer opened with only default
657     // arguments specified.
658     const SdfLayer::FileFormatArguments defaultArgs =
659         fileFormat->GetDefaultFileFormatArguments();
660     TF_FOR_ALL(it, defaultArgs) {
661         SdfLayer::FileFormatArguments::iterator argIt = args.find(it->first);
662         if (argIt != args.end() && argIt->second == it->second) {
663             args.erase(argIt);
664         }
665     }
666 
667     return args;
668 }
669 
670 struct SdfLayer::_FindOrOpenLayerInfo
671 {
672     // File format plugin for the layer. This may be NULL if
673     // the file format could not be identified.
674     SdfFileFormatConstPtr fileFormat;
675 
676     // Canonical file format arguments.
677     SdfLayer::FileFormatArguments fileFormatArgs;
678 
679     // Whether this layer is anonymous.
680     bool isAnonymous = false;
681 
682     // Path to the layer.
683     string layerPath;
684 
685     // Resolved path for the layer. If the layer is an anonymous layer,
686     // this will be the same as layerPath.
687     string resolvedLayerPath;
688 
689     // Identifier for the layer, combining both the layer path and
690     // file format arguments.
691     string identifier;
692 
693     // Asset info from resolving the layer path.
694     ArAssetInfo assetInfo;
695 };
696 
697 bool
_ComputeInfoToFindOrOpenLayer(const string & identifier,const SdfLayer::FileFormatArguments & args,_FindOrOpenLayerInfo * info,bool computeAssetInfo)698 SdfLayer::_ComputeInfoToFindOrOpenLayer(
699     const string& identifier,
700     const SdfLayer::FileFormatArguments& args,
701     _FindOrOpenLayerInfo* info,
702     bool computeAssetInfo)
703 {
704     TRACE_FUNCTION();
705 
706     if (identifier.empty()) {
707         return false;
708     }
709 
710     string layerPath;
711     SdfLayer::FileFormatArguments layerArgs;
712     if (!Sdf_SplitIdentifier(identifier, &layerPath, &layerArgs) ||
713         layerPath.empty()) {
714         return false;
715     }
716 
717     const bool isAnonymous = IsAnonymousLayerIdentifier(layerPath);
718 
719 #if AR_VERSION > 1
720     if (!isAnonymous) {
721         layerPath = ArGetResolver().CreateIdentifier(layerPath);
722     }
723 #endif
724 
725     // If we're trying to open an anonymous layer, do not try to compute the
726     // real path for it.
727     ArAssetInfo assetInfo;
728     string resolvedLayerPath = isAnonymous ? layerPath :
729         Sdf_ResolvePath(layerPath, computeAssetInfo ? &assetInfo : nullptr);
730 
731     // Merge explicitly-specified arguments over any arguments
732     // embedded in the given identifier.
733     if (layerArgs.empty()) {
734         layerArgs = args;
735     }
736     else {
737         TF_FOR_ALL(it, args) {
738             layerArgs[it->first] = it->second;
739         }
740     }
741 
742     info->fileFormat = SdfFileFormat::FindByExtension(
743         resolvedLayerPath.empty() ? layerPath : resolvedLayerPath, layerArgs);
744     info->fileFormatArgs.swap(_CanonicalizeFileFormatArguments(
745         layerPath, info->fileFormat, layerArgs));
746 
747     info->isAnonymous = isAnonymous;
748     info->layerPath.swap(layerPath);
749     info->resolvedLayerPath.swap(resolvedLayerPath);
750     info->identifier = Sdf_CreateIdentifier(
751         info->layerPath, info->fileFormatArgs);
752     swap(info->assetInfo, assetInfo);
753     return true;
754 }
755 
756 template <class ScopedLock>
757 SdfLayerRefPtr
_TryToFindLayer(const string & identifier,const string & resolvedPath,ScopedLock & lock,bool retryAsWriter)758 SdfLayer::_TryToFindLayer(const string &identifier,
759                           const string &resolvedPath,
760                           ScopedLock &lock,
761                           bool retryAsWriter)
762 {
763     SdfLayerRefPtr result;
764     bool hasWriteLock = false;
765 
766   retry:
767     if (SdfLayerHandle layer = _layerRegistry->Find(identifier, resolvedPath)) {
768         // We found a layer in the registry -- try to acquire a TfRefPtr to this
769         // layer.  Since we have the lock, we guarantee that the layer's
770         // TfRefBase will not be destroyed until we unlock.
771         result = TfCreateRefPtrFromProtectedWeakPtr(layer);
772         if (result) {
773             // We got an ownership stake in the layer, release the lock and
774             // return it.
775             lock.release();
776             return result;
777         }
778 
779         // We found a layer but we could not get an ownership stake in it -- it
780         // is expiring.  Upgrade the lock to a write lock since we will have to
781         // try to remove this expiring layer from the registry.  If our upgrade
782         // is non-atomic, we must retry the steps above, since everything
783         // might've changed in the meantime.
784         if (!hasWriteLock && !lock.upgrade_to_writer()) {
785             // We have the write lock, but we released it in the interim, so
786             // repeat our steps above now that we have the write lock.
787             hasWriteLock = true;
788             goto retry;
789         }
790 
791         if (layer) {
792             // Layer is expiring and we have the write lock: erase it from the
793             // registry.
794             _layerRegistry->Erase(layer);
795         }
796     } else if (!hasWriteLock && retryAsWriter && !lock.upgrade_to_writer()) {
797         // Retry the find since we released the lock in upgrade_to_writer().
798         hasWriteLock = true;
799         goto retry;
800     }
801 
802     if (!retryAsWriter)
803         lock.release();
804 
805     return result;
806 }
807 
808 /* static */
809 SdfLayerRefPtr
FindOrOpen(const string & identifier,const FileFormatArguments & args)810 SdfLayer::FindOrOpen(const string &identifier,
811                      const FileFormatArguments &args)
812 {
813     TRACE_FUNCTION();
814     TF_DEBUG(SDF_LAYER).Msg(
815         "SdfLayer::FindOrOpen('%s', '%s')\n",
816         identifier.c_str(), TfStringify(args).c_str());
817 
818     // Drop the GIL, since if we hold it and another thread that has the
819     // _layerRegistryMutex needs it (if its opening code invokes python, for
820     // instance), we'll deadlock.
821     TF_PY_ALLOW_THREADS_IN_SCOPE();
822 
823     _FindOrOpenLayerInfo layerInfo;
824     if (!_ComputeInfoToFindOrOpenLayer(identifier, args, &layerInfo,
825                                        /* computeAssetInfo = */ true)) {
826         return TfNullPtr;
827     }
828 
829     // First see if this layer is already present.
830     tbb::queuing_rw_mutex::scoped_lock
831         lock(_GetLayerRegistryMutex(), /*write=*/false);
832     if (SdfLayerRefPtr layer =
833         _TryToFindLayer(layerInfo.identifier, layerInfo.resolvedLayerPath,
834                         lock, /*retryAsWriter=*/true)) {
835         // This could be written as a ternary, but we rely on return values
836         // being implicitly moved to avoid making an unnecessary copy of
837         // layer and the associated ref-count bump.
838         if (layer->_WaitForInitializationAndCheckIfSuccessful()) {
839             return layer;
840         }
841         return TfNullPtr;
842     }
843     // At this point _TryToFindLayer has upgraded lock to a writer.
844 
845     // Some layers, such as anonymous layers, have identifiers but don't have
846     // resolved paths.  They aren't backed by assets on disk.  If we don't find
847     // such a layer by identifier in the registry and the format doesn't specify
848     // that anonymous layers should still be read, we're done since we don't
849     // have an asset to open.
850     if (layerInfo.isAnonymous) {
851         if (!layerInfo.fileFormat ||
852             !layerInfo.fileFormat->ShouldReadAnonymousLayers()) {
853             return TfNullPtr;
854         }
855     }
856 
857     if (layerInfo.resolvedLayerPath.empty()) {
858         return TfNullPtr;
859     }
860 
861     // Otherwise we create the layer and insert it into the registry.
862     return _OpenLayerAndUnlockRegistry(lock, layerInfo,
863                                        /* metadataOnly */ false);
864 }
865 
866 /* static */
867 SdfLayerRefPtr
FindOrOpenRelativeToLayer(const SdfLayerHandle & anchor,const string & identifier,const FileFormatArguments & args)868 SdfLayer::FindOrOpenRelativeToLayer(
869     const SdfLayerHandle &anchor,
870     const string &identifier,
871     const FileFormatArguments &args)
872 {
873     TRACE_FUNCTION();
874 
875     if (!anchor) {
876         TF_CODING_ERROR("Anchor layer is invalid");
877         return TfNullPtr;
878     }
879 
880     // For consistency with FindOrOpen, we silently bail out if identifier
881     // is empty here to avoid the coding error that is emitted in that case
882     // in SdfComputeAssetPathRelativeToLayer.
883     if (identifier.empty()) {
884         return TfNullPtr;
885     }
886 
887     return FindOrOpen(
888         SdfComputeAssetPathRelativeToLayer(anchor, identifier), args);
889 }
890 
891 /* static */
892 SdfLayerRefPtr
OpenAsAnonymous(const std::string & layerPath,bool metadataOnly,const std::string & tag)893 SdfLayer::OpenAsAnonymous(
894     const std::string &layerPath,
895     bool metadataOnly,
896     const std::string &tag)
897 {
898     _FindOrOpenLayerInfo layerInfo;
899     if (!_ComputeInfoToFindOrOpenLayer(layerPath, FileFormatArguments(),
900                                        &layerInfo)) {
901         return TfNullPtr;
902     }
903 
904     // XXX: Is this really a coding error? SdfLayer avoids issuing errors if
905     //      given a non-existent file, for instance. Should we be following the
906     //      same policy here?
907     if (!layerInfo.fileFormat) {
908         TF_CODING_ERROR("Cannot determine file format for @%s@",
909                         layerInfo.identifier.c_str());
910         return TfNullPtr;
911     }
912 
913     // Create a new anonymous layer.
914     SdfLayerRefPtr layer;
915     {
916         tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
917         layer = _CreateNewWithFormat(
918                 layerInfo.fileFormat, Sdf_GetAnonLayerIdentifierTemplate(tag),
919                 string());
920         // From this point, we must call _FinishInitialization() on
921         // either success or failure in order to unblock other
922         // threads waiting for initialization to finish.
923     }
924 
925     // Run the file parser to read in the file contents.
926     if (!layer->_Read(layerInfo.identifier, layerInfo.resolvedLayerPath,
927                       metadataOnly)) {
928         layer->_FinishInitialization(/* success = */ false);
929         return TfNullPtr;
930     }
931 
932     layer->_MarkCurrentStateAsClean();
933     layer->_FinishInitialization(/* success = */ true);
934     return layer;
935 }
936 
937 const SdfSchemaBase&
GetSchema() const938 SdfLayer::GetSchema() const
939 {
940     return GetFileFormat()->GetSchema();
941 }
942 
943 SdfLayer::_ReloadResult
_Reload(bool force)944 SdfLayer::_Reload(bool force)
945 {
946     TRACE_FUNCTION();
947 
948     string identifier = GetIdentifier();
949     if (identifier.empty()) {
950         TF_CODING_ERROR("Can't reload a layer with no identifier");
951         return _ReloadFailed;
952     }
953 
954     const bool isAnonymous = IsAnonymous();
955 
956     SdfChangeBlock block;
957     if (isAnonymous && GetFileFormat()->ShouldSkipAnonymousReload()) {
958         // Different file formats have different policies for reloading
959         // anonymous layers.  Some want to treat it as a noop, others want to
960         // treat it as 'Clear'.
961         //
962         // XXX: in the future, I think we want FileFormat plugins to
963         // have a Reload function.  The plugin can manage when it needs to
964         // reload data appropriately.
965         return _ReloadSkipped;
966     }
967     else if (IsMuted() ||
968              (isAnonymous && !GetFileFormat()->ShouldReadAnonymousLayers())) {
969         // Reloading a muted layer leaves it with the initialized contents.
970         SdfAbstractDataRefPtr initialData =
971             GetFileFormat()->InitData(GetFileFormatArguments());
972         if (_data->Equals(initialData)) {
973             return _ReloadSkipped;
974         }
975         _SetData(initialData);
976     }
977     else if (isAnonymous) {
978         // Ask the current external asset dependency state.
979         VtDictionary externalAssetTimestamps =
980             _GetExternalAssetModificationTimes(*this);
981 
982         // See if we can skip reloading.
983         if (!force && !IsDirty()
984             && (externalAssetTimestamps == _externalAssetModificationTimes)) {
985             return _ReloadSkipped;
986         }
987 
988         std::string resolvedPath;
989         std::string args;
990         Sdf_SplitIdentifier(GetIdentifier(), &resolvedPath, &args);
991 
992         if (!_Read(identifier, resolvedPath, /* metadataOnly = */ false)) {
993             return _ReloadFailed;
994         }
995 
996         _externalAssetModificationTimes = std::move(externalAssetTimestamps);
997     } else {
998         // The physical location of the file may have changed since
999         // the last load, so re-resolve the identifier.
1000         const ArResolvedPath oldResolvedPath = GetResolvedPath();
1001         UpdateAssetInfo();
1002         const ArResolvedPath resolvedPath = GetResolvedPath();
1003 
1004         // If asset resolution in UpdateAssetInfo failed, we may end
1005         // up with an empty real path, and cannot reload the layer.
1006         if (resolvedPath.empty()) {
1007             TF_RUNTIME_ERROR(
1008                 "Cannot determine resolved path for '%s', skipping reload.",
1009                 identifier.c_str());
1010             return _ReloadFailed;
1011         }
1012 
1013         // If this layer's modification timestamp is empty, this is a
1014         // new layer that has never been serialized. This could happen
1015         // if a layer were created with SdfLayer::New, for instance.
1016         // In such cases we can skip the reload since there's nowhere
1017         // to reload data from.
1018         //
1019         // This ensures we don't ask for the modification timestamp for
1020         // unserialized new layers below, which would result in errors.
1021         //
1022         // XXX 2014-09-02 Reset layer to initial data?
1023         if (_assetModificationTime.IsEmpty()) {
1024             return _ReloadSkipped;
1025         }
1026 
1027         // Get the layer's modification timestamp.
1028         std::string layerPath, args;
1029         Sdf_SplitIdentifier(GetIdentifier(), &layerPath, &args);
1030 
1031         VtValue timestamp(ArGetResolver().GetModificationTimestamp(
1032             layerPath, resolvedPath));
1033 #if AR_VERSION == 1
1034         if (timestamp.IsEmpty()) {
1035             TF_CODING_ERROR(
1036                 "Unable to get modification time for '%s (%s)'",
1037                 GetIdentifier().c_str(), resolvedPath.GetPathString().c_str());
1038             return _ReloadFailed;
1039         }
1040 #endif
1041 
1042         // Ask the current external asset dependency state.
1043         VtDictionary externalAssetTimestamps =
1044             _GetExternalAssetModificationTimes(*this);
1045 
1046         // See if we can skip reloading.
1047         if (!force && !IsDirty()
1048             && (resolvedPath == oldResolvedPath)
1049             && (_ModificationTimesEqual(timestamp, _assetModificationTime))
1050             && (_ModificationTimesEqual(
1051                     externalAssetTimestamps, _externalAssetModificationTimes))){
1052             return _ReloadSkipped;
1053         }
1054 
1055         if (!_Read(GetIdentifier(), resolvedPath, /* metadataOnly = */ false)) {
1056             return _ReloadFailed;
1057         }
1058 
1059         _assetModificationTime.Swap(timestamp);
1060         _externalAssetModificationTimes = std::move(externalAssetTimestamps);
1061 
1062         if (resolvedPath != oldResolvedPath) {
1063             Sdf_ChangeManager::Get().DidChangeLayerResolvedPath(_self);
1064         }
1065     }
1066 
1067     _MarkCurrentStateAsClean();
1068 
1069     Sdf_ChangeManager::Get().DidReloadLayerContent(_self);
1070 
1071     return _ReloadSucceeded;
1072 }
1073 
1074 bool
Reload(bool force)1075 SdfLayer::Reload(bool force)
1076 {
1077     return _Reload(force) == _ReloadSucceeded;
1078 }
1079 
1080 bool
ReloadLayers(const set<SdfLayerHandle> & layers,bool force)1081 SdfLayer::ReloadLayers(
1082     const set<SdfLayerHandle>& layers,
1083     bool force)
1084 {
1085     TF_DESCRIBE_SCOPE("Reloading %zu layer(s)", layers.size());
1086 
1087     // Block re-composition until we've finished reloading layers.
1088     SdfChangeBlock block;
1089     bool status = true;
1090     TF_FOR_ALL(layer, layers) {
1091         if (*layer) {
1092             if ((*layer)->_Reload(force) == _ReloadFailed) {
1093                 status = false;
1094                 TF_WARN("Unable to re-read @%s@",
1095                         (*layer)->GetIdentifier().c_str());
1096             }
1097         }
1098     }
1099 
1100     return status;
1101 }
1102 
1103 bool
Import(const string & layerPath)1104 SdfLayer::Import(const string &layerPath)
1105 {
1106     string filePath = Sdf_ResolvePath(layerPath);
1107     if (filePath.empty())
1108         return false;
1109 
1110     return _Read(layerPath, filePath, /* metadataOnly = */ false);
1111 }
1112 
1113 bool
ImportFromString(const std::string & s)1114 SdfLayer::ImportFromString(const std::string &s)
1115 {
1116     return GetFileFormat()->ReadFromString(this, s);
1117 }
1118 
1119 bool
_Read(const string & identifier,const string & resolvedPath,bool metadataOnly)1120 SdfLayer::_Read(
1121     const string& identifier,
1122     const string& resolvedPath,
1123     bool metadataOnly)
1124 {
1125     TRACE_FUNCTION();
1126     TfAutoMallocTag tag("SdfLayer::_Read");
1127     TF_DESCRIBE_SCOPE("Loading layer '%s'", resolvedPath.c_str());
1128     TF_DEBUG(SDF_LAYER).Msg(
1129         "SdfLayer::_Read('%s', '%s', metadataOnly=%s)\n",
1130         identifier.c_str(), resolvedPath.c_str(),
1131         TfStringify(metadataOnly).c_str());
1132 
1133     SdfFileFormatConstPtr format = GetFileFormat();
1134 #if AR_VERSION == 1
1135     if (format->LayersAreFileBased()) {
1136         if (!ArGetResolver().FetchToLocalResolvedPath(
1137                 identifier, resolvedPath)) {
1138             TF_DEBUG(SDF_LAYER).Msg(
1139                 "SdfLayer::_Read - unable to fetch '%s' to "
1140                 "local path '%s'\n",
1141                 identifier.c_str(), resolvedPath.c_str());
1142             return false;
1143         }
1144 
1145         TF_DEBUG(SDF_LAYER).Msg(
1146             "SdfLayer::_Read - fetched '%s' to local path '%s'\n",
1147             identifier.c_str(), resolvedPath.c_str());
1148     }
1149 #endif
1150     return format->Read(this, resolvedPath, metadataOnly);
1151 }
1152 
1153 /*static*/
1154 SdfLayerHandle
Find(const string & identifier,const FileFormatArguments & args)1155 SdfLayer::Find(const string &identifier,
1156                const FileFormatArguments &args)
1157 {
1158     TRACE_FUNCTION();
1159 
1160     tbb::queuing_rw_mutex::scoped_lock lock;
1161     return _Find(identifier, args, lock, /* retryAsWriter = */ false);
1162 }
1163 
1164 template <class ScopedLock>
1165 SdfLayerRefPtr
_Find(const string & identifier,const FileFormatArguments & args,ScopedLock & lock,bool retryAsWriter)1166 SdfLayer::_Find(const string &identifier,
1167                 const FileFormatArguments &args,
1168                 ScopedLock& lock,
1169                 bool retryAsWriter)
1170 {
1171     // We don't need to drop the GIL here, since _TryToFindLayer() doesn't
1172     // invoke any plugin code, and if we do wind up calling
1173     // _WaitForInitializationAndCheckIfSuccessful() then we'll drop the GIL in
1174     // there.
1175 
1176     _FindOrOpenLayerInfo layerInfo;
1177     if (!_ComputeInfoToFindOrOpenLayer(identifier, args, &layerInfo)) {
1178         return TfNullPtr;
1179     }
1180 
1181     // First see if this layer is already present.
1182     lock.acquire(_GetLayerRegistryMutex(), /*write=*/false);
1183     if (SdfLayerRefPtr layer = _TryToFindLayer(
1184             layerInfo.identifier, layerInfo.resolvedLayerPath,
1185             lock, retryAsWriter)) {
1186         return layer->_WaitForInitializationAndCheckIfSuccessful() ?
1187             layer : TfNullPtr;
1188     }
1189     return TfNullPtr;
1190 }
1191 
1192 /* static */
1193 SdfLayerHandle
FindRelativeToLayer(const SdfLayerHandle & anchor,const string & identifier,const FileFormatArguments & args)1194 SdfLayer::FindRelativeToLayer(
1195     const SdfLayerHandle &anchor,
1196     const string &identifier,
1197     const FileFormatArguments &args)
1198 {
1199     TRACE_FUNCTION();
1200 
1201     if (!anchor) {
1202         TF_CODING_ERROR("Anchor layer is invalid");
1203         return TfNullPtr;
1204     }
1205 
1206     // For consistency with FindOrOpen, we silently bail out if identifier
1207     // is empty here to avoid the coding error that is emitted in that case
1208     // in SdfComputeAssetPathRelativeToLayer.
1209     if (identifier.empty()) {
1210         return TfNullPtr;
1211     }
1212 
1213     return Find(
1214         SdfComputeAssetPathRelativeToLayer(anchor, identifier), args);
1215 }
1216 
1217 std::set<double>
ListAllTimeSamples() const1218 SdfLayer::ListAllTimeSamples() const
1219 {
1220     return _data->ListAllTimeSamples();
1221 }
1222 
1223 std::set<double>
ListTimeSamplesForPath(const SdfPath & path) const1224 SdfLayer::ListTimeSamplesForPath(const SdfPath& path) const
1225 {
1226     return _data->ListTimeSamplesForPath(path);
1227 }
1228 
1229 bool
GetBracketingTimeSamples(double time,double * tLower,double * tUpper)1230 SdfLayer::GetBracketingTimeSamples(double time, double* tLower, double* tUpper)
1231 {
1232     return _data->GetBracketingTimeSamples(time, tLower, tUpper);
1233 }
1234 
1235 size_t
GetNumTimeSamplesForPath(const SdfPath & path) const1236 SdfLayer::GetNumTimeSamplesForPath(const SdfPath& path) const
1237 {
1238     return _data->GetNumTimeSamplesForPath(path);
1239 }
1240 
1241 bool
GetBracketingTimeSamplesForPath(const SdfPath & path,double time,double * tLower,double * tUpper)1242 SdfLayer::GetBracketingTimeSamplesForPath(const SdfPath& path,
1243                                           double time,
1244                                           double* tLower, double* tUpper)
1245 {
1246     return _data->GetBracketingTimeSamplesForPath(path, time, tLower, tUpper);
1247 }
1248 
1249 bool
QueryTimeSample(const SdfPath & path,double time,VtValue * value) const1250 SdfLayer::QueryTimeSample(const SdfPath& path, double time,
1251                           VtValue *value) const
1252 {
1253     return _data->QueryTimeSample(path, time, value);
1254 }
1255 
1256 bool
QueryTimeSample(const SdfPath & path,double time,SdfAbstractDataValue * value) const1257 SdfLayer::QueryTimeSample(const SdfPath& path, double time,
1258                           SdfAbstractDataValue *value) const
1259 {
1260     return _data->QueryTimeSample(path, time, value);
1261 }
1262 
1263 static TfType
_GetExpectedTimeSampleValueType(const SdfLayer & layer,const SdfPath & path)1264 _GetExpectedTimeSampleValueType(
1265     const SdfLayer& layer, const SdfPath& path)
1266 {
1267     const SdfSpecType specType = layer.GetSpecType(path);
1268     if (specType == SdfSpecTypeUnknown) {
1269         TF_CODING_ERROR("Cannot set time sample at <%s> since spec does "
1270                         "not exist", path.GetText());
1271         return TfType();
1272     }
1273     else if (specType != SdfSpecTypeAttribute &&
1274              specType != SdfSpecTypeRelationship) {
1275         TF_CODING_ERROR("Cannot set time sample at <%s> because spec "
1276                         "is not an attribute or relationship",
1277                         path.GetText());
1278         return TfType();
1279     }
1280 
1281     TfType valueType;
1282     TfToken valueTypeName;
1283     if (specType == SdfSpecTypeRelationship) {
1284         static const TfType pathType = TfType::Find<SdfPath>();
1285         valueType = pathType;
1286     }
1287     else if (layer.HasField(path, SdfFieldKeys->TypeName, &valueTypeName)) {
1288         valueType = layer.GetSchema().FindType(valueTypeName).GetType();
1289     }
1290 
1291     if (!valueType) {
1292         TF_CODING_ERROR("Cannot determine value type for <%s>",
1293                         path.GetText());
1294     }
1295 
1296     return valueType;
1297 }
1298 
1299 void
SetTimeSample(const SdfPath & path,double time,const VtValue & value)1300 SdfLayer::SetTimeSample(const SdfPath& path, double time,
1301                         const VtValue & value)
1302 {
1303     if (!PermissionToEdit()) {
1304         TF_CODING_ERROR("Cannot set time sample on <%s>.  "
1305                         "Layer @%s@ is not editable.",
1306                         path.GetText(),
1307                         GetIdentifier().c_str());
1308         return;
1309     }
1310 
1311     // circumvent type checking if setting a block.
1312     if (value.IsHolding<SdfValueBlock>()) {
1313         _PrimSetTimeSample(path, time, value);
1314         return;
1315     }
1316 
1317     const TfType expectedType = _GetExpectedTimeSampleValueType(*this, path);
1318     if (!expectedType) {
1319         // Error already emitted, just bail.
1320         return;
1321     }
1322 
1323     if (value.GetType() == expectedType) {
1324         _PrimSetTimeSample(path, time, value);
1325     }
1326     else {
1327         const VtValue castValue =
1328             VtValue::CastToTypeid(value, expectedType.GetTypeid());
1329         if (castValue.IsEmpty()) {
1330             TF_CODING_ERROR("Can't set time sample on <%s> to %s: "
1331                             "expected a value of type \"%s\"",
1332                             path.GetText(),
1333                             TfStringify(value).c_str(),
1334                             expectedType.GetTypeName().c_str());
1335             return;
1336         }
1337 
1338         _PrimSetTimeSample(path, time, castValue);
1339     }
1340 }
1341 
1342 // cache the value of typeid(SdfValueBlock)
1343 namespace
1344 {
_GetSdfValueBlockType()1345     const TfType& _GetSdfValueBlockType()
1346     {
1347         static const TfType blockType = TfType::Find<SdfValueBlock>();
1348         return blockType;
1349     }
1350 }
1351 
1352 
1353 void
SetTimeSample(const SdfPath & path,double time,const SdfAbstractDataConstValue & value)1354 SdfLayer::SetTimeSample(const SdfPath& path, double time,
1355                         const SdfAbstractDataConstValue& value)
1356 {
1357     if (!PermissionToEdit()) {
1358         TF_CODING_ERROR("Cannot set time sample on <%s>.  "
1359                         "Layer @%s@ is not editable.",
1360                         path.GetText(),
1361                         GetIdentifier().c_str());
1362         return;
1363     }
1364 
1365     if (value.valueType == _GetSdfValueBlockType().GetTypeid()) {
1366         _PrimSetTimeSample(path, time, value);
1367         return;
1368     }
1369 
1370     const TfType expectedType = _GetExpectedTimeSampleValueType(*this, path);
1371     if (!expectedType) {
1372         // Error already emitted, just bail.
1373         return;
1374     }
1375 
1376     if (TfSafeTypeCompare(value.valueType, expectedType.GetTypeid())) {
1377         _PrimSetTimeSample(path, time, value);
1378     }
1379     else {
1380         VtValue tmpValue;
1381         value.GetValue(&tmpValue);
1382 
1383         const VtValue castValue =
1384             VtValue::CastToTypeid(tmpValue, expectedType.GetTypeid());
1385         if (castValue.IsEmpty()) {
1386             TF_CODING_ERROR("Can't set time sample on <%s> to %s: "
1387                             "expected a value of type \"%s\"",
1388                             path.GetText(),
1389                             TfStringify(tmpValue).c_str(),
1390                             expectedType.GetTypeName().c_str());
1391             return;
1392         }
1393 
1394         _PrimSetTimeSample(path, time, castValue);
1395     }
1396 }
1397 
1398 void
EraseTimeSample(const SdfPath & path,double time)1399 SdfLayer::EraseTimeSample(const SdfPath& path, double time)
1400 {
1401     if (!PermissionToEdit()) {
1402         TF_CODING_ERROR("Cannot set time sample on <%s>.  "
1403                         "Layer @%s@ is not editable.",
1404                         path.GetText(),
1405                         GetIdentifier().c_str());
1406         return;
1407     }
1408     if (!HasSpec(path)) {
1409         TF_CODING_ERROR("Cannot SetTimeSample at <%s> since spec does "
1410                         "not exist", path.GetText());
1411         return;
1412     }
1413 
1414     if (!QueryTimeSample(path, time)) {
1415         // No time sample to remove.
1416         return;
1417     }
1418 
1419     _PrimSetTimeSample(path, time, VtValue());
1420 }
1421 
1422 static
_GetVtValue(const VtValue & v)1423 const VtValue& _GetVtValue(const VtValue& v)
1424 { return v; }
1425 
1426 static
_GetVtValue(const SdfAbstractDataConstValue & v)1427 VtValue _GetVtValue(const SdfAbstractDataConstValue& v)
1428 {
1429     VtValue value;
1430     TF_VERIFY(v.GetValue(&value));
1431     return value;
1432 }
1433 
1434 template <class T>
1435 void
_PrimSetTimeSample(const SdfPath & path,double time,const T & value,bool useDelegate)1436 SdfLayer::_PrimSetTimeSample(const SdfPath& path, double time,
1437                              const T& value,
1438                              bool useDelegate)
1439 {
1440     if (useDelegate && TF_VERIFY(_stateDelegate)) {
1441         _stateDelegate->SetTimeSample(path, time, value);
1442         return;
1443     }
1444 
1445     SdfChangeBlock block;
1446 
1447     // TODO(USD):optimization: Analyze the affected time interval.
1448     Sdf_ChangeManager::Get().DidChangeAttributeTimeSamples(_self, path);
1449 
1450     // XXX: Should modify SetTimeSample API to take an
1451     //      SdfAbstractDataConstValue instead of (or along with) VtValue.
1452     const VtValue& valueToSet = _GetVtValue(value);
1453     _data->SetTimeSample(path, time, valueToSet);
1454 }
1455 
1456 template void SdfLayer::_PrimSetTimeSample(
1457     const SdfPath&, double,
1458     const VtValue&, bool);
1459 template void SdfLayer::_PrimSetTimeSample(
1460     const SdfPath&, double,
1461     const SdfAbstractDataConstValue&, bool);
1462 
1463 // ---
1464 // End of SdfLayer static functions
1465 // ---
1466 
1467 void
_InitializeFromIdentifier(const string & identifier,const string & realPath,const string & fileVersion,const ArAssetInfo & assetInfo)1468 SdfLayer::_InitializeFromIdentifier(
1469     const string& identifier,
1470     const string& realPath,
1471     const string& fileVersion,
1472     const ArAssetInfo& assetInfo)
1473 {
1474     TRACE_FUNCTION();
1475 
1476     // Compute layer asset information from the identifier.
1477     std::unique_ptr<Sdf_AssetInfo> newInfo(
1478         Sdf_ComputeAssetInfoFromIdentifier(identifier, realPath, assetInfo,
1479             fileVersion));
1480     if (!newInfo)
1481         return;
1482 
1483     // If the newly computed asset info is identical to the existing asset
1484     // info, there is no need to update registries or send notices.
1485     if (*newInfo == *_assetInfo)
1486         return;
1487 
1488     // Swap the layer asset info with the newly computed information. This
1489     // must occur prior to updating the layer registry, as the new layer
1490     // information is used to recompute registry indices.
1491     string oldIdentifier = _assetInfo->identifier;
1492     ArResolvedPath oldResolvedPath = _assetInfo->resolvedPath;
1493     _assetInfo.swap(newInfo);
1494 
1495     // Update layer state delegate.
1496     if (TF_VERIFY(_stateDelegate)) {
1497         _stateDelegate->_SetLayer(_self);
1498     }
1499 
1500     // Update the layer registry before sending notices.
1501     _layerRegistry->InsertOrUpdate(_self);
1502 
1503     // Only send a notice if the identifier has changed (this notice causes
1504     // mass invalidation. See http://bug/33217). If the old identifier was
1505     // empty, this is a newly constructed layer, so don't send the notice.
1506     if (!oldIdentifier.empty()) {
1507         SdfChangeBlock block;
1508         if (oldIdentifier != GetIdentifier()) {
1509             Sdf_ChangeManager::Get().DidChangeLayerIdentifier(
1510                 _self, oldIdentifier);
1511         }
1512         if (oldResolvedPath != GetResolvedPath()) {
1513             Sdf_ChangeManager::Get().DidChangeLayerResolvedPath(_self);
1514         }
1515     }
1516 }
1517 
1518 template <class T>
1519 inline
1520 void
_SetValue(const TfToken & key,T value)1521 SdfLayer::_SetValue(const TfToken& key, T value)
1522 {
1523     SetField(SdfPath::AbsoluteRootPath(), key, VtValue(value));
1524 }
1525 
1526 template <class T>
1527 inline
1528 T
_GetValue(const TfToken & key) const1529 SdfLayer::_GetValue(const TfToken& key) const
1530 {
1531     VtValue value;
1532     if (!HasField(SdfPath::AbsoluteRootPath(), key, &value)) {
1533         return GetSchema().GetFallback(key).Get<T>();
1534     }
1535 
1536     return value.Get<T>();
1537 }
1538 
1539 SdfAssetPath
GetColorConfiguration() const1540 SdfLayer::GetColorConfiguration() const
1541 {
1542     return _GetValue<SdfAssetPath>(SdfFieldKeys->ColorConfiguration);
1543 }
1544 
1545 void
SetColorConfiguration(const SdfAssetPath & colorConfiguration)1546 SdfLayer::SetColorConfiguration(const SdfAssetPath &colorConfiguration)
1547 {
1548     _SetValue(SdfFieldKeys->ColorConfiguration, colorConfiguration);
1549 }
1550 
1551 bool
HasColorConfiguration() const1552 SdfLayer::HasColorConfiguration() const
1553 {
1554     return HasField(SdfPath::AbsoluteRootPath(),
1555                     SdfFieldKeys->ColorConfiguration);
1556 }
1557 
1558 void
ClearColorConfiguration()1559 SdfLayer::ClearColorConfiguration()
1560 {
1561     EraseField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->ColorConfiguration);
1562 }
1563 
1564 TfToken
GetColorManagementSystem() const1565 SdfLayer::GetColorManagementSystem() const
1566 {
1567     return _GetValue<TfToken>(SdfFieldKeys->ColorManagementSystem);
1568 }
1569 
1570 void
SetColorManagementSystem(const TfToken & cms)1571 SdfLayer::SetColorManagementSystem(const TfToken &cms)
1572 {
1573     _SetValue(SdfFieldKeys->ColorManagementSystem, cms);
1574 }
1575 
1576 bool
HasColorManagementSystem() const1577 SdfLayer::HasColorManagementSystem() const
1578 {
1579     return HasField(SdfPath::AbsoluteRootPath(),
1580                     SdfFieldKeys->ColorManagementSystem);
1581 }
1582 
1583 void
ClearColorManagementSystem()1584 SdfLayer::ClearColorManagementSystem()
1585 {
1586     EraseField(SdfPath::AbsoluteRootPath(),
1587                SdfFieldKeys->ColorManagementSystem);
1588 }
1589 
1590 void
SetComment(const string & newVal)1591 SdfLayer::SetComment(const string &newVal)
1592 {
1593     _SetValue(SdfFieldKeys->Comment, newVal);
1594 }
1595 
1596 string
GetComment() const1597 SdfLayer::GetComment() const
1598 {
1599     return _GetValue<string>(SdfFieldKeys->Comment);
1600 }
1601 
1602 void
SetDefaultPrim(const TfToken & name)1603 SdfLayer::SetDefaultPrim(const TfToken &name)
1604 {
1605     _SetValue(SdfFieldKeys->DefaultPrim, name);
1606 }
1607 
1608 TfToken
GetDefaultPrim() const1609 SdfLayer::GetDefaultPrim() const
1610 {
1611     return _GetValue<TfToken>(SdfFieldKeys->DefaultPrim);
1612 }
1613 
1614 void
ClearDefaultPrim()1615 SdfLayer::ClearDefaultPrim()
1616 {
1617     EraseField(SdfPath::AbsoluteRootPath(),
1618                SdfFieldKeys->DefaultPrim);
1619 }
1620 
1621 bool
HasDefaultPrim()1622 SdfLayer::HasDefaultPrim()
1623 {
1624     return HasField(SdfPath::AbsoluteRootPath(),
1625                     SdfFieldKeys->DefaultPrim);
1626 }
1627 
1628 void
SetDocumentation(const string & newVal)1629 SdfLayer::SetDocumentation(const string &newVal)
1630 {
1631     _SetValue(SdfFieldKeys->Documentation, newVal);
1632 }
1633 
1634 string
GetDocumentation() const1635 SdfLayer::GetDocumentation() const
1636 {
1637     return _GetValue<string>(SdfFieldKeys->Documentation);
1638 }
1639 
1640 void
SetStartTimeCode(double newVal)1641 SdfLayer::SetStartTimeCode( double newVal )
1642 {
1643     _SetValue(SdfFieldKeys->StartTimeCode, newVal);
1644 }
1645 
1646 double
GetStartTimeCode() const1647 SdfLayer::GetStartTimeCode() const
1648 {
1649     return _GetValue<double>(SdfFieldKeys->StartTimeCode);
1650 }
1651 
1652 bool
HasStartTimeCode() const1653 SdfLayer::HasStartTimeCode() const
1654 {
1655     return HasField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->StartTimeCode);
1656 }
1657 
1658 void
ClearStartTimeCode()1659 SdfLayer::ClearStartTimeCode()
1660 {
1661     EraseField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->StartTimeCode);
1662 }
1663 
1664 void
SetEndTimeCode(double newVal)1665 SdfLayer::SetEndTimeCode( double newVal )
1666 {
1667     _SetValue(SdfFieldKeys->EndTimeCode, newVal);
1668 }
1669 
1670 double
GetEndTimeCode() const1671 SdfLayer::GetEndTimeCode() const
1672 {
1673     return _GetValue<double>(SdfFieldKeys->EndTimeCode);
1674 }
1675 
1676 bool
HasEndTimeCode() const1677 SdfLayer::HasEndTimeCode() const
1678 {
1679     return HasField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->EndTimeCode);
1680 }
1681 
1682 void
ClearEndTimeCode()1683 SdfLayer::ClearEndTimeCode()
1684 {
1685     EraseField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->EndTimeCode);
1686 }
1687 
1688 void
SetTimeCodesPerSecond(double newVal)1689 SdfLayer::SetTimeCodesPerSecond( double newVal )
1690 {
1691     _SetValue(SdfFieldKeys->TimeCodesPerSecond, newVal);
1692 }
1693 
1694 double
GetTimeCodesPerSecond() const1695 SdfLayer::GetTimeCodesPerSecond() const
1696 {
1697     // If there is an authored value for timeCodesPerSecond, return that.
1698     VtValue value;
1699     if (HasField(
1700             SdfPath::AbsoluteRootPath(),
1701             SdfFieldKeys->TimeCodesPerSecond,
1702             &value)) {
1703         return value.Get<double>();
1704     }
1705 
1706     // Otherwise return framesPerSecond as a dynamic fallback.  This allows
1707     // layers to lock framesPerSecond and timeCodesPerSecond together by
1708     // specifying only framesPerSecond.
1709     //
1710     // If neither field has an authored value, this will return 24, which is the
1711     // final fallback value for both fields.
1712     return GetFramesPerSecond();
1713 }
1714 
1715 bool
HasTimeCodesPerSecond() const1716 SdfLayer::HasTimeCodesPerSecond() const
1717 {
1718     return HasField(
1719         SdfPath::AbsoluteRootPath(), SdfFieldKeys->TimeCodesPerSecond);
1720 }
1721 
1722 void
ClearTimeCodesPerSecond()1723 SdfLayer::ClearTimeCodesPerSecond()
1724 {
1725     return EraseField(
1726         SdfPath::AbsoluteRootPath(), SdfFieldKeys->TimeCodesPerSecond);
1727 }
1728 
1729 void
SetFramesPerSecond(double newVal)1730 SdfLayer::SetFramesPerSecond( double newVal )
1731 {
1732     _SetValue(SdfFieldKeys->FramesPerSecond, newVal);
1733 }
1734 
1735 double
GetFramesPerSecond() const1736 SdfLayer::GetFramesPerSecond() const
1737 {
1738     return _GetValue<double>(SdfFieldKeys->FramesPerSecond);
1739 }
1740 
1741 bool
HasFramesPerSecond() const1742 SdfLayer::HasFramesPerSecond() const
1743 {
1744     return HasField(
1745         SdfPath::AbsoluteRootPath(), SdfFieldKeys->FramesPerSecond);
1746 }
1747 
1748 void
ClearFramesPerSecond()1749 SdfLayer::ClearFramesPerSecond()
1750 {
1751     return EraseField(
1752         SdfPath::AbsoluteRootPath(), SdfFieldKeys->FramesPerSecond);
1753 }
1754 
1755 void
SetFramePrecision(int newVal)1756 SdfLayer::SetFramePrecision( int newVal )
1757 {
1758     _SetValue(SdfFieldKeys->FramePrecision, newVal);
1759 }
1760 
1761 int
GetFramePrecision() const1762 SdfLayer::GetFramePrecision() const
1763 {
1764     return _GetValue<int>(SdfFieldKeys->FramePrecision);
1765 }
1766 
1767 bool
HasFramePrecision() const1768 SdfLayer::HasFramePrecision() const
1769 {
1770     return HasField(
1771         SdfPath::AbsoluteRootPath(), SdfFieldKeys->FramePrecision);
1772 }
1773 
1774 void
ClearFramePrecision()1775 SdfLayer::ClearFramePrecision()
1776 {
1777     return EraseField(
1778         SdfPath::AbsoluteRootPath(), SdfFieldKeys->FramePrecision);
1779 }
1780 
1781 string
GetOwner() const1782 SdfLayer::GetOwner() const
1783 {
1784     return _GetValue<string>(SdfFieldKeys->Owner);
1785 }
1786 
1787 void
SetOwner(const std::string & newVal)1788 SdfLayer::SetOwner(const std::string& newVal)
1789 {
1790     _SetValue(SdfFieldKeys->Owner, newVal);
1791 }
1792 
1793 bool
HasOwner() const1794 SdfLayer::HasOwner() const
1795 {
1796     return HasField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->Owner);
1797 }
1798 
1799 void
ClearOwner()1800 SdfLayer::ClearOwner()
1801 {
1802     return EraseField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->Owner);
1803 }
1804 
1805 string
GetSessionOwner() const1806 SdfLayer::GetSessionOwner() const
1807 {
1808     return _GetValue<string>(SdfFieldKeys->SessionOwner);
1809 }
1810 
1811 void
SetSessionOwner(const std::string & newVal)1812 SdfLayer::SetSessionOwner(const std::string& newVal)
1813 {
1814     _SetValue(SdfFieldKeys->SessionOwner, newVal);
1815 }
1816 
1817 bool
HasSessionOwner() const1818 SdfLayer::HasSessionOwner() const
1819 {
1820     return HasField(
1821         SdfPath::AbsoluteRootPath(), SdfFieldKeys->SessionOwner);
1822 }
1823 
1824 void
ClearSessionOwner()1825 SdfLayer::ClearSessionOwner()
1826 {
1827     return EraseField(
1828         SdfPath::AbsoluteRootPath(), SdfFieldKeys->SessionOwner);
1829 }
1830 
1831 bool
GetHasOwnedSubLayers() const1832 SdfLayer::GetHasOwnedSubLayers() const
1833 {
1834     return _GetValue<bool>(SdfFieldKeys->HasOwnedSubLayers);
1835 }
1836 
1837 void
SetHasOwnedSubLayers(bool newVal)1838 SdfLayer::SetHasOwnedSubLayers(bool newVal)
1839 {
1840     _SetValue(SdfFieldKeys->HasOwnedSubLayers, newVal);
1841 }
1842 
1843 VtDictionary
GetCustomLayerData() const1844 SdfLayer::GetCustomLayerData() const
1845 {
1846     return _GetValue<VtDictionary>(SdfFieldKeys->CustomLayerData);
1847 }
1848 
1849 void
SetCustomLayerData(const VtDictionary & dict)1850 SdfLayer::SetCustomLayerData(const VtDictionary& dict)
1851 {
1852     _SetValue(SdfFieldKeys->CustomLayerData, dict);
1853 }
1854 
1855 bool
HasCustomLayerData() const1856 SdfLayer::HasCustomLayerData() const
1857 {
1858     return HasField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->CustomLayerData);
1859 }
1860 
1861 void
ClearCustomLayerData()1862 SdfLayer::ClearCustomLayerData()
1863 {
1864     EraseField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->CustomLayerData);
1865 }
1866 
1867 SdfPrimSpecHandle
GetPseudoRoot() const1868 SdfLayer::GetPseudoRoot() const
1869 {
1870     return SdfPrimSpecHandle(
1871         _idRegistry.Identify(SdfPath::AbsoluteRootPath()));
1872 }
1873 
1874 SdfLayer::RootPrimsView
GetRootPrims() const1875 SdfLayer::GetRootPrims() const
1876 {
1877     return GetPseudoRoot()->GetNameChildren();
1878 }
1879 
1880 void
SetRootPrims(const SdfPrimSpecHandleVector & newComps)1881 SdfLayer::SetRootPrims( const SdfPrimSpecHandleVector &newComps )
1882 {
1883     return GetPseudoRoot()->SetNameChildren(newComps);
1884 }
1885 
1886 bool
InsertRootPrim(const SdfPrimSpecHandle & prim,int index)1887 SdfLayer::InsertRootPrim( const SdfPrimSpecHandle & prim, int index )
1888 {
1889     return GetPseudoRoot()->InsertNameChild(prim, index);
1890 }
1891 
1892 void
RemoveRootPrim(const SdfPrimSpecHandle & prim)1893 SdfLayer::RemoveRootPrim(const SdfPrimSpecHandle & prim)
1894 {
1895     GetPseudoRoot()->RemoveNameChild(prim);
1896 }
1897 
1898 SdfNameOrderProxy
GetRootPrimOrder() const1899 SdfLayer::GetRootPrimOrder() const
1900 {
1901     return GetPseudoRoot()->GetNameChildrenOrder();
1902 }
1903 
1904 void
SetRootPrimOrder(const vector<TfToken> & names)1905 SdfLayer::SetRootPrimOrder( const vector<TfToken>& names )
1906 {
1907     GetPseudoRoot()->SetNameChildrenOrder(names);
1908 }
1909 
1910 void
InsertInRootPrimOrder(const TfToken & name,int index)1911 SdfLayer::InsertInRootPrimOrder( const TfToken & name, int index )
1912 {
1913     GetPseudoRoot()->InsertInNameChildrenOrder(name, index);
1914 }
1915 
1916 void
RemoveFromRootPrimOrder(const TfToken & name)1917 SdfLayer::RemoveFromRootPrimOrder( const TfToken & name )
1918 {
1919     GetPseudoRoot()->RemoveFromNameChildrenOrder(name);
1920 }
1921 
1922 void
RemoveFromRootPrimOrderByIndex(int index)1923 SdfLayer::RemoveFromRootPrimOrderByIndex(int index)
1924 {
1925     GetPseudoRoot()->RemoveFromNameChildrenOrderByIndex(index);
1926 }
1927 
1928 void
ApplyRootPrimOrder(vector<TfToken> * vec) const1929 SdfLayer::ApplyRootPrimOrder( vector<TfToken>* vec ) const
1930 {
1931     GetPseudoRoot()->ApplyNameChildrenOrder(vec);
1932 }
1933 
1934 SdfSubLayerProxy
GetSubLayerPaths() const1935 SdfLayer::GetSubLayerPaths() const
1936 {
1937     boost::shared_ptr<Sdf_ListEditor<SdfSubLayerTypePolicy>>
1938         editor(new Sdf_SubLayerListEditor(_self));
1939 
1940     return SdfSubLayerProxy(editor, SdfListOpTypeOrdered);
1941 }
1942 
1943 void
SetSubLayerPaths(const vector<string> & newPaths)1944 SdfLayer::SetSubLayerPaths(const vector<string>& newPaths)
1945 {
1946     GetSubLayerPaths() = newPaths;
1947 }
1948 
1949 size_t
GetNumSubLayerPaths() const1950 SdfLayer::GetNumSubLayerPaths() const
1951 {
1952     return GetSubLayerPaths().size();
1953 }
1954 
1955 void
InsertSubLayerPath(const string & path,int index)1956 SdfLayer::InsertSubLayerPath(const string& path, int index)
1957 {
1958     SdfSubLayerProxy proxy = GetSubLayerPaths();
1959 
1960     if (index == -1) {
1961         index = static_cast<int>(proxy.size());
1962     }
1963 
1964     proxy.Insert(index, path);
1965 }
1966 
1967 void
RemoveSubLayerPath(int index)1968 SdfLayer::RemoveSubLayerPath(int index)
1969 {
1970     GetSubLayerPaths().Erase(index);
1971 }
1972 
1973 SdfLayerOffsetVector
GetSubLayerOffsets() const1974 SdfLayer::GetSubLayerOffsets() const
1975 {
1976     return GetFieldAs<SdfLayerOffsetVector>(
1977         SdfPath::AbsoluteRootPath(), SdfFieldKeys->SubLayerOffsets);
1978 }
1979 
1980 SdfLayerOffset
GetSubLayerOffset(int index) const1981 SdfLayer::GetSubLayerOffset(int index) const
1982 {
1983     SdfLayerOffsetVector offsets = GetSubLayerOffsets();
1984     if (index < 0 || static_cast<size_t>(index) >= offsets.size()) {
1985         TF_CODING_ERROR("Invalid sublayer index");
1986         return SdfLayerOffset();
1987     }
1988     return offsets[index];
1989 }
1990 
1991 void
SetSubLayerOffset(const SdfLayerOffset & offset,int index)1992 SdfLayer::SetSubLayerOffset(const SdfLayerOffset& offset, int index)
1993 {
1994     SdfLayerOffsetVector offsets = GetFieldAs<SdfLayerOffsetVector>(
1995         SdfPath::AbsoluteRootPath(), SdfFieldKeys->SubLayerOffsets);
1996     if (index < 0 || static_cast<size_t>(index) >= offsets.size()) {
1997         TF_CODING_ERROR("Invalid sublayer index");
1998         return;
1999     }
2000 
2001     offsets[index] = offset;
2002 
2003     SetField(SdfPath::AbsoluteRootPath(), SdfFieldKeys->SubLayerOffsets,
2004         VtValue(offsets));
2005 }
2006 
2007 bool
_CanGetSpecAtPath(const SdfPath & path,SdfPath * canonicalPath,SdfSpecType * specType) const2008 SdfLayer::_CanGetSpecAtPath(
2009     const SdfPath& path,
2010     SdfPath* canonicalPath, SdfSpecType* specType) const
2011 {
2012     if (path.IsEmpty()) {
2013         return false;
2014     }
2015 
2016     // We need to always call MakeAbsolutePath, even if relativePath is
2017     // already absolute, because we also need to absolutize target paths
2018     // within the path.
2019     SdfPath const *absPath = &path;
2020     if (ARCH_UNLIKELY(!path.IsAbsolutePath() || path.ContainsTargetPath())) {
2021         *canonicalPath = path.MakeAbsolutePath(SdfPath::AbsoluteRootPath());
2022         absPath = canonicalPath;
2023     }
2024     // Grab the object type stored in the SdfData hash table. If no type has
2025     // been set, this path doesn't point to a valid location.
2026     *specType = GetSpecType(*absPath);
2027     return *specType != SdfSpecTypeUnknown;
2028 }
2029 
2030 template <class Spec>
2031 SdfHandle<Spec>
_GetSpecAtPath(const SdfPath & path)2032 SdfLayer::_GetSpecAtPath(const SdfPath& path)
2033 {
2034     SdfPath canonicalPath;
2035     SdfSpecType specType;
2036     if (!_CanGetSpecAtPath(path, &canonicalPath, &specType) ||
2037         !Sdf_SpecType::CanCast(specType, typeid(Spec))) {
2038         return TfNullPtr;
2039     }
2040 
2041     if (ARCH_UNLIKELY(!canonicalPath.IsEmpty())) {
2042         return SdfHandle<Spec>(_idRegistry.Identify(canonicalPath));
2043     }
2044     return SdfHandle<Spec>(_idRegistry.Identify(path));
2045 }
2046 
2047 SdfSpecHandle
GetObjectAtPath(const SdfPath & path)2048 SdfLayer::GetObjectAtPath(const SdfPath &path)
2049 {
2050     // This function is exactly the same as _GetSpecAtPath, but skips the
2051     // CanCast(...) check since all specs can be represented by SdfSpecHandles.
2052     // In addition, this avoids issues when dealing with things like
2053     // relationship target specs where an SdfSpecType value is defined, but
2054     // no C++ SdfSpec class exists. In that case, consumers should still be
2055     // able to get a generic SdfSpecHandle.
2056     SdfPath canonicalPath;
2057     SdfSpecType specType;
2058     if (!_CanGetSpecAtPath(path, &canonicalPath, &specType)) {
2059         return TfNullPtr;
2060     }
2061 
2062     if (ARCH_UNLIKELY(!canonicalPath.IsEmpty())) {
2063         return SdfSpecHandle(_idRegistry.Identify(canonicalPath));
2064     }
2065     return SdfSpecHandle(_idRegistry.Identify(path));
2066 }
2067 
2068 SdfPrimSpecHandle
GetPrimAtPath(const SdfPath & path)2069 SdfLayer::GetPrimAtPath(const SdfPath& path)
2070 {
2071     // Special-case attempts to look up the pseudo-root via this function.
2072     if (path == SdfPath::AbsoluteRootPath()) {
2073         return GetPseudoRoot();
2074     }
2075 
2076     return _GetSpecAtPath<SdfPrimSpec>(path);
2077 }
2078 
2079 SdfPropertySpecHandle
GetPropertyAtPath(const SdfPath & path)2080 SdfLayer::GetPropertyAtPath(const SdfPath &path)
2081 {
2082     return _GetSpecAtPath<SdfPropertySpec>(path);
2083 }
2084 
2085 SdfAttributeSpecHandle
GetAttributeAtPath(const SdfPath & path)2086 SdfLayer::GetAttributeAtPath(const SdfPath &path)
2087 {
2088     return _GetSpecAtPath<SdfAttributeSpec>(path);
2089 }
2090 
2091 SdfRelationshipSpecHandle
GetRelationshipAtPath(const SdfPath & path)2092 SdfLayer::GetRelationshipAtPath(const SdfPath &path)
2093 {
2094     return _GetSpecAtPath<SdfRelationshipSpec>(path);
2095 }
2096 
2097 bool
PermissionToEdit() const2098 SdfLayer::PermissionToEdit() const
2099 {
2100     return _permissionToEdit && !IsMuted();
2101 }
2102 
2103 bool
PermissionToSave() const2104 SdfLayer::PermissionToSave() const
2105 {
2106     return _permissionToSave &&
2107         !IsAnonymous() &&
2108         !IsMuted()     &&
2109         Sdf_CanWriteLayerToPath(GetResolvedPath());
2110 }
2111 
2112 void
SetPermissionToEdit(bool allow)2113 SdfLayer::SetPermissionToEdit(bool allow)
2114 {
2115     _permissionToEdit = allow;
2116 }
2117 
2118 void
SetPermissionToSave(bool allow)2119 SdfLayer::SetPermissionToSave(bool allow)
2120 {
2121     _permissionToSave = allow;
2122 }
2123 
2124 static
2125 bool
_HasObjectAtPath(const SdfLayerHandle & layer,const SdfPath & path)2126 _HasObjectAtPath(const SdfLayerHandle& layer, const SdfPath& path)
2127 {
2128     return layer->GetObjectAtPath(path);
2129 }
2130 
2131 static
2132 bool
_CanEdit(const SdfLayerHandle & layer,const SdfNamespaceEdit & edit,std::string * detail)2133 _CanEdit(
2134     const SdfLayerHandle& layer,
2135     const SdfNamespaceEdit& edit,
2136     std::string* detail)
2137 {
2138     if (edit.currentPath.IsPrimPath()) {
2139         if (edit.newPath.IsEmpty()) {
2140             // Remove prim child.
2141             return Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::
2142                     CanRemoveChildForBatchNamespaceEdit(
2143                         layer, edit.currentPath.GetParentPath(),
2144                         edit.currentPath.GetNameToken(),
2145                         detail);
2146         }
2147         else {
2148             // Insert prim child.
2149             return Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::
2150                     CanMoveChildForBatchNamespaceEdit(
2151                         layer, edit.newPath.GetParentPath(),
2152                         layer->GetPrimAtPath(edit.currentPath),
2153                         edit.newPath.GetNameToken(),
2154                         edit.index,
2155                         detail);
2156         }
2157     }
2158     else {
2159         if (edit.newPath.IsEmpty()) {
2160             if (edit.currentPath.IsRelationalAttributePath()) {
2161                 // Remove relational attribute.
2162                 return Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::
2163                         CanRemoveChildForBatchNamespaceEdit(
2164                             layer, edit.currentPath.GetParentPath(),
2165                             edit.currentPath.GetNameToken(),
2166                             detail);
2167             }
2168             else {
2169                 // Remove prim property.
2170                 return Sdf_ChildrenUtils<Sdf_PropertyChildPolicy>::
2171                         CanRemoveChildForBatchNamespaceEdit(
2172                             layer, edit.currentPath.GetParentPath(),
2173                             edit.currentPath.GetNameToken(),
2174                             detail);
2175             }
2176         }
2177         else if (edit.newPath.IsRelationalAttributePath()) {
2178             if (SdfAttributeSpecHandle attr =
2179                     layer->GetAttributeAtPath(edit.currentPath)) {
2180                 // Move a prim or relational attribute to be a relational
2181                 // attribute.
2182                 return Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::
2183                         CanMoveChildForBatchNamespaceEdit(
2184                             layer, edit.newPath.GetParentPath(),
2185                             attr,
2186                             edit.newPath.GetNameToken(),
2187                             edit.index,
2188                             detail);
2189             }
2190             else {
2191                 // Trying to make a non-attribute into a relational attribute.
2192                 if (detail) {
2193                     *detail = "Object is not an attribute";
2194                 }
2195                 return false;
2196             }
2197         }
2198         else {
2199             // Move a prim property or relational attribute to be a prim
2200             // property
2201             return Sdf_ChildrenUtils<Sdf_PropertyChildPolicy>::
2202                     CanMoveChildForBatchNamespaceEdit(
2203                         layer, edit.newPath.GetParentPath(),
2204                         layer->GetPropertyAtPath(edit.currentPath),
2205                         edit.newPath.GetNameToken(),
2206                         edit.index,
2207                         detail);
2208         }
2209     }
2210 }
2211 
2212 static
2213 void
_DoEdit(const SdfLayerHandle & layer,const SdfNamespaceEdit & edit)2214 _DoEdit(const SdfLayerHandle& layer, const SdfNamespaceEdit& edit)
2215 {
2216     if (edit.currentPath.IsPrimPath()) {
2217         if (edit.newPath.IsEmpty()) {
2218             // Remove prim child.
2219             Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::
2220                 RemoveChildForBatchNamespaceEdit(
2221                     layer, edit.currentPath.GetParentPath(),
2222                     edit.currentPath.GetNameToken());
2223         }
2224         else {
2225             // Insert prim child.
2226             Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::
2227                 MoveChildForBatchNamespaceEdit(
2228                     layer, edit.newPath.GetParentPath(),
2229                     layer->GetPrimAtPath(edit.currentPath),
2230                     edit.newPath.GetNameToken(),
2231                     edit.index);
2232         }
2233     }
2234     else {
2235         if (edit.newPath.IsEmpty()) {
2236             if (edit.currentPath.IsRelationalAttributePath()) {
2237                 // Remove relational attribute.
2238                 Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::
2239                     RemoveChildForBatchNamespaceEdit(
2240                         layer, edit.currentPath.GetParentPath(),
2241                         edit.currentPath.GetNameToken());
2242             }
2243             else {
2244                 // Remove prim property.
2245                 Sdf_ChildrenUtils<Sdf_PropertyChildPolicy>::
2246                     RemoveChildForBatchNamespaceEdit(
2247                         layer, edit.currentPath.GetParentPath(),
2248                         edit.currentPath.GetNameToken());
2249             }
2250         }
2251         else {
2252             if (edit.newPath.IsRelationalAttributePath()) {
2253                 // Move a prim or relational attribute to be a relational
2254                 // attribute.
2255                 Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::
2256                     MoveChildForBatchNamespaceEdit(
2257                         layer, edit.newPath.GetParentPath(),
2258                         layer->GetAttributeAtPath(edit.currentPath),
2259                         edit.newPath.GetNameToken(),
2260                         edit.index);
2261             }
2262             else {
2263                 // Move a prim property or relational attribute to be a prim
2264                 // property
2265                 Sdf_ChildrenUtils<Sdf_PropertyChildPolicy>::
2266                     MoveChildForBatchNamespaceEdit(
2267                         layer, edit.newPath.GetParentPath(),
2268                         layer->GetPropertyAtPath(edit.currentPath),
2269                         edit.newPath.GetNameToken(),
2270                         edit.index);
2271             }
2272         }
2273     }
2274 }
2275 
2276 SdfNamespaceEditDetail::Result
CanApply(const SdfBatchNamespaceEdit & edits,SdfNamespaceEditDetailVector * details) const2277 SdfLayer::CanApply(
2278     const SdfBatchNamespaceEdit& edits,
2279     SdfNamespaceEditDetailVector* details) const
2280 {
2281     SdfNamespaceEditDetail::Result result = SdfNamespaceEditDetail::Okay;
2282 
2283     static const bool fixBackpointers = true;
2284     if (!edits.Process(NULL,
2285                        std::bind(&_HasObjectAtPath, _self, ph::_1),
2286                        std::bind(&_CanEdit, _self, ph::_1, ph::_2),
2287                        details, !fixBackpointers)) {
2288         result = CombineError(result);
2289     }
2290 
2291     return result;
2292 }
2293 
2294 bool
Apply(const SdfBatchNamespaceEdit & edits)2295 SdfLayer::Apply(const SdfBatchNamespaceEdit& edits)
2296 {
2297     if (!PermissionToEdit()) {
2298         return false;
2299     }
2300 
2301     static const bool fixBackpointers = true;
2302     SdfNamespaceEditVector final;
2303     if (!edits.Process(&final,
2304                        std::bind(&_HasObjectAtPath, _self, ph::_1),
2305                        std::bind(&_CanEdit, _self, ph::_1, ph::_2),
2306                        NULL, !fixBackpointers)) {
2307         return false;
2308     }
2309 
2310     SdfChangeBlock block;
2311     for (const auto& edit : final) {
2312         _DoEdit(_self, edit);
2313     }
2314 
2315     return true;
2316 }
2317 
2318 void
ScheduleRemoveIfInert(const SdfSpec & spec)2319 SdfLayer::ScheduleRemoveIfInert(const SdfSpec& spec)
2320 {
2321     Sdf_ChangeManager::Get().RemoveSpecIfInert(spec);
2322 }
2323 
2324 void
_RemoveIfInert(const SdfSpec & spec)2325 SdfLayer::_RemoveIfInert(const SdfSpec& spec)
2326 {
2327     if (!spec.IsDormant()) {
2328         SdfSpecHandle specHandle(spec);
2329         if (SdfPrimSpecHandle prim =
2330             TfDynamic_cast<SdfPrimSpecHandle>(specHandle)) {
2331             // We only want to call RemovePrimIfInert if the prim itself is
2332             // inert because RemovePrimIfInert first removes any inert children
2333             // before checking if the prim is inert, but we don't want to touch
2334             // the children. We only want to concern ourselves with the
2335             // specified spec without modifying its children first.
2336             if (prim->IsInert()) {
2337                 RemovePrimIfInert(prim);
2338             }
2339         }
2340         else if(SdfPropertySpecHandle property =
2341                 TfDynamic_cast<SdfPropertySpecHandle>(specHandle)) {
2342 
2343             RemovePropertyIfHasOnlyRequiredFields(property);
2344         }
2345     }
2346 }
2347 
2348 void
RemovePrimIfInert(SdfPrimSpecHandle prim)2349 SdfLayer::RemovePrimIfInert(SdfPrimSpecHandle prim)
2350 {
2351     if (prim && _RemoveInertDFS(prim))
2352         _RemoveInertToRootmost(prim);
2353 }
2354 
2355 void
RemovePropertyIfHasOnlyRequiredFields(SdfPropertySpecHandle prop)2356 SdfLayer::RemovePropertyIfHasOnlyRequiredFields(SdfPropertySpecHandle prop)
2357 {
2358     if (!(prop && prop->HasOnlyRequiredFields()))
2359         return;
2360 
2361     if (SdfPrimSpecHandle owner =
2362         TfDynamic_cast<SdfPrimSpecHandle>(prop->GetOwner())) {
2363 
2364         owner->RemoveProperty(prop);
2365         _RemoveInertToRootmost(owner);
2366 
2367     }
2368     else if (SdfAttributeSpecHandle attr =
2369              TfDynamic_cast<SdfAttributeSpecHandle>(prop)) {
2370         Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::RemoveChild(
2371             _self, attr->GetPath().GetParentPath(), attr->GetNameToken());
2372     }
2373     else if (SdfRelationshipSpecHandle rel =
2374              TfDynamic_cast<SdfRelationshipSpecHandle>(prop)) {
2375         Sdf_ChildrenUtils<Sdf_RelationshipChildPolicy>::RemoveChild(
2376             _self, rel->GetPath().GetParentPath(), rel->GetNameToken());
2377     }
2378     //XXX: We may want to do something like
2379     //     _RemoveInertToRootmost here, but that would currently
2380     //     exacerbate bug 23878. Until we have  a solution for that bug,
2381     //     we won't automatically clean up our parents in this case.
2382 }
2383 
2384 void
RemoveInertSceneDescription()2385 SdfLayer::RemoveInertSceneDescription()
2386 {
2387     SdfChangeBlock block;
2388 
2389     _RemoveInertDFS(GetPseudoRoot());
2390 }
2391 
2392 bool
_RemoveInertDFS(SdfPrimSpecHandle prim)2393 SdfLayer::_RemoveInertDFS(SdfPrimSpecHandle prim)
2394 {
2395     bool inert = prim->IsInert();
2396 
2397     if (!inert) {
2398         // Child prims
2399         SdfPrimSpecHandleVector removedChildren;
2400         TF_FOR_ALL(it, prim->GetNameChildren()) {
2401             SdfPrimSpecHandle child = *it;
2402             if (_RemoveInertDFS(child) &&
2403                 !SdfIsDefiningSpecifier(child->GetSpecifier()))
2404                 removedChildren.push_back(child);
2405         }
2406         TF_FOR_ALL(it, removedChildren) {
2407             prim->RemoveNameChild(*it);
2408         }
2409         // Child prims inside variants
2410         SdfVariantSetsProxy variantSetMap = prim->GetVariantSets();
2411         TF_FOR_ALL(varSetIt, variantSetMap) {
2412             const SdfVariantSetSpecHandle &varSetSpec = varSetIt->second;
2413             const SdfVariantSpecHandleVector &variants =
2414                 varSetSpec->GetVariantList();
2415             TF_FOR_ALL(varIt, variants) {
2416                 _RemoveInertDFS((*varIt)->GetPrimSpec());
2417             }
2418         }
2419     }
2420 
2421     return inert ? inert : prim->IsInert();
2422 }
2423 
2424 void
_RemoveInertToRootmost(SdfPrimSpecHandle prim)2425 SdfLayer::_RemoveInertToRootmost(SdfPrimSpecHandle prim)
2426 {
2427     while (prim &&
2428            !SdfIsDefiningSpecifier(prim->GetSpecifier()) &&
2429            prim->IsInert()) {
2430         SdfPrimSpecHandle parent = prim->GetRealNameParent();
2431         if (parent) {
2432             parent->RemoveNameChild(prim);
2433         }
2434 
2435         // Recurse.
2436         prim = parent;
2437     }
2438 }
2439 
2440 bool
SplitIdentifier(const string & identifier,string * layerPath,FileFormatArguments * arguments)2441 SdfLayer::SplitIdentifier(
2442     const string& identifier,
2443     string* layerPath,
2444     FileFormatArguments* arguments)
2445 {
2446     return Sdf_SplitIdentifier(identifier, layerPath, arguments);
2447 }
2448 
2449 std::string
CreateIdentifier(const string & layerPath,const FileFormatArguments & arguments)2450 SdfLayer::CreateIdentifier(
2451     const string& layerPath,
2452     const FileFormatArguments& arguments)
2453 {
2454     return Sdf_CreateIdentifier(layerPath, arguments);
2455 }
2456 
2457 const string&
GetIdentifier() const2458 SdfLayer::GetIdentifier() const
2459 {
2460     return _assetInfo->identifier;
2461 }
2462 
2463 void
SetIdentifier(const string & identifier)2464 SdfLayer::SetIdentifier(const string &identifier)
2465 {
2466     TRACE_FUNCTION();
2467     TF_DEBUG(SDF_LAYER).Msg(
2468         "SdfLayer::SetIdentifier('%s')\n",
2469         identifier.c_str());
2470 
2471     string oldLayerPath;
2472     SdfLayer::FileFormatArguments oldArguments;
2473     if (!TF_VERIFY(Sdf_SplitIdentifier(
2474             GetIdentifier(), &oldLayerPath, &oldArguments))) {
2475         return;
2476     }
2477 
2478     string newLayerPath;
2479     SdfLayer::FileFormatArguments newArguments;
2480     if (!Sdf_SplitIdentifier(identifier, &newLayerPath, &newArguments)) {
2481         TF_CODING_ERROR("Invalid identifier '%s'", identifier.c_str());
2482         return;
2483     }
2484 
2485     if (oldArguments != newArguments) {
2486         TF_CODING_ERROR(
2487             "Identifier '%s' contains arguments that differ from the layer's "
2488             "current arguments ('%s').",
2489             identifier.c_str(), GetIdentifier().c_str());
2490         return;
2491     }
2492 
2493     string whyNot;
2494     if (!Sdf_CanCreateNewLayerWithIdentifier(newLayerPath, &whyNot)) {
2495         TF_CODING_ERROR("Cannot change identifier to '%s': %s",
2496             identifier.c_str(), whyNot.c_str());
2497         return;
2498     }
2499 
2500 #if AR_VERSION == 1
2501     // When changing a layer's identifier, assume that relative identifiers are
2502     // relative to the current working directory.
2503     const string absIdentifier = ArGetResolver().IsRelativePath(identifier) ?
2504         TfAbsPath(identifier) : identifier;
2505 #else
2506     // Create an identifier for the layer based on the desired identifier
2507     // that was passed in. Since this may identifier may point to an asset
2508     // that doesn't exist yet, use CreateIdentifierForNewAsset.
2509     newLayerPath = ArGetResolver().CreateIdentifierForNewAsset(newLayerPath);
2510     const string absIdentifier =
2511         Sdf_CreateIdentifier(newLayerPath, newArguments);
2512 #endif
2513     const ArResolvedPath oldResolvedPath = GetResolvedPath();
2514 
2515     // Hold open a change block to defer identifier-did-change
2516     // notification until the mutex is unlocked.
2517     SdfChangeBlock block;
2518 
2519     {
2520         tbb::queuing_rw_mutex::scoped_lock lock;
2521 
2522         // See if another layer with the same identifier exists in the registry.
2523         // If it doesn't, we will be updating the registry so we need to ensure
2524         // our lock is upgraded to a write lock by setting retryAsWriter = true.
2525         //
2526         // It is possible that the call to _Find returns the same layer we're
2527         // modifying. For example, if a layer was originally opened using some
2528         // path and we're now trying to set its identifier to something that
2529         // resolves to that same path. In this case, we don't want to error
2530         // out.
2531         const bool retryAsWriter = true;
2532         SdfLayerRefPtr existingLayer = _Find(
2533             absIdentifier, FileFormatArguments(), lock, retryAsWriter);
2534         if (existingLayer) {
2535             if (get_pointer(existingLayer) != this) {
2536                 TF_CODING_ERROR(
2537                     "Layer with identifier '%s' and resolved path '%s' exists.",
2538                     existingLayer->GetIdentifier().c_str(),
2539                     existingLayer->GetResolvedPath().GetPathString().c_str());
2540                 return;
2541             }
2542         }
2543 
2544         // We should have acquired a write lock on the layer registry by this
2545         // point, so it's safe to call _InitializeFromIdentifier.
2546         _InitializeFromIdentifier(absIdentifier);
2547     }
2548 
2549     // If this layer has changed where it's stored, reset the modification
2550     // time. Note that the new identifier may not resolve to an existing
2551     // location, and we get an empty timestamp from the resolver.
2552     // This is OK -- this means the layer hasn't been serialized to this
2553     // new location yet.
2554     const ArResolvedPath newResolvedPath = GetResolvedPath();
2555     if (oldResolvedPath != newResolvedPath) {
2556 #if AR_VERSION == 1
2557         _assetModificationTime = ArGetResolver().GetModificationTimestamp(
2558             GetIdentifier(), newResolvedPath);
2559 #else
2560         const ArTimestamp timestamp = ArGetResolver().GetModificationTimestamp(
2561             newLayerPath, newResolvedPath);
2562         _assetModificationTime =
2563             (timestamp.IsValid() || Sdf_ResolvePath(newLayerPath)) ?
2564             VtValue(timestamp) : VtValue();
2565 #endif
2566     }
2567 }
2568 
2569 #if AR_VERSION == 1
2570 
2571 void
UpdateAssetInfo(const string & fileVersion)2572 SdfLayer::UpdateAssetInfo(const string &fileVersion)
2573 {
2574     TRACE_FUNCTION();
2575     TF_DEBUG(SDF_LAYER).Msg(
2576         "SdfLayer::UpdateAssetInfo('%s')\n",
2577         fileVersion.c_str());
2578 
2579     // Hold open a change block to defer identifier-did-change
2580     // notification until the mutex is unlocked.
2581     SdfChangeBlock block;
2582     {
2583         // If the layer has a resolve info with a non-empty asset name, this
2584         // means that the layer identifier is a search-path to a layer within
2585         // an asset, which last resolved to a pinnable location. Bind the
2586         // original context found in the resolve info within this block so the
2587         // layer's search path identifier can be properly re-resolved within
2588         // _InitializeFromIdentifier.
2589         std::unique_ptr<ArResolverContextBinder> binder;
2590         if (!GetAssetName().empty()) {
2591             binder.reset(new ArResolverContextBinder(
2592                     _assetInfo->resolverContext));
2593         }
2594 
2595         tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
2596         _InitializeFromIdentifier(GetIdentifier(),
2597             /* realPath */ std::string(), fileVersion);
2598     }
2599 }
2600 
2601 #else
2602 
2603 void
UpdateAssetInfo()2604 SdfLayer::UpdateAssetInfo()
2605 {
2606     TRACE_FUNCTION();
2607     TF_DEBUG(SDF_LAYER).Msg("SdfLayer::UpdateAssetInfo()\n");
2608 
2609     // Hold open a change block to defer identifier-did-change
2610     // notification until the mutex is unlocked.
2611     SdfChangeBlock block;
2612     {
2613         // If the layer has a resolve info with a non-empty asset name, this
2614         // means that the layer identifier is a search-path to a layer within
2615         // an asset, which last resolved to a pinnable location. Bind the
2616         // original context found in the resolve info within this block so the
2617         // layer's search path identifier can be properly re-resolved within
2618         // _InitializeFromIdentifier.
2619         std::unique_ptr<ArResolverContextBinder> binder;
2620         if (!GetAssetName().empty()) {
2621             binder.reset(new ArResolverContextBinder(
2622                     _assetInfo->resolverContext));
2623         }
2624 
2625         tbb::queuing_rw_mutex::scoped_lock lock(_GetLayerRegistryMutex());
2626         _InitializeFromIdentifier(GetIdentifier());
2627     }
2628 }
2629 
2630 #endif // AR_VERSION
2631 
2632 string
GetDisplayName() const2633 SdfLayer::GetDisplayName() const
2634 {
2635     return GetDisplayNameFromIdentifier(GetIdentifier());
2636 }
2637 
2638 const ArResolvedPath&
GetResolvedPath() const2639 SdfLayer::GetResolvedPath() const
2640 {
2641     return _assetInfo->resolvedPath;
2642 }
2643 
2644 const string&
GetRealPath() const2645 SdfLayer::GetRealPath() const
2646 {
2647     return _assetInfo->resolvedPath.GetPathString();
2648 }
2649 
2650 string
GetFileExtension() const2651 SdfLayer::GetFileExtension() const
2652 {
2653     string ext = Sdf_GetExtension(GetRealPath());
2654 
2655     if (ext.empty())
2656         ext = GetFileFormat()->GetPrimaryFileExtension();
2657 
2658     return ext;
2659 }
2660 
2661 const string&
GetRepositoryPath() const2662 SdfLayer::GetRepositoryPath() const
2663 {
2664     return _assetInfo->assetInfo.repoPath;
2665 }
2666 
2667 const string&
GetVersion() const2668 SdfLayer::GetVersion() const
2669 {
2670     return _assetInfo->assetInfo.version;
2671 }
2672 
2673 const VtValue&
GetAssetInfo() const2674 SdfLayer::GetAssetInfo() const
2675 {
2676     return _assetInfo->assetInfo.resolverInfo;
2677 }
2678 
2679 const string&
GetAssetName() const2680 SdfLayer::GetAssetName() const
2681 {
2682     return _assetInfo->assetInfo.assetName;
2683 }
2684 
2685 SdfLayerHints
GetHints() const2686 SdfLayer::GetHints() const
2687 {
2688     // Hints are invalidated by any authoring operation but we don't want to
2689     // incur the cost of resetting the _hints object at authoring time.
2690     // Instead, we return a default SdfLayerHints here if the layer is dirty.
2691     return IsDirty() ? SdfLayerHints{} : _hints;
2692 }
2693 
2694 SdfDataRefPtr
GetMetadata() const2695 SdfLayer::GetMetadata() const
2696 {
2697     SdfDataRefPtr result = TfCreateRefPtr(new SdfData);
2698     SdfPath const &absRoot = SdfPath::AbsoluteRootPath();
2699 
2700     // The metadata for this layer is the data at the absolute root path.
2701     // Here, we copy it into 'result'.
2702     //
2703     // XXX: This is copying more than just the metadata. This includes things
2704     //      like name children, etc. We should probably be filtering this to
2705     //      just fields tagged as metadata in the schema.
2706     result->CreateSpec(absRoot, SdfSpecTypePseudoRoot);
2707     const TfTokenVector tokenVec = ListFields(absRoot);
2708     for (auto const &token : tokenVec) {
2709         const VtValue &value = GetField(absRoot, token);
2710         result->Set(absRoot, token, value);
2711     }
2712 
2713     return result;
2714 }
2715 
2716 string
ComputeAbsolutePath(const string & assetPath) const2717 SdfLayer::ComputeAbsolutePath(const string& assetPath) const
2718 {
2719     if (assetPath.empty()
2720         || Sdf_IsAnonLayerIdentifier(assetPath)) {
2721         return assetPath;
2722     }
2723 
2724 #if AR_VERSION == 1
2725     // Make it relative to the repository path, if available, so that path
2726     // resolution will work for references.
2727     const string relativeToPath = GetRepositoryPath().empty() ?
2728         GetRealPath() : GetRepositoryPath();
2729     return ArGetResolver().AnchorRelativePath(relativeToPath, assetPath);
2730 #else
2731     return SdfComputeAssetPathRelativeToLayer(
2732         SdfCreateNonConstHandle(this), assetPath);
2733 #endif
2734 }
2735 
2736 string
_GetMutedPath() const2737 SdfLayer::_GetMutedPath() const
2738 {
2739     return GetRepositoryPath().empty()
2740            ? GetIdentifier()
2741            : GetRepositoryPath();
2742 }
2743 
2744 set<string>
GetMutedLayers()2745 SdfLayer::GetMutedLayers()
2746 {
2747     std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2748     return *_mutedLayers;
2749 }
2750 
2751 void
SetMuted(bool muted)2752 SdfLayer::SetMuted(bool muted)
2753 {
2754     // XXX Racy...
2755 
2756     if (muted == IsMuted()) {
2757         return;
2758     }
2759 
2760     if (muted) {
2761         AddToMutedLayers(_GetMutedPath());
2762     }
2763     else {
2764         RemoveFromMutedLayers(_GetMutedPath());
2765     }
2766 }
2767 
2768 bool
IsMuted() const2769 SdfLayer::IsMuted() const
2770 {
2771     // Read the current muted revision number.  If it's up-to-date we return our
2772     // cache.  It's possible that this is racy, but the whole thing is racy
2773     // regardless.  Even with a pure locking implementation, say we found this
2774     // layer in the muted set -- by the time we return to the caller with
2775     // 'true', some other thread may have removed this layer from the muted set.
2776 
2777     size_t curRev = _mutedLayersRevision;
2778     if (ARCH_UNLIKELY(_mutedLayersRevisionCache != curRev)) {
2779         string mutedPath = _GetMutedPath();
2780         std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2781         // Read again, since this is guaranteed to give us the current value
2782         // because we have the lock.  _mutedLayersRevision only changes with the
2783         // lock held.
2784         _mutedLayersRevisionCache = _mutedLayersRevision;
2785         _isMutedCache = _mutedLayers->count(mutedPath);
2786     }
2787 
2788     return _isMutedCache;
2789 }
2790 
2791 /*static*/
2792 bool
IsMuted(const string & path)2793 SdfLayer::IsMuted(const string &path)
2794 {
2795     std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2796     return _mutedLayers->count(path);
2797 }
2798 
2799 /*static*/
2800 void
AddToMutedLayers(const string & path)2801 SdfLayer::AddToMutedLayers(const string &path)
2802 {
2803     bool didChange = false;
2804     {
2805         // Racy...
2806         std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2807         ++_mutedLayersRevision;
2808         didChange = _mutedLayers->insert(path).second;
2809     }
2810     if (didChange) {
2811         if (SdfLayerHandle layer = Find(path)) {
2812             if (layer->IsDirty()) {
2813                 SdfFileFormatConstPtr format = layer->GetFileFormat();
2814                 SdfAbstractDataRefPtr initializedData =
2815                     format->InitData(layer->GetFileFormatArguments());
2816                 if (layer->_data->StreamsData()) {
2817                     // See the discussion in TransferContent()
2818                     // about streaming layers; the same concerns
2819                     // apply here.  We must swap out the actual data
2820                     // ownership and tell clients the entire data
2821                     // store has changed.
2822                     {
2823                         std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2824                         TF_VERIFY((*_mutedLayerData).find(path) ==
2825                                   (*_mutedLayerData).end());
2826                         (*_mutedLayerData)[path] = layer->_data;
2827                     }
2828                     // _SetData() takes ownership of initializedData and sends
2829                     // change notification.
2830                     layer->_SetData(initializedData);
2831                 } else {
2832                     // Copy the dirty layer data to an in-memory store
2833                     // that will be owned by _mutedLayerData.
2834                     SdfAbstractDataRefPtr mutedData =
2835                         format->InitData(layer->GetFileFormatArguments());
2836                     mutedData->CopyFrom(layer->_data);
2837                     {
2838                         std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2839                         TF_VERIFY((*_mutedLayerData).find(path) ==
2840                                   (*_mutedLayerData).end());
2841                         std::swap( (*_mutedLayerData)[path], mutedData );
2842                     }
2843                     // Mutate the layer's data to the initialized state.
2844                     // This enables efficient change processing downstream.
2845                     layer->_SetData(initializedData);
2846                 }
2847                 TF_VERIFY(layer->IsDirty());
2848             } else {
2849                 // Reload as muted.
2850                 layer->_Reload(/* force */ true);
2851             }
2852         }
2853         SdfNotice::LayerMutenessChanged(path, /* wasMuted = */ true).Send();
2854     }
2855 }
2856 
2857 /*static*/
2858 void
RemoveFromMutedLayers(const string & path)2859 SdfLayer::RemoveFromMutedLayers(const string &path)
2860 {
2861     bool didChange = false;
2862     {
2863         // Racy...
2864         std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2865         ++_mutedLayersRevision;
2866         didChange = _mutedLayers->erase(path);
2867     }
2868     if (didChange) {
2869         if (SdfLayerHandle layer = Find(path)) {
2870             if (layer->IsDirty()) {
2871                 SdfAbstractDataRefPtr mutedData;
2872                 {
2873                     std::lock_guard<std::mutex> lock(*_mutedLayersMutex);
2874                     _MutedLayerDataMap::iterator i =
2875                         _mutedLayerData->find(path);
2876                     if (TF_VERIFY(i != _mutedLayerData->end())) {
2877                         std::swap(mutedData, i->second);
2878                         _mutedLayerData->erase(i);
2879                     }
2880                 }
2881                 if (TF_VERIFY(mutedData)) {
2882                     // If SdfAbstractData::StreamsData() is true, this re-takes
2883                     // ownership of the mutedData object.  Otherwise, this
2884                     // mutates the existing data container to match its
2885                     // contents.
2886                     layer->_SetData(mutedData);
2887                 }
2888                 TF_VERIFY(layer->IsDirty());
2889             } else {
2890                 // Reload as unmuted.
2891                 layer->_Reload(/* force */ true);
2892             }
2893         }
2894         SdfNotice::LayerMutenessChanged(path, /* wasMuted = */ false).Send();
2895     }
2896 }
2897 
2898 bool
_ShouldNotify() const2899 SdfLayer::_ShouldNotify() const
2900 {
2901     // Only notify if this layer has been successfully initialized.
2902     // (If initialization is not yet complete, do not notify.)
2903     return _initializationWasSuccessful.get_value_or(false);
2904 }
2905 
2906 void
Clear()2907 SdfLayer::Clear()
2908 {
2909     if (!PermissionToEdit()) {
2910         TF_CODING_ERROR("Clear: Permission denied.");
2911         return;
2912     }
2913 
2914     const bool isStreamingLayer = _data->StreamsData();
2915 
2916     _SetData(GetFileFormat()->InitData(GetFileFormatArguments()));
2917 
2918     if (isStreamingLayer) {
2919         _stateDelegate->_MarkCurrentStateAsDirty();
2920     }
2921 }
2922 
2923 bool
IsDirty() const2924 SdfLayer::IsDirty() const
2925 {
2926     return (TF_VERIFY(_stateDelegate) ? _stateDelegate->IsDirty() : false);
2927 }
2928 
2929 bool
_UpdateLastDirtinessState() const2930 SdfLayer::_UpdateLastDirtinessState() const
2931 {
2932     // Did not change since last call...
2933     if (IsDirty() == _lastDirtyState)
2934         return false;
2935 
2936     // It did change, update last saved changed state...
2937     _lastDirtyState = IsDirty();
2938 
2939     return true;
2940 }
2941 
2942 SdfLayerStateDelegateBasePtr
GetStateDelegate() const2943 SdfLayer::GetStateDelegate() const
2944 {
2945     return _stateDelegate;
2946 }
2947 
2948 void
SetStateDelegate(const SdfLayerStateDelegateBaseRefPtr & delegate)2949 SdfLayer::SetStateDelegate(const SdfLayerStateDelegateBaseRefPtr& delegate)
2950 {
2951     // A layer can never have an invalid state delegate, as it relies
2952     // on it to track dirtiness.
2953     if (!delegate) {
2954         TF_CODING_ERROR("Invalid layer state delegate");
2955         return;
2956     }
2957 
2958     _stateDelegate->_SetLayer(SdfLayerHandle());
2959     _stateDelegate = delegate;
2960     _stateDelegate->_SetLayer(_self);
2961 
2962     if (_lastDirtyState) {
2963         _stateDelegate->_MarkCurrentStateAsDirty();
2964     }
2965     else {
2966         _stateDelegate->_MarkCurrentStateAsClean();
2967     }
2968 }
2969 
2970 void
_MarkCurrentStateAsClean() const2971 SdfLayer::_MarkCurrentStateAsClean() const
2972 {
2973     if (TF_VERIFY(_stateDelegate)) {
2974         _stateDelegate->_MarkCurrentStateAsClean();
2975     }
2976 
2977     if (_UpdateLastDirtinessState()) {
2978         SdfNotice::LayerDirtinessChanged().Send(_self);
2979     }
2980 }
2981 
2982 bool
IsEmpty() const2983 SdfLayer::IsEmpty() const
2984 {
2985     // XXX: What about documentation/frames?  I don't
2986     // think these get composed or exposed through composition, so I don't think
2987     // they matter for the sake of this query.
2988     return GetRootPrims().empty()  &&
2989         GetRootPrimOrder().empty() &&
2990         GetSubLayerPaths().empty();
2991 }
2992 
2993 void
TransferContent(const SdfLayerHandle & layer)2994 SdfLayer::TransferContent(const SdfLayerHandle& layer)
2995 {
2996     if (!PermissionToEdit()) {
2997         TF_RUNTIME_ERROR("TransferContent of '%s': Permission denied.",
2998                          GetDisplayName().c_str());
2999         return;
3000     }
3001 
3002     // Two concerns apply here:
3003     //
3004     // If we need to notify about the changes, we need to use the
3005     // _SetData() API to get incremental change notification;
3006     // otherwise we can just blindly copy the SdfAbstractData.
3007     //
3008     // If this is a streaming layer, _SetData will simply take
3009     // ownership of the data object passed to it. We don't want
3010     // multiple layers to be sharing the same data object, so we
3011     // have to make a copy of the data here.
3012     //
3013 
3014     bool notify = _ShouldNotify();
3015     bool isStreamingLayer = _data->StreamsData();
3016     SdfAbstractDataRefPtr newData;
3017 
3018     if (!notify || isStreamingLayer) {
3019         newData = GetFileFormat()->InitData(GetFileFormatArguments());
3020         newData->CopyFrom(layer->_data);
3021     }
3022     else {
3023         newData = layer->_data;
3024     }
3025 
3026     if (notify) {
3027         _SetData(newData, &(layer->GetSchema()));
3028     } else {
3029         _data = newData;
3030     }
3031 
3032     // Copy hints from other layer
3033     _hints = layer->_hints;
3034 
3035     // If this is a "streaming" layer, we must mark it dirty.
3036     if (isStreamingLayer) {
3037         _stateDelegate->_MarkCurrentStateAsDirty();
3038     }
3039 }
3040 
3041 static void
_GatherPrimCompositionDependencies(const SdfPrimSpecHandle & prim,set<string> * assetReferences)3042 _GatherPrimCompositionDependencies(const SdfPrimSpecHandle &prim,
3043                                    set<string> *assetReferences)
3044 {
3045     if (prim != prim->GetLayer()->GetPseudoRoot()) {
3046         // Prim references
3047         for (const SdfReference &ref:
3048              prim->GetReferenceList().GetAddedOrExplicitItems()) {
3049             assetReferences->insert(ref.GetAssetPath());
3050         }
3051 
3052         // Prim payloads
3053         for (const SdfPayload &payload:
3054              prim->GetPayloadList().GetAddedOrExplicitItems()) {
3055             assetReferences->insert(payload.GetAssetPath());
3056         }
3057 
3058         // Prim variants
3059         SdfVariantSetsProxy variantSetMap = prim->GetVariantSets();
3060         for (const auto &varSetIt: variantSetMap) {
3061             const SdfVariantSetSpecHandle &varSetSpec = varSetIt.second;
3062             const SdfVariantSpecHandleVector &variants =
3063                 varSetSpec->GetVariantList();
3064             for(const SdfVariantSpecHandle &varSpec : variants) {
3065                 _GatherPrimCompositionDependencies(
3066                     varSpec->GetPrimSpec(), assetReferences );
3067             }
3068         }
3069     }
3070 
3071     // Recurse on nameChildren
3072     for (const SdfPrimSpecHandle &child : prim->GetNameChildren()) {
3073         _GatherPrimCompositionDependencies(child, assetReferences);
3074     }
3075 }
3076 
3077 set<string>
GetExternalReferences() const3078 SdfLayer::GetExternalReferences() const
3079 {
3080     return GetCompositionAssetDependencies();
3081 }
3082 
3083 bool
UpdateExternalReference(const string & oldLayerPath,const string & newLayerPath)3084 SdfLayer::UpdateExternalReference(
3085     const string &oldLayerPath,
3086     const string &newLayerPath)
3087 {
3088     return UpdateCompositionAssetDependency(oldLayerPath, newLayerPath);
3089 }
3090 
3091 set<string>
GetCompositionAssetDependencies() const3092 SdfLayer::GetCompositionAssetDependencies() const
3093 {
3094     SdfSubLayerProxy subLayers = GetSubLayerPaths();
3095 
3096     set<string> results(subLayers.begin(), subLayers.end());
3097 
3098     _GatherPrimCompositionDependencies(GetPseudoRoot(), &results);
3099 
3100     return results;
3101 }
3102 
3103 bool
UpdateCompositionAssetDependency(const string & oldLayerPath,const string & newLayerPath)3104 SdfLayer::UpdateCompositionAssetDependency(
3105     const string &oldLayerPath,
3106     const string &newLayerPath)
3107 {
3108     if (oldLayerPath.empty())
3109         return false;
3110 
3111     // Search sublayers and rename if found...
3112     SdfSubLayerProxy subLayers = GetSubLayerPaths();
3113     size_t index = subLayers.Find(oldLayerPath);
3114     if (index != (size_t)-1) {
3115         RemoveSubLayerPath(index);
3116 
3117         // If new layer path given, do rename, otherwise it's a delete.
3118         if (!newLayerPath.empty()) {
3119             InsertSubLayerPath(newLayerPath, index);
3120         }
3121 
3122         return true; // sublayers are unique, do no more...
3123     }
3124 
3125     _UpdatePrimCompositionDependencyPaths(
3126         GetPseudoRoot(), oldLayerPath, newLayerPath);
3127 
3128     return true;
3129 }
3130 
3131 
3132 std::set<std::string>
GetExternalAssetDependencies() const3133 SdfLayer::GetExternalAssetDependencies() const
3134 {
3135     return _fileFormat->GetExternalAssetDependencies(*this);
3136 }
3137 
3138 // ModifyItemEdits() callback that updates a reference's or payload's
3139 // asset path for SdfReferenceListEditor and SdfPayloadListEditor.
3140 template <class RefOrPayloadType>
3141 static boost::optional<RefOrPayloadType>
_UpdateRefOrPayloadPath(const string & oldLayerPath,const string & newLayerPath,const RefOrPayloadType & refOrPayload)3142 _UpdateRefOrPayloadPath(
3143     const string &oldLayerPath,
3144     const string &newLayerPath,
3145     const RefOrPayloadType &refOrPayload)
3146 {
3147     if (refOrPayload.GetAssetPath() == oldLayerPath) {
3148         // Delete if new layer path is empty, otherwise rename.
3149         if (newLayerPath.empty()) {
3150             return boost::optional<RefOrPayloadType>();
3151         } else {
3152             RefOrPayloadType updatedRefOrPayload = refOrPayload;
3153             updatedRefOrPayload.SetAssetPath(newLayerPath);
3154             return updatedRefOrPayload;
3155         }
3156     }
3157     return refOrPayload;
3158 }
3159 
3160 void
_UpdatePrimCompositionDependencyPaths(const SdfPrimSpecHandle & prim,const string & oldLayerPath,const string & newLayerPath)3161 SdfLayer::_UpdatePrimCompositionDependencyPaths(
3162     const SdfPrimSpecHandle &prim,
3163     const string &oldLayerPath,
3164     const string &newLayerPath)
3165 {
3166     TF_AXIOM(!oldLayerPath.empty());
3167 
3168     // Prim references
3169     prim->GetReferenceList().ModifyItemEdits(std::bind(
3170         &_UpdateRefOrPayloadPath<SdfReference>, oldLayerPath, newLayerPath,
3171         ph::_1));
3172 
3173     // Prim payloads
3174     prim->GetPayloadList().ModifyItemEdits(std::bind(
3175         &_UpdateRefOrPayloadPath<SdfPayload>, oldLayerPath, newLayerPath,
3176         ph::_1));
3177 
3178     // Prim variants
3179     SdfVariantSetsProxy variantSetMap = prim->GetVariantSets();
3180     for (const auto& setNameAndSpec : variantSetMap) {
3181         const SdfVariantSetSpecHandle &varSetSpec = setNameAndSpec.second;
3182         const SdfVariantSpecHandleVector &variants =
3183             varSetSpec->GetVariantList();
3184         for (const auto& variantSpec : variants) {
3185             _UpdatePrimCompositionDependencyPaths(
3186                 variantSpec->GetPrimSpec(), oldLayerPath, newLayerPath);
3187         }
3188     }
3189 
3190     // Recurse on nameChildren
3191     for (const auto& primSpec : prim->GetNameChildren()) {
3192         _UpdatePrimCompositionDependencyPaths(
3193             primSpec, oldLayerPath, newLayerPath);
3194     }
3195 }
3196 
3197 /*static*/
3198 void
DumpLayerInfo()3199 SdfLayer::DumpLayerInfo()
3200 {
3201     tbb::queuing_rw_mutex::scoped_lock
3202         lock(_GetLayerRegistryMutex(), /*write=*/false);
3203     std::cerr << "Layer Registry Dump:" << std::endl
3204         << *_layerRegistry << std::endl;
3205 }
3206 
3207 bool
WriteDataFile(const string & filename)3208 SdfLayer::WriteDataFile(const string &filename)
3209 {
3210     std::ofstream file(filename.c_str());
3211     _data->WriteToStream(file);
3212     return file.good();
3213 }
3214 
3215 /*static*/
3216 set<SdfLayerHandle>
GetLoadedLayers()3217 SdfLayer::GetLoadedLayers()
3218 {
3219     tbb::queuing_rw_mutex::scoped_lock
3220         lock(_GetLayerRegistryMutex(), /*write=*/false);
3221     return _layerRegistry->GetLayers();
3222 }
3223 
3224 /* static */
3225 template <class Lock>
3226 SdfLayerRefPtr
_OpenLayerAndUnlockRegistry(Lock & lock,const _FindOrOpenLayerInfo & info,bool metadataOnly)3227 SdfLayer::_OpenLayerAndUnlockRegistry(
3228     Lock &lock,
3229     const _FindOrOpenLayerInfo& info,
3230     bool metadataOnly)
3231 {
3232     TfAutoMallocTag2 tag("Sdf", "SdfLayer::_OpenLayerAndUnlockRegistry "
3233                          + info.identifier);
3234 
3235     TRACE_FUNCTION();
3236 
3237     TF_DEBUG(SDF_LAYER).Msg(
3238         "SdfLayer::_OpenLayerAndUnlockRegistry('%s', '%s', '%s', '%s', "
3239         "metadataOnly=%s)\n",
3240         info.identifier.c_str(), info.layerPath.c_str(),
3241         info.fileFormat ?
3242             info.fileFormat->GetFormatId().GetText() :  "unknown file format",
3243         TfStringify(info.fileFormatArgs).c_str(),
3244         metadataOnly ? "True" : "False");
3245 
3246     // XXX: Is this really a coding error? SdfLayer avoids issuing errors if
3247     //      given a non-existent file, for instance. Should we be following the
3248     //      same policy here?
3249     if (!info.fileFormat) {
3250         TF_CODING_ERROR("Cannot determine file format for @%s@",
3251                         info.identifier.c_str());
3252         lock.release();
3253         return TfNullPtr;
3254     }
3255 
3256     // Create a new layer of the appropriate format.
3257     SdfLayerRefPtr layer = _CreateNewWithFormat(
3258         info.fileFormat, info.identifier, info.resolvedLayerPath,
3259         info.assetInfo, info.fileFormatArgs);
3260 
3261     // The layer constructor sets _initializationComplete to false, which will
3262     // block any other threads trying to use the layer until we complete
3263     // initialization.  But now that the layer is in the registry, we release
3264     // the registry lock to avoid blocking progress of threads working with
3265     // other layers.
3266     TF_VERIFY(_layerRegistry->
3267               FindByIdentifier(layer->GetIdentifier()) == layer,
3268               "Could not find %s", layer->GetIdentifier().c_str());
3269 
3270     lock.release();
3271 
3272     // From this point on, we need to be sure to call
3273     // layer->_FinishInitialization() with either success or failure,
3274     // in order to unblock any other threads waiting for initialization
3275     // to finish.
3276 
3277     if (info.isAnonymous != layer->IsAnonymous()) {
3278         if (info.isAnonymous) {
3279             TF_CODING_ERROR("Opened anonymous layer ('%s' with format id '%s') "
3280                     "but resulting layer is not anonymous.",
3281                     info.identifier.c_str(),
3282                     info.fileFormat->GetFormatId().GetText());
3283         }
3284         else {
3285             TF_CODING_ERROR("Opened layer without anonymous prefix "
3286                     "('%s' with format id '%s') but resulting layer is "
3287                     "anonymous.",
3288                     info.identifier.c_str(),
3289                     info.fileFormat->GetFormatId().GetText());
3290         }
3291         layer->_FinishInitialization(/* success = */ false);
3292         return TfNullPtr;
3293     }
3294 
3295     // This is in support of specialized file formats that piggyback
3296     // on anonymous layer functionality. If the layer is anonymous,
3297     // pass the original assetPath to the reader, otherwise, pass the
3298     // resolved path of the layer.
3299     const string readFilePath =
3300         info.isAnonymous ? info.layerPath : info.resolvedLayerPath;
3301 
3302     if (!layer->IsMuted()) {
3303         // Run the file parser to read in the file contents.
3304         if (!layer->_Read(info.identifier, readFilePath, metadataOnly)) {
3305             layer->_FinishInitialization(/* success = */ false);
3306             return TfNullPtr;
3307         }
3308      }
3309 
3310     // Grab the modification time even if layer is muted and not being
3311     // read. Since a muted layer may become unmuted later, there needs
3312     // to be a non-empty timestamp so it will not be misidentified as
3313     // a newly created non-serialized layer.
3314     if (!info.isAnonymous) {
3315         // Grab modification timestamp.
3316         VtValue timestamp(ArGetResolver().GetModificationTimestamp(
3317             info.layerPath, ArResolvedPath(readFilePath)));
3318 #if AR_VERSION == 1
3319         if (timestamp.IsEmpty()) {
3320             TF_CODING_ERROR(
3321                 "Unable to get modification timestamp for '%s (%s)'",
3322                 info.identifier.c_str(), readFilePath.c_str());
3323             layer->_FinishInitialization(/* success = */ false);
3324             return TfNullPtr;
3325         }
3326 #endif
3327 
3328         layer->_assetModificationTime.Swap(timestamp);
3329     }
3330 
3331     // Store any external asset dependencies so we have an initial state to
3332     // compare during reload.
3333     layer->_externalAssetModificationTimes =
3334         _GetExternalAssetModificationTimes(*layer);
3335 
3336     layer->_MarkCurrentStateAsClean();
3337 
3338     // Layer initialization is complete.
3339     layer->_FinishInitialization(/* success = */ true);
3340 
3341     return layer;
3342 }
3343 
3344 bool
HasSpec(const SdfPath & path) const3345 SdfLayer::HasSpec(const SdfPath& path) const
3346 {
3347     return _data->HasSpec(path);
3348 }
3349 
3350 SdfSpecType
GetSpecType(const SdfPath & path) const3351 SdfLayer::GetSpecType(const SdfPath& path) const
3352 {
3353     return _data->GetSpecType(path);
3354 }
3355 
3356 vector<TfToken>
ListFields(const SdfPath & path) const3357 SdfLayer::ListFields(const SdfPath& path) const
3358 {
3359     return _ListFields(GetSchema(), *get_pointer(_data), path);
3360 }
3361 
3362 vector<TfToken>
_ListFields(SdfSchemaBase const & schema,SdfAbstractData const & data,const SdfPath & path)3363 SdfLayer::_ListFields(SdfSchemaBase const &schema,
3364                       SdfAbstractData const &data, const SdfPath& path)
3365 {
3366     // Invoke List() on the underlying data implementation but be sure to
3367     // include all required fields too.
3368 
3369     // Collect the list from the data implemenation.
3370     vector<TfToken> dataList = data.List(path);
3371 
3372     // Determine spec type.  If unknown, return early.
3373     SdfSpecType specType = data.GetSpecType(path);
3374     if (ARCH_UNLIKELY(specType == SdfSpecTypeUnknown)) {
3375         return dataList;
3376     }
3377 
3378     // Collect required fields.
3379     vector<TfToken> const &req = schema.GetRequiredFields(specType);
3380 
3381     // Union them together, but retain order of dataList, since it influences
3382     // the output ordering in some file writers.
3383     TfToken const *dataListBegin = dataList.data();
3384     TfToken const *dataListEnd = dataListBegin + dataList.size();
3385     bool mightAlloc = (dataList.size() + req.size()) > dataList.capacity();
3386     for (size_t reqIdx = 0, reqSz = req.size(); reqIdx != reqSz; ++reqIdx) {
3387         TfToken const &reqName = req[reqIdx];
3388         TfToken const *iter = std::find(dataListBegin, dataListEnd, reqName);
3389         if (iter == dataListEnd) {
3390             // If the required field name is not already present, append it.
3391             // Make sure we have capacity for all required fields so we do no
3392             // more than one additional allocation here.
3393             if (mightAlloc && dataList.size() == dataList.capacity()) {
3394                 dataList.reserve(dataList.size() + (reqSz - reqIdx));
3395                 dataListEnd =
3396                     dataList.data() + std::distance(dataListBegin, dataListEnd);
3397                 dataListBegin = dataList.data();
3398                 mightAlloc = false;
3399             }
3400             dataList.push_back(reqName);
3401         }
3402     }
3403     return dataList;
3404 }
3405 
3406 SdfSchema::FieldDefinition const *
_GetRequiredFieldDef(const SdfPath & path,const TfToken & fieldName,SdfSpecType specType) const3407 SdfLayer::_GetRequiredFieldDef(const SdfPath &path,
3408                                const TfToken &fieldName,
3409                                SdfSpecType specType) const
3410 {
3411     SdfSchemaBase const &schema = GetSchema();
3412     if (ARCH_UNLIKELY(schema.IsRequiredFieldName(fieldName))) {
3413         // Get the spec definition.
3414         if (specType == SdfSpecTypeUnknown) {
3415             specType = GetSpecType(path);
3416         }
3417         if (SdfSchema::SpecDefinition const *
3418             specDef = schema.GetSpecDefinition(specType)) {
3419             // If this field is required for this spec type, look up the
3420             // field definition.
3421             if (specDef->IsRequiredField(fieldName)) {
3422                 return schema.GetFieldDefinition(fieldName);
3423             }
3424         }
3425     }
3426     return nullptr;
3427 }
3428 
3429 SdfSchema::FieldDefinition const *
_GetRequiredFieldDef(const SdfSchemaBase & schema,const TfToken & fieldName,SdfSpecType specType)3430 SdfLayer::_GetRequiredFieldDef(const SdfSchemaBase &schema,
3431                                const TfToken &fieldName,
3432                                SdfSpecType specType)
3433 {
3434     if (ARCH_UNLIKELY(schema.IsRequiredFieldName(fieldName))) {
3435         if (SdfSchema::SpecDefinition const *
3436             specDef = schema.GetSpecDefinition(specType)) {
3437             // If this field is required for this spec type, look up the
3438             // field definition.
3439             if (specDef->IsRequiredField(fieldName)) {
3440                 return schema.GetFieldDefinition(fieldName);
3441             }
3442         }
3443     }
3444     return nullptr;
3445 }
3446 
3447 bool
_HasField(const SdfSchemaBase & schema,const SdfAbstractData & data,const SdfPath & path,const TfToken & fieldName,VtValue * value)3448 SdfLayer::_HasField(const SdfSchemaBase &schema,
3449                     const SdfAbstractData &data,
3450                     const SdfPath& path,
3451                     const TfToken& fieldName,
3452                     VtValue *value)
3453 {
3454     SdfSpecType specType;
3455     if (data.HasSpecAndField(path, fieldName, value, &specType)) {
3456         return true;
3457     }
3458     if (specType == SdfSpecTypeUnknown) {
3459         return false;
3460     }
3461     // Otherwise if this is a required field, and the data has a spec here,
3462     // return the fallback value.
3463     if (SdfSchema::FieldDefinition const *def =
3464         _GetRequiredFieldDef(schema, fieldName, specType)) {
3465         if (value)
3466             *value = def->GetFallbackValue();
3467         return true;
3468     }
3469     return false;
3470 }
3471 
3472 bool
HasField(const SdfPath & path,const TfToken & fieldName,VtValue * value) const3473 SdfLayer::HasField(const SdfPath& path, const TfToken& fieldName,
3474                    VtValue *value) const
3475 {
3476     SdfSpecType specType;
3477     if (_data->HasSpecAndField(path, fieldName, value, &specType)) {
3478         return true;
3479     }
3480     if (specType == SdfSpecTypeUnknown) {
3481         return false;
3482     }
3483     // Otherwise if this is a required field, and the data has a spec here,
3484     // return the fallback value.
3485     if (SdfSchema::FieldDefinition const *def =
3486         _GetRequiredFieldDef(path, fieldName, specType)) {
3487         if (value)
3488             *value = def->GetFallbackValue();
3489         return true;
3490     }
3491     return false;
3492 }
3493 
3494 bool
HasField(const SdfPath & path,const TfToken & fieldName,SdfAbstractDataValue * value) const3495 SdfLayer::HasField(const SdfPath& path, const TfToken& fieldName,
3496                    SdfAbstractDataValue *value) const
3497 {
3498     SdfSpecType specType;
3499     if (_data->HasSpecAndField(path, fieldName, value, &specType)) {
3500         return true;
3501     }
3502     if (specType == SdfSpecTypeUnknown) {
3503         return false;
3504     }
3505     // Otherwise if this is a required field, and the data has a spec here,
3506     // return the fallback value.
3507     if (SdfSchema::FieldDefinition const *def =
3508         _GetRequiredFieldDef(path, fieldName, specType)) {
3509         if (value)
3510             return value->StoreValue(def->GetFallbackValue());
3511         return true;
3512     }
3513     return false;
3514 }
3515 
3516 bool
HasFieldDictKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath,VtValue * value) const3517 SdfLayer::HasFieldDictKey(const SdfPath& path,
3518                           const TfToken &fieldName,
3519                           const TfToken &keyPath,
3520                           VtValue *value) const
3521 {
3522     if (_data->HasDictKey(path, fieldName, keyPath, value))
3523         return true;
3524     // Otherwise if this is a required field, and the data has a spec here,
3525     // return the fallback value.
3526     if (SdfSchema::FieldDefinition const *def =
3527         _GetRequiredFieldDef(path, fieldName)) {
3528         VtValue const &fallback = def->GetFallbackValue();
3529         if (fallback.IsHolding<VtDictionary>()) {
3530             VtDictionary const &dict = fallback.UncheckedGet<VtDictionary>();
3531             if (VtValue const *v = dict.GetValueAtPath(keyPath)) {
3532                 if (value)
3533                     *value = *v;
3534                 return true;
3535             }
3536         }
3537     }
3538     return false;
3539 }
3540 
3541 bool
HasFieldDictKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath,SdfAbstractDataValue * value) const3542 SdfLayer::HasFieldDictKey(const SdfPath& path,
3543                           const TfToken &fieldName,
3544                           const TfToken &keyPath,
3545                           SdfAbstractDataValue *value) const
3546 {
3547     if (_data->HasDictKey(path, fieldName, keyPath, value))
3548         return true;
3549     // Otherwise if this is a required field, and the data has a spec here,
3550     // return the fallback value.
3551     if (SdfSchema::FieldDefinition const *def =
3552         _GetRequiredFieldDef(path, fieldName)) {
3553         VtValue const &fallback = def->GetFallbackValue();
3554         if (fallback.IsHolding<VtDictionary>()) {
3555             VtDictionary const &dict = fallback.UncheckedGet<VtDictionary>();
3556             if (VtValue const *v = dict.GetValueAtPath(keyPath)) {
3557                 if (value)
3558                     return value->StoreValue(*v);
3559                 return true;
3560             }
3561         }
3562     }
3563     return false;
3564 }
3565 
3566 VtValue
GetField(const SdfPath & path,const TfToken & fieldName) const3567 SdfLayer::GetField(const SdfPath& path,
3568     const TfToken& fieldName) const
3569 {
3570     VtValue result;
3571     HasField(path, fieldName, &result);
3572     return result;
3573 }
3574 
3575 VtValue
_GetField(const SdfSchemaBase & schema,const SdfAbstractData & data,const SdfPath & path,const TfToken & fieldName)3576 SdfLayer::_GetField(const SdfSchemaBase &schema,
3577                     const SdfAbstractData &data,
3578                     const SdfPath& path,
3579                     const TfToken& fieldName)
3580 {
3581     VtValue result;
3582     _HasField(schema, data, path, fieldName, &result);
3583     return result;
3584 }
3585 
3586 VtValue
GetFieldDictValueByKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath) const3587 SdfLayer::GetFieldDictValueByKey(const SdfPath& path,
3588                                  const TfToken& fieldName,
3589                                  const TfToken &keyPath) const
3590 {
3591     VtValue result;
3592     HasFieldDictKey(path, fieldName, keyPath, &result);
3593     return result;
3594 }
3595 
3596 static bool
_IsValidFieldForLayer(const SdfLayer & layer,const SdfPath & path,const TfToken & fieldName)3597 _IsValidFieldForLayer(
3598     const SdfLayer& layer, const SdfPath& path,
3599     const TfToken& fieldName)
3600 {
3601     return layer.GetSchema().IsValidFieldForSpec(
3602         fieldName, layer.GetSpecType(path));
3603 }
3604 
3605 void
SetField(const SdfPath & path,const TfToken & fieldName,const VtValue & value)3606 SdfLayer::SetField(const SdfPath& path, const TfToken& fieldName,
3607                    const VtValue& value)
3608 {
3609     if (value.IsEmpty())
3610         return EraseField(path, fieldName);
3611 
3612     if (ARCH_UNLIKELY(!PermissionToEdit())) {
3613         TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.",
3614                         fieldName.GetText(), path.GetText(),
3615                         GetIdentifier().c_str());
3616         return;
3617     }
3618 
3619     if (ARCH_UNLIKELY(_validateAuthoring) &&
3620         !_IsValidFieldForLayer(*this, path, fieldName)) {
3621         TF_ERROR(SdfAuthoringErrorUnrecognizedFields,
3622                  "Cannot set %s on <%s>. Field is not valid for layer @%s@.",
3623                  fieldName.GetText(), path.GetText(),
3624                  GetIdentifier().c_str());
3625         return;
3626     }
3627 
3628     VtValue oldValue = GetField(path, fieldName);
3629     if (value != oldValue)
3630         _PrimSetField(path, fieldName, value, &oldValue);
3631 }
3632 
3633 void
SetField(const SdfPath & path,const TfToken & fieldName,const SdfAbstractDataConstValue & value)3634 SdfLayer::SetField(const SdfPath& path, const TfToken& fieldName,
3635                    const SdfAbstractDataConstValue& value)
3636 {
3637     if (value.IsEqual(VtValue()))
3638         return EraseField(path, fieldName);
3639 
3640     if (ARCH_UNLIKELY(!PermissionToEdit())) {
3641         TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.",
3642                         fieldName.GetText(), path.GetText(),
3643                         GetIdentifier().c_str());
3644         return;
3645     }
3646 
3647     if (ARCH_UNLIKELY(_validateAuthoring) &&
3648         !_IsValidFieldForLayer(*this, path, fieldName)) {
3649         TF_ERROR(SdfAuthoringErrorUnrecognizedFields,
3650                  "Cannot set %s on <%s>. Field is not valid for layer @%s@.",
3651                  fieldName.GetText(), path.GetText(),
3652                  GetIdentifier().c_str());
3653         return;
3654     }
3655 
3656     VtValue oldValue = GetField(path, fieldName);
3657     if (!value.IsEqual(oldValue))
3658         _PrimSetField(path, fieldName, value, &oldValue);
3659 }
3660 
3661 void
SetFieldDictValueByKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath,const VtValue & value)3662 SdfLayer::SetFieldDictValueByKey(const SdfPath& path,
3663                                  const TfToken& fieldName,
3664                                  const TfToken& keyPath,
3665                                  const VtValue& value)
3666 {
3667     if (!PermissionToEdit()) {
3668         TF_CODING_ERROR("Cannot set %s:%s on <%s>. Layer @%s@ is not editable.",
3669                         fieldName.GetText(), keyPath.GetText(),
3670                         path.GetText(),
3671                         GetIdentifier().c_str());
3672         return;
3673     }
3674 
3675     if (ARCH_UNLIKELY(_validateAuthoring) &&
3676         !_IsValidFieldForLayer(*this, path, fieldName)) {
3677         TF_ERROR(SdfAuthoringErrorUnrecognizedFields,
3678                  "Cannot set %s:%s on <%s>. Field is not valid for layer @%s@.",
3679                  fieldName.GetText(), keyPath.GetText(),
3680                  path.GetText(), GetIdentifier().c_str());
3681         return;
3682     }
3683 
3684     VtValue oldValue = GetFieldDictValueByKey(path, fieldName, keyPath);
3685     if (value == oldValue)
3686         return;
3687 
3688     _PrimSetFieldDictValueByKey(path, fieldName, keyPath, value, &oldValue);
3689 }
3690 
3691 void
SetFieldDictValueByKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath,const SdfAbstractDataConstValue & value)3692 SdfLayer::SetFieldDictValueByKey(const SdfPath& path,
3693                                  const TfToken& fieldName,
3694                                  const TfToken& keyPath,
3695                                  const SdfAbstractDataConstValue& value)
3696 {
3697     if (!PermissionToEdit()) {
3698         TF_CODING_ERROR("Cannot set %s:%s on <%s>. Layer @%s@ is not editable.",
3699                         fieldName.GetText(), keyPath.GetText(),
3700                         path.GetText(),
3701                         GetIdentifier().c_str());
3702         return;
3703     }
3704 
3705     if (ARCH_UNLIKELY(_validateAuthoring) &&
3706         !_IsValidFieldForLayer(*this, path, fieldName)) {
3707         TF_ERROR(SdfAuthoringErrorUnrecognizedFields,
3708                  "Cannot set %s:%s on <%s>. Field is not valid for layer @%s@.",
3709                  fieldName.GetText(), keyPath.GetText(),
3710                  path.GetText(), GetIdentifier().c_str());
3711         return;
3712     }
3713 
3714     VtValue oldValue = GetFieldDictValueByKey(path, fieldName, keyPath);
3715     if (value.IsEqual(oldValue))
3716         return;
3717 
3718     _PrimSetFieldDictValueByKey(path, fieldName, keyPath, value, &oldValue);
3719 }
3720 
3721 void
EraseField(const SdfPath & path,const TfToken & fieldName)3722 SdfLayer::EraseField(const SdfPath& path, const TfToken& fieldName)
3723 {
3724     if (ARCH_UNLIKELY(!PermissionToEdit())) {
3725         TF_CODING_ERROR("Cannot erase %s on <%s>. Layer @%s@ is not editable.",
3726                         fieldName.GetText(), path.GetText(),
3727                         GetIdentifier().c_str());
3728         return;
3729     }
3730 
3731     if (!_data->Has(path, fieldName)) {
3732         return;
3733     }
3734 
3735     // If this is a required field, only perform the set if the current value
3736     // differs from the fallback.  Required fields behave as if they're always
3737     // authored, so the effect of an "erase" is to set the value to the fallback
3738     // value.
3739     if (SdfSchema::FieldDefinition const *def =
3740         _GetRequiredFieldDef(path, fieldName)) {
3741         if (GetField(path, fieldName) == def->GetFallbackValue())
3742             return;
3743     }
3744 
3745     // XXX:
3746     // Note that with this implementation, erasing a field and undoing that
3747     // operation will not restore the underlying SdfData exactly to its
3748     // previous state. Specifically, this may cause the order of the fields
3749     // for the given spec to change. There are no semantics attached to this
3750     // ordering, so this should hopefully be OK.
3751     _PrimSetField(path, fieldName, VtValue());
3752 }
3753 
3754 void
EraseFieldDictValueByKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath)3755 SdfLayer::EraseFieldDictValueByKey(const SdfPath& path,
3756                                    const TfToken& fieldName,
3757                                    const TfToken &keyPath)
3758 {
3759     if (!PermissionToEdit()) {
3760         TF_CODING_ERROR("Cannot erase %s:%s on <%s>. Layer @%s@ is not editable.",
3761                         fieldName.GetText(), keyPath.GetText(),
3762                         path.GetText(),
3763                         GetIdentifier().c_str());
3764         return;
3765     }
3766 
3767     if (!_data->HasDictKey(path, fieldName, keyPath,
3768                            static_cast<VtValue *>(NULL))) {
3769         return;
3770     }
3771 
3772     // XXX:
3773     // Note that with this implementation, erasing a field and undoing that
3774     // operation will not restore the underlying SdfData exactly to its
3775     // previous state. Specifically, this may cause the order of the fields
3776     // for the given spec to change. There are no semantics attached to this
3777     // ordering, so this should hopefully be OK.
3778     _PrimSetFieldDictValueByKey(path, fieldName, keyPath, VtValue());
3779 }
3780 
3781 SdfAbstractDataConstPtr
_GetData() const3782 SdfLayer::_GetData() const
3783 {
3784     return _data;
3785 }
3786 
3787 void
_SwapData(SdfAbstractDataRefPtr & data)3788 SdfLayer::_SwapData(SdfAbstractDataRefPtr &data)
3789 {
3790     _data.swap(data);
3791 }
3792 
3793 void
_SetData(const SdfAbstractDataPtr & newData,const SdfSchemaBase * newDataSchema)3794 SdfLayer::_SetData(const SdfAbstractDataPtr &newData,
3795                    const SdfSchemaBase *newDataSchema)
3796 {
3797     TRACE_FUNCTION();
3798     TF_DESCRIBE_SCOPE("Setting layer data");
3799 
3800     // Guard against setting an empty SdfData, which is invalid.
3801     TF_VERIFY(!newData->IsEmpty() );
3802 
3803     // This code below performs a series of specific edits to mutate _data
3804     // to match newData.  This approach provides fine-grained change
3805     // notification, which allows more efficient invalidation in clients
3806     // of Sd.  Do all this in a single changeblock.
3807     SdfChangeBlock block;
3808 
3809     // If we're transferring from one schema to a different schema, we will go
3810     // through the fine-grained update in order to do cross-schema field
3811     // validation.
3812     const bool differentSchema = newDataSchema && newDataSchema != &GetSchema();
3813 
3814     // If this layer streams its data on demand, we avoid the fine-grained
3815     // change code path (unless it's to a different schema) because that would
3816     // cause all of the data in the layer to be streamed in from disk.  So we
3817     // move the new data into place and notify the world that this layer may
3818     // have changed arbitrarily.
3819     if (!differentSchema && _data->StreamsData()) {
3820         _data = newData;
3821         Sdf_ChangeManager::Get().DidReplaceLayerContent(_self);
3822         return;
3823     }
3824 
3825     // Remove specs that no longer exist or whose required fields changed.
3826     {
3827         // Collect specs to delete, ordered by namespace.
3828         struct _SpecsToDelete : public SdfAbstractDataSpecVisitor {
3829             _SpecsToDelete(const SdfAbstractDataPtr& newData_)
3830                 : newData(newData_) { }
3831 
3832             virtual bool VisitSpec(
3833                 const SdfAbstractData& oldData, const SdfPath& path)
3834             {
3835                 if (!newData->HasSpec(path) ||
3836                     (newData->GetSpecType(path) != oldData.GetSpecType(path))) {
3837                     paths.insert(path);
3838                 }
3839                 return true;
3840             }
3841 
3842             virtual void Done(const SdfAbstractData&)
3843             {
3844                 // Do nothing
3845             }
3846 
3847             const SdfAbstractDataRefPtr newData;
3848             std::set<SdfPath> paths;
3849         };
3850 
3851         _SpecsToDelete specsToDelete(newData);
3852         _data->VisitSpecs(&specsToDelete);
3853 
3854         // Delete specs bottom-up to provide optimal diffs.
3855         // Erase fields first, to take advantage of the more efficient
3856         // update possible when removing inert specs.
3857         TF_REVERSE_FOR_ALL(i, specsToDelete.paths) {
3858             const SdfPath &path = *i;
3859 
3860             std::vector<TfToken> fields = ListFields(path);
3861 
3862             SdfSpecType specType = _data->GetSpecType(path);
3863             const SdfSchema::SpecDefinition* specDefinition =
3864                 GetSchema().GetSpecDefinition(specType);
3865 
3866             TF_FOR_ALL(field, fields) {
3867                 if (!specDefinition->IsRequiredField(*field))
3868                     _PrimSetField(path, *field, VtValue());
3869             }
3870             _PrimDeleteSpec(*i, _IsInertSubtree(*i));
3871         }
3872     }
3873 
3874     // Create new specs.
3875     {
3876         // Collect specs to create, ordered by namespace.
3877         struct _SpecsToCreate : public SdfAbstractDataSpecVisitor {
3878             _SpecsToCreate(const SdfAbstractData& oldData_)
3879                 : oldData(oldData_) { }
3880 
3881             virtual bool VisitSpec(
3882                 const SdfAbstractData& newData, const SdfPath& path)
3883             {
3884                 if (!oldData.HasSpec(path)) {
3885                     paths.insert(path);
3886                 }
3887                 return true;
3888             }
3889 
3890             virtual void Done(const SdfAbstractData&)
3891             {
3892                 // Do nothing
3893             }
3894 
3895             const SdfAbstractData& oldData;
3896             std::set<SdfPath> paths;
3897         };
3898 
3899         _SpecsToCreate specsToCreate(*boost::get_pointer(_data));
3900         newData->VisitSpecs(&specsToCreate);
3901 
3902         SdfPath unrecognizedSpecTypePaths[SdfNumSpecTypes];
3903 
3904         // Create specs top-down to provide optimal diffs.
3905         TF_FOR_ALL(i, specsToCreate.paths) {
3906             const SdfPath& path = *i;
3907 
3908             // Determine if the spec is inert based on its fields.
3909             //
3910             // XXX We should consolidate this with the logic
3911             //     in the spec _New() methods.
3912             bool inert = false;
3913             if (path.IsPrimPath()) {
3914                 // Prims are considered inert if they are an 'over' with
3915                 // no typename. Make sure we specify the expected fallback
3916                 // values in case newData does not explicitly store a value
3917                 // for these fields.
3918                 inert =
3919                     (newData->GetAs<SdfSpecifier>(path, SdfFieldKeys->Specifier,
3920                                                   SdfSpecifierOver)
3921                         == SdfSpecifierOver)
3922                     && (newData->GetAs<TfToken>(path, SdfFieldKeys->TypeName,
3923                                                 TfToken())
3924                         .IsEmpty());
3925             } else if (path.IsPropertyPath()) {
3926                 // Properties are considered inert if they are custom.
3927                 inert = !newData->GetAs<bool>(path, SdfFieldKeys->Custom,
3928                                               false);
3929             }
3930 
3931             SdfSpecType specType = newData->GetSpecType(path);
3932 
3933             // If this is a cross-schema _SetData call, check to see if the spec
3934             // type is known to this layer's schema.  If not, skip creating it
3935             // and record it to issue an error later.
3936             if (differentSchema && !GetSchema().GetSpecDefinition(specType)) {
3937                 // Record the path where this spec type was first encountered.
3938                 if (unrecognizedSpecTypePaths[specType].IsEmpty()) {
3939                     unrecognizedSpecTypePaths[specType] = path;
3940                 }
3941             }
3942             else {
3943                 _PrimCreateSpec(path, specType, inert);
3944             }
3945         }
3946         // If there were unrecognized specTypes, issue an error.
3947         if (differentSchema) {
3948             vector<string> specDescrs;
3949             for (int i = 0; i != SdfSpecTypeUnknown; ++i) {
3950                 if (unrecognizedSpecTypePaths[i].IsEmpty()) {
3951                     continue;
3952                 }
3953                 specDescrs.push_back(
3954                     TfStringPrintf(
3955                         "'%s' first seen at <%s>",
3956                         TfStringify(static_cast<SdfSpecType>(i)).c_str(),
3957                         unrecognizedSpecTypePaths[i].GetAsString().c_str()));
3958             }
3959             if (!specDescrs.empty()) {
3960                 TF_ERROR(SdfAuthoringErrorUnrecognizedSpecType,
3961                          "Omitted unrecognized spec types setting data on "
3962                          "@%s@: %s", GetIdentifier().c_str(),
3963                          TfStringJoin(specDescrs, "; ").c_str());
3964             }
3965         }
3966     }
3967 
3968     // Update spec fields.
3969     {
3970         struct _SpecUpdater : public SdfAbstractDataSpecVisitor {
3971             _SpecUpdater(SdfLayer* layer_,
3972                          const SdfSchemaBase &newDataSchema_)
3973                 : layer(layer_)
3974                 , newDataSchema(newDataSchema_) {}
3975 
3976             virtual bool VisitSpec(
3977                 const SdfAbstractData& newData, const SdfPath& path)
3978             {
3979                 const TfTokenVector oldFields = layer->ListFields(path);
3980                 const TfTokenVector newFields =
3981                     _ListFields(newDataSchema, newData, path);
3982 
3983                 const SdfSchemaBase &thisLayerSchema = layer->GetSchema();
3984 
3985                 const bool differentSchema = &thisLayerSchema != &newDataSchema;
3986 
3987                 // If this layer has a different schema from newDataSchema, then
3988                 // it's possible there is no corresponding spec for the path, in
3989                 // case the spec type is not supported.  Check for this, and
3990                 // skip field processing if so.
3991                 if (differentSchema && !layer->HasSpec(path)) {
3992                     return true;
3993                 }
3994 
3995                 // Remove empty fields.
3996                 for (TfToken const &field: oldFields) {
3997                     // This is O(N^2) in number of fields in each spec, but
3998                     // we expect a small max N, around 10.
3999                     if (std::find(newFields.begin(), newFields.end(), field)
4000                         == newFields.end()) {
4001                         layer->_PrimSetField(path, field, VtValue());
4002                     }
4003                 }
4004 
4005                 // Set field values.
4006                 for (TfToken const &field: newFields) {
4007                     VtValue newValue =
4008                         _GetField(newDataSchema, newData, path, field);
4009                     VtValue oldValue = layer->GetField(path, field);
4010                     if (oldValue != newValue) {
4011                         if (differentSchema && oldValue.IsEmpty() &&
4012                             !thisLayerSchema.IsValidFieldForSpec(
4013                                 field, layer->GetSpecType(path))) {
4014                             // This field might not be valid for the target
4015                             // schema.  If that's the case record it (if it's
4016                             // not already recorded) and skip setting it.
4017                             unrecognizedFields.emplace(field, path);
4018                         }
4019                         else {
4020                             layer->_PrimSetField(path, field,
4021                                                  newValue, &oldValue);
4022                         }
4023                     }
4024                 }
4025                 return true;
4026             }
4027 
4028             virtual void Done(const SdfAbstractData&)
4029             {
4030                 // Do nothing
4031             }
4032 
4033             SdfLayer* layer;
4034             const SdfSchemaBase &newDataSchema;
4035             std::map<TfToken, SdfPath> unrecognizedFields;
4036         };
4037 
4038         // If no newDataSchema is supplied, we assume the newData adheres to
4039         // this layer's schema.
4040         _SpecUpdater updater(
4041             this, newDataSchema ? *newDataSchema : GetSchema());
4042         newData->VisitSpecs(&updater);
4043 
4044         // If there were unrecognized fields, report an error.
4045         if (!updater.unrecognizedFields.empty()) {
4046             vector<string> fieldDescrs;
4047             fieldDescrs.reserve(updater.unrecognizedFields.size());
4048             for (std::pair<TfToken, SdfPath> const &tokenPath:
4049                      updater.unrecognizedFields) {
4050                 fieldDescrs.push_back(
4051                     TfStringPrintf("'%s' first seen at <%s>",
4052                                    tokenPath.first.GetText(),
4053                                    tokenPath.second.GetAsString().c_str()));
4054             }
4055             TF_ERROR(SdfAuthoringErrorUnrecognizedFields,
4056                      "Omitted unrecognized fields setting data on @%s@: %s",
4057                      GetIdentifier().c_str(),
4058                      TfStringJoin(fieldDescrs, "; ").c_str());
4059         }
4060     }
4061 
4062     // Verify that the result matches.
4063     // TODO Enable in debug builds.
4064     if (0) {
4065         TRACE_SCOPE("SdfLayer::_SetData - Verify result");
4066         TF_VERIFY(_data->Equals(newData));
4067     }
4068 }
4069 
4070 template <class T>
4071 void
_PrimSetField(const SdfPath & path,const TfToken & fieldName,const T & value,const VtValue * oldValuePtr,bool useDelegate)4072 SdfLayer::_PrimSetField(const SdfPath& path,
4073                         const TfToken& fieldName,
4074                         const T& value,
4075                         const VtValue *oldValuePtr,
4076                         bool useDelegate)
4077 {
4078     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4079         _stateDelegate->SetField(path, fieldName, value, oldValuePtr);
4080         return;
4081     }
4082 
4083     const VtValue& oldValue =
4084         oldValuePtr ? *oldValuePtr : GetField(path, fieldName);
4085     const VtValue& newValue = _GetVtValue(value);
4086 
4087     // Send notification when leaving the change block.
4088     SdfChangeBlock block;
4089 
4090     Sdf_ChangeManager::Get().DidChangeField(
4091         _self, path, fieldName, oldValue, newValue);
4092 
4093     _data->Set(path, fieldName, value);
4094 }
4095 
4096 template void SdfLayer::_PrimSetField(
4097     const SdfPath&, const TfToken&,
4098     const VtValue&, const VtValue *, bool);
4099 template void SdfLayer::_PrimSetField(
4100     const SdfPath&, const TfToken&,
4101     const SdfAbstractDataConstValue&, const VtValue *, bool);
4102 
4103 template <class T>
4104 void
_PrimPushChild(const SdfPath & parentPath,const TfToken & fieldName,const T & value,bool useDelegate)4105 SdfLayer::_PrimPushChild(const SdfPath& parentPath,
4106                          const TfToken& fieldName,
4107                          const T& value,
4108                          bool useDelegate)
4109 {
4110     if (!HasField(parentPath, fieldName)) {
4111         _PrimSetField(parentPath, fieldName,
4112             VtValue(std::vector<T>(1, value)));
4113         return;
4114     }
4115 
4116     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4117         _stateDelegate->PushChild(parentPath, fieldName, value);
4118         return;
4119     }
4120 
4121     // A few efficiency notes:
4122     //
4123     // - We want to push the child onto the existing vector.  Since
4124     //   VtValue is copy-on-write, we avoid incurring a copy fault
4125     //   by retrieving the value from the data store and then
4126     //   erasing the field before modifying the vector.  Similarly,
4127     //   we swap the vector<T> out of the type-erased VtValue box,
4128     //   modify that, then swap it back in.
4129     //
4130     // - Do not record a field change entry with Sdf_ChangeManager.
4131     //   Doing so would require us to provide both the old & new
4132     //   values for the vector.  Note tha the the changelist protocol
4133     //   already has special affordances for spec add/remove events,
4134     //   and child fields are essentially an implementation detail.
4135     //
4136     VtValue box = _data->Get(parentPath, fieldName);
4137     _data->Erase(parentPath, fieldName);
4138     std::vector<T> vec;
4139     if (box.IsHolding<std::vector<T>>()) {
4140         box.Swap(vec);
4141     } else {
4142         // If the value isn't a vector, we replace it with an empty one.
4143     }
4144     vec.push_back(value);
4145     box.Swap(vec);
4146     _data->Set(parentPath, fieldName, box);
4147 }
4148 
4149 template void SdfLayer::_PrimPushChild(
4150     const SdfPath&, const TfToken&,
4151     const TfToken &, bool);
4152 template void SdfLayer::_PrimPushChild(
4153     const SdfPath&, const TfToken&,
4154     const SdfPath &, bool);
4155 
4156 template <class T>
4157 void
_PrimPopChild(const SdfPath & parentPath,const TfToken & fieldName,bool useDelegate)4158 SdfLayer::_PrimPopChild(const SdfPath& parentPath,
4159                         const TfToken& fieldName,
4160                         bool useDelegate)
4161 {
4162     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4163         std::vector<T> vec = GetFieldAs<std::vector<T> >(parentPath, fieldName);
4164         if (!vec.empty()) {
4165             T oldValue = vec.back();
4166             _stateDelegate->PopChild(parentPath, fieldName, oldValue);
4167         } else {
4168             TF_CODING_ERROR("SdfLayer::_PrimPopChild failed: field %s is "
4169                             "empty vector", fieldName.GetText());
4170         }
4171         return;
4172     }
4173 
4174     // See efficiency notes in _PrimPushChild().
4175     VtValue box = _data->Get(parentPath, fieldName);
4176     _data->Erase(parentPath, fieldName);
4177     if (!box.IsHolding<std::vector<T>>()) {
4178         TF_CODING_ERROR("SdfLayer::_PrimPopChild failed: field %s is "
4179                         "non-vector", fieldName.GetText());
4180         return;
4181     }
4182     std::vector<T> vec;
4183     box.Swap(vec);
4184     if (vec.empty()) {
4185         TF_CODING_ERROR("SdfLayer::_PrimPopChild failed: %s is empty",
4186                         fieldName.GetText());
4187         return;
4188     }
4189     vec.pop_back();
4190     box.Swap(vec);
4191     _data->Set(parentPath, fieldName, box);
4192 }
4193 
4194 template void SdfLayer::_PrimPopChild<TfToken>(
4195     const SdfPath&, const TfToken&, bool);
4196 template void SdfLayer::_PrimPopChild<SdfPath>(
4197     const SdfPath&, const TfToken&, bool);
4198 
4199 template <class T>
4200 void
_PrimSetFieldDictValueByKey(const SdfPath & path,const TfToken & fieldName,const TfToken & keyPath,const T & value,const VtValue * oldValuePtr,bool useDelegate)4201 SdfLayer::_PrimSetFieldDictValueByKey(const SdfPath& path,
4202                                       const TfToken& fieldName,
4203                                       const TfToken& keyPath,
4204                                       const T& value,
4205                                       const VtValue *oldValuePtr,
4206                                       bool useDelegate)
4207 {
4208     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4209         _stateDelegate->SetFieldDictValueByKey(
4210             path, fieldName, keyPath, value, oldValuePtr);
4211         return;
4212     }
4213 
4214     // Send notification when leaving the change block.
4215     SdfChangeBlock block;
4216 
4217     // This can't only use oldValuePtr currently, since we need the entire
4218     // dictionary, not just they key being set.  If we augment change
4219     // notification to be as granular as dict-key-path, we could use it.
4220     VtValue oldValue = GetField(path, fieldName);
4221 
4222     _data->SetDictValueByKey(path, fieldName, keyPath, value);
4223 
4224     VtValue newValue = GetField(path, fieldName);
4225 
4226     Sdf_ChangeManager::Get().DidChangeField(
4227         _self, path, fieldName, oldValue, newValue);
4228 }
4229 
4230 template void SdfLayer::_PrimSetFieldDictValueByKey(
4231     const SdfPath&, const TfToken&, const TfToken &,
4232     const VtValue&, const VtValue *, bool);
4233 template void SdfLayer::_PrimSetFieldDictValueByKey(
4234     const SdfPath&, const TfToken&, const TfToken &,
4235     const SdfAbstractDataConstValue&, const VtValue *, bool);
4236 
4237 bool
_MoveSpec(const SdfPath & oldPath,const SdfPath & newPath)4238 SdfLayer::_MoveSpec(const SdfPath &oldPath, const SdfPath &newPath)
4239 {
4240     TRACE_FUNCTION();
4241 
4242     if (!PermissionToEdit()) {
4243         TF_CODING_ERROR("Cannot move <%s> to <%s>. Layer @%s@ is not editable.",
4244                         oldPath.GetText(), newPath.GetText(),
4245                         GetIdentifier().c_str());
4246         return false;
4247     }
4248 
4249     if (oldPath.IsEmpty() || newPath.IsEmpty()) {
4250         TF_CODING_ERROR("Cannot move <%s> to <%s>. "
4251                         "Source and destination must be non-empty paths",
4252                         oldPath.GetText(), newPath.GetText());
4253         return false;
4254     }
4255 
4256     if (oldPath.HasPrefix(newPath) || newPath.HasPrefix(oldPath)) {
4257         TF_CODING_ERROR("Cannot move <%s> to <%s>. "
4258                         "Source and destination must not overlap",
4259                         oldPath.GetText(), newPath.GetText());
4260         return false;
4261     }
4262 
4263     if (!_data->HasSpec(oldPath)) {
4264         // Cannot move; nothing at source.
4265         return false;
4266     }
4267     if (_data->HasSpec(newPath)) {
4268         // Cannot move; destination exists.
4269         return false;
4270     }
4271 
4272     _PrimMoveSpec(oldPath, newPath);
4273 
4274     return true;
4275 }
4276 
4277 static void
_MoveSpecInternal(SdfAbstractDataRefPtr data,Sdf_IdentityRegistry * idReg,const SdfPath & oldSpecPath,const SdfPath & oldRootPath,const SdfPath & newRootPath)4278 _MoveSpecInternal(
4279     SdfAbstractDataRefPtr data, Sdf_IdentityRegistry* idReg,
4280     const SdfPath& oldSpecPath,
4281     const SdfPath& oldRootPath, const SdfPath& newRootPath)
4282 {
4283     const SdfPath newSpecPath =
4284         oldSpecPath.ReplacePrefix(
4285             oldRootPath, newRootPath, /* fixTargets = */ false);
4286 
4287     data->MoveSpec(oldSpecPath, newSpecPath);
4288     idReg->MoveIdentity(oldSpecPath, newSpecPath);
4289 }
4290 
4291 void
_PrimMoveSpec(const SdfPath & oldPath,const SdfPath & newPath,bool useDelegate)4292 SdfLayer::_PrimMoveSpec(const SdfPath& oldPath, const SdfPath& newPath,
4293                         bool useDelegate)
4294 {
4295     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4296         _stateDelegate->MoveSpec(oldPath, newPath);
4297         return;
4298     }
4299 
4300     SdfChangeBlock block;
4301 
4302     Sdf_ChangeManager::Get().DidMoveSpec(_self, oldPath, newPath);
4303 
4304     Traverse(oldPath, std::bind(_MoveSpecInternal, _data,
4305                                 &_idRegistry, ph::_1, oldPath, newPath));
4306 }
4307 
4308 static bool
_IsValidSpecForLayer(const SdfLayer & layer,SdfSpecType specType)4309 _IsValidSpecForLayer(
4310     const SdfLayer& layer, SdfSpecType specType)
4311 {
4312     const SdfSchemaBase::SpecDefinition* specDef =
4313         layer.GetSchema().GetSpecDefinition(specType);
4314     return static_cast<bool>(specDef);
4315 }
4316 
4317 bool
_CreateSpec(const SdfPath & path,SdfSpecType specType,bool inert)4318 SdfLayer::_CreateSpec(const SdfPath& path, SdfSpecType specType, bool inert)
4319 {
4320     if (specType == SdfSpecTypeUnknown) {
4321         return false;
4322     }
4323 
4324     if (!PermissionToEdit()) {
4325         TF_CODING_ERROR("Cannot create spec at <%s>. Layer @%s@ is not editable.",
4326                         path.GetText(),
4327                         GetIdentifier().c_str());
4328         return false;
4329     }
4330 
4331     if (_validateAuthoring && !_IsValidSpecForLayer(*this, specType)) {
4332         TF_ERROR(SdfAuthoringErrorUnrecognizedSpecType,
4333                  "Cannot create spec at <%s>. %s is not a valid spec type "
4334                  "for layer @%s@",
4335                  path.GetText(), TfEnum::GetName(specType).c_str(),
4336                  GetIdentifier().c_str());
4337         return false;
4338     }
4339 
4340     if (_data->HasSpec(path)) {
4341         TF_CODING_ERROR(
4342             "Cannot create spec <%s> because it already exists in @%s@",
4343             path.GetText(), GetIdentifier().c_str());
4344         return false;
4345     }
4346 
4347     _PrimCreateSpec(path, specType, inert);
4348 
4349     return true;
4350 }
4351 
4352 bool
_DeleteSpec(const SdfPath & path)4353 SdfLayer::_DeleteSpec(const SdfPath &path)
4354 {
4355     if (!PermissionToEdit()) {
4356         TF_CODING_ERROR("Cannot delete <%s>. Layer @%s@ is not editable",
4357                         path.GetText(),
4358                         GetIdentifier().c_str());
4359         return false;
4360     }
4361 
4362     if (!HasSpec(path)) {
4363         return false;
4364     }
4365 
4366     std::vector<SdfPath> inertSpecs;
4367     if (_IsInertSubtree(path, &inertSpecs)) {
4368         // If the subtree is inert, delete each inert spec from the
4369         // bottom up to send a notification for each inert spec in the
4370         // subtree. This is necessary since inert specs notices don't
4371         //imply anything about descendant specs. See also _SetData.
4372         SdfChangeBlock block;
4373 
4374         for (const SdfPath& inertSpecPath : inertSpecs) {
4375             if (inertSpecPath.IsPrimPath()) {
4376                 // Clear out prim and property children fields before calling
4377                 // _PrimDeleteSpec so that function doesn't try to recursively
4378                 // delete specs we've already deleted (since we're deleting
4379                 // from the bottom up).
4380                 VtValue val;
4381                 if (HasField(inertSpecPath,
4382                              SdfChildrenKeys->PrimChildren, &val)) {
4383                     _PrimSetField(
4384                         inertSpecPath, SdfChildrenKeys->PrimChildren,
4385                         VtValue(), &val);
4386                 }
4387 
4388                 if (HasField(inertSpecPath,
4389                              SdfChildrenKeys->PropertyChildren, &val)) {
4390                     _PrimSetField(
4391                         inertSpecPath, SdfChildrenKeys->PropertyChildren,
4392                         VtValue(), &val);
4393                 }
4394             }
4395 
4396             _PrimDeleteSpec(inertSpecPath, /* inert = */ true);
4397         }
4398     }
4399     else {
4400         _PrimDeleteSpec(path, /* inert = */ false);
4401     }
4402 
4403     return true;
4404 }
4405 
4406 template<typename ChildPolicy>
4407 void
_TraverseChildren(const SdfPath & path,const TraversalFunction & func)4408 SdfLayer::_TraverseChildren(const SdfPath &path, const TraversalFunction &func)
4409 {
4410     std::vector<typename ChildPolicy::FieldType> children =
4411         GetFieldAs<std::vector<typename ChildPolicy::FieldType> >(
4412             path, ChildPolicy::GetChildrenToken(path));
4413 
4414     TF_FOR_ALL(i, children) {
4415         Traverse(ChildPolicy::GetChildPath(path, *i), func);
4416     }
4417 }
4418 
4419 void
Traverse(const SdfPath & path,const TraversalFunction & func)4420 SdfLayer::Traverse(const SdfPath &path, const TraversalFunction &func)
4421 {
4422     std::vector<TfToken> fields = ListFields(path);
4423     TF_FOR_ALL(i, fields) {
4424         if (*i == SdfChildrenKeys->PrimChildren) {
4425             _TraverseChildren<Sdf_PrimChildPolicy>(path, func);
4426         } else if (*i == SdfChildrenKeys->PropertyChildren) {
4427             _TraverseChildren<Sdf_PropertyChildPolicy>(path, func);
4428         } else if (*i == SdfChildrenKeys->MapperChildren) {
4429             _TraverseChildren<Sdf_MapperChildPolicy>(path, func);
4430         } else if (*i == SdfChildrenKeys->MapperArgChildren) {
4431             _TraverseChildren<Sdf_MapperArgChildPolicy>(path, func);
4432         } else if (*i == SdfChildrenKeys->VariantChildren) {
4433             _TraverseChildren<Sdf_VariantChildPolicy>(path, func);
4434         } else if (*i == SdfChildrenKeys->VariantSetChildren) {
4435             _TraverseChildren<Sdf_VariantSetChildPolicy>(path, func);
4436         } else if (*i == SdfChildrenKeys->ConnectionChildren) {
4437             _TraverseChildren<Sdf_AttributeConnectionChildPolicy>(path, func);
4438         } else if (*i == SdfChildrenKeys->RelationshipTargetChildren) {
4439             _TraverseChildren<Sdf_RelationshipTargetChildPolicy>(path, func);
4440         } else if (*i == SdfChildrenKeys->ExpressionChildren) {
4441             _TraverseChildren<Sdf_ExpressionChildPolicy>(path, func);
4442         }
4443     }
4444 
4445     func(path);
4446 }
4447 
4448 static void
_EraseSpecAtPath(SdfAbstractData * data,const SdfPath & path)4449 _EraseSpecAtPath(SdfAbstractData* data, const SdfPath& path)
4450 {
4451     data->EraseSpec(path);
4452 }
4453 
4454 void
_PrimDeleteSpec(const SdfPath & path,bool inert,bool useDelegate)4455 SdfLayer::_PrimDeleteSpec(const SdfPath &path, bool inert, bool useDelegate)
4456 {
4457     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4458         _stateDelegate->DeleteSpec(path, inert);
4459         return;
4460     }
4461 
4462     SdfChangeBlock block;
4463 
4464     Sdf_ChangeManager::Get().DidRemoveSpec(_self, path, inert);
4465 
4466     TraversalFunction eraseFunc =
4467         std::bind(&_EraseSpecAtPath, boost::get_pointer(_data), ph::_1);
4468     Traverse(path, eraseFunc);
4469 }
4470 
4471 void
_PrimCreateSpec(const SdfPath & path,SdfSpecType specType,bool inert,bool useDelegate)4472 SdfLayer::_PrimCreateSpec(const SdfPath &path,
4473                           SdfSpecType specType, bool inert,
4474                           bool useDelegate)
4475 {
4476     if (useDelegate && TF_VERIFY(_stateDelegate)) {
4477         _stateDelegate->CreateSpec(path, specType, inert);
4478         return;
4479     }
4480 
4481     SdfChangeBlock block;
4482 
4483     Sdf_ChangeManager::Get().DidAddSpec(_self, path, inert);
4484 
4485     _data->CreateSpec(path, specType);
4486 }
4487 
4488 bool
_IsInert(const SdfPath & path,bool ignoreChildren,bool requiredFieldOnlyPropertiesAreInert) const4489 SdfLayer::_IsInert(const SdfPath &path, bool ignoreChildren,
4490                    bool requiredFieldOnlyPropertiesAreInert) const
4491 {
4492     // If the spec has only the required SpecType field (stored
4493     // separately from other fields), then it doesn't affect the scene.
4494     const std::vector<TfToken> fields = ListFields(path);
4495     if (fields.empty()) {
4496         return true;
4497     }
4498 
4499     // If the spec is custom it affects the scene.
4500     if (GetFieldAs<bool>(path, SdfFieldKeys->Custom, false)) {
4501         return false;
4502     }
4503 
4504     // Special cases for determining whether a spec affects the scene.
4505     const SdfSpecType specType = GetSpecType(path);
4506 
4507     // Prims that are defs or with a specific typename always affect the scene
4508     // since they bring a prim into existence.
4509     if (specType == SdfSpecTypePrim) {
4510         const SdfSpecifier specifier = GetFieldAs<SdfSpecifier>(
4511             path, SdfFieldKeys->Specifier, SdfSpecifierOver);
4512         if (SdfIsDefiningSpecifier(specifier)) {
4513             return false;
4514         }
4515 
4516         const TfToken type = GetFieldAs<TfToken>(path, SdfFieldKeys->TypeName);
4517         if (!type.IsEmpty()) {
4518             return false;
4519         }
4520     }
4521 
4522     // If we're not considering required-field-only properties as inert, then
4523     // properties should never be considered inert because they might exist to
4524     // instantiate an on-demand property.
4525     if (!requiredFieldOnlyPropertiesAreInert &&
4526         (specType == SdfSpecTypeAttribute    ||
4527          specType == SdfSpecTypeRelationship)) {
4528         return false;
4529     }
4530 
4531     // Prims and properties don't affect the scene if they only contain
4532     // opinions about required fields.
4533     if (specType == SdfSpecTypePrim         ||
4534         specType == SdfSpecTypeAttribute    ||
4535         specType == SdfSpecTypeRelationship) {
4536 
4537         const SdfSchema::SpecDefinition* specDefinition =
4538             GetSchema().GetSpecDefinition(specType);
4539         if (!TF_VERIFY(specDefinition)) {
4540             return false;
4541         }
4542 
4543         TF_FOR_ALL(field, fields) {
4544             // If specified, skip over prim name children and properties.
4545             // This is a special case to allow _IsInertSubtree to process
4546             // these children separately.
4547             if (specType == SdfSpecTypePrim && ignoreChildren) {
4548                 if (*field == SdfChildrenKeys->PrimChildren ||
4549                     *field == SdfChildrenKeys->PropertyChildren) {
4550                     continue;
4551                 }
4552             }
4553 
4554             if (specDefinition->IsRequiredField(*field)) {
4555                 continue;
4556             }
4557 
4558             return false;
4559         }
4560 
4561         return true;
4562     }
4563 
4564     return false;
4565 }
4566 
4567 bool
_IsInertSubtree(const SdfPath & path,std::vector<SdfPath> * inertSpecs)4568 SdfLayer::_IsInertSubtree(
4569     const SdfPath &path,
4570     std::vector<SdfPath>* inertSpecs)
4571 {
4572     if (!_IsInert(path, true /*ignoreChildren*/,
4573                   true /* requiredFieldOnlyPropertiesAreInert */)) {
4574         return false;
4575     }
4576 
4577     if (path.IsPrimPath()) {
4578         std::vector<TfToken> prims;
4579         if (HasField(path, SdfChildrenKeys->PrimChildren, &prims)) {
4580             for (const TfToken& child : prims) {
4581                 if (!_IsInertSubtree(path.AppendChild(child), inertSpecs)) {
4582                     return false;
4583                 }
4584             }
4585         }
4586 
4587         std::vector<TfToken> properties;
4588         if (HasField(path, SdfChildrenKeys->PropertyChildren, &properties)) {
4589             for (const TfToken& prop : properties) {
4590                 const SdfPath propPath = path.AppendProperty(prop);
4591                 if (!_IsInert(propPath,
4592                         /* ignoreChildren = */ false,
4593                         /* requiredFieldOnlyPropertiesAreInert = */ true)) {
4594                     return false;
4595                 }
4596                 else if (inertSpecs) {
4597                     inertSpecs->push_back(propPath);
4598                 }
4599             }
4600         }
4601     }
4602 
4603     if (inertSpecs) {
4604         inertSpecs->push_back(path);
4605     }
4606     return true;
4607 }
4608 
4609 bool
ExportToString(std::string * result) const4610 SdfLayer::ExportToString( std::string *result ) const
4611 {
4612     TRACE_FUNCTION();
4613 
4614     TF_DESCRIBE_SCOPE("Writing layer @%s@", GetIdentifier().c_str());
4615 
4616     return GetFileFormat()->WriteToString(*this, result);
4617 }
4618 
4619 bool
_WriteToFile(const string & newFileName,const string & comment,SdfFileFormatConstPtr fileFormat,const FileFormatArguments & args) const4620 SdfLayer::_WriteToFile(const string & newFileName,
4621                        const string &comment,
4622                        SdfFileFormatConstPtr fileFormat,
4623                        const FileFormatArguments& args) const
4624 {
4625     TRACE_FUNCTION();
4626 
4627     TF_DESCRIBE_SCOPE("Writing layer @%s@", GetIdentifier().c_str());
4628 
4629     if (newFileName.empty())
4630         return false;
4631 
4632     if ((newFileName == GetRealPath()) && !PermissionToSave()) {
4633         TF_RUNTIME_ERROR("Cannot save layer @%s@, saving not allowed",
4634                     newFileName.c_str());
4635         return false;
4636     }
4637 
4638     // If a file format was explicitly provided, use that regardless of the
4639     // file extension, else discover the file format from the file extension.
4640     if (!fileFormat) {
4641         const string ext = Sdf_GetExtension(newFileName);
4642         if (!ext.empty())
4643             fileFormat = SdfFileFormat::FindByExtension(ext);
4644 
4645         if (!fileFormat) {
4646             // Some parts of the system generate temp files
4647             // with garbage extensions, furthermore we do not restrict
4648             // users from writing to arbitrary file names, so here we must fall
4649             // back to the current file format associated with the layer.
4650             fileFormat = GetFileFormat();
4651         }
4652     }
4653 
4654     // Disallow saving or exporting package layers via the Sdf API.
4655     if (Sdf_IsPackageOrPackagedLayer(fileFormat, newFileName)) {
4656         TF_CODING_ERROR("Cannot save layer @%s@: writing %s %s layer "
4657                         "is not allowed through this API.",
4658                         newFileName.c_str(),
4659                         fileFormat->IsPackage() ? "package" : "packaged",
4660                         fileFormat->GetFormatId().GetText());
4661         return false;
4662     }
4663 
4664     if (!TF_VERIFY(fileFormat)) {
4665         TF_RUNTIME_ERROR("Unknown file format when attempting to write '%s'",
4666             newFileName.c_str());
4667         return false;
4668     }
4669 
4670 #if AR_VERSION == 1
4671     if (!ArGetResolver().CreatePathForLayer(newFileName)) {
4672         TF_RUNTIME_ERROR(
4673             "Cannot create path to write '%s'",
4674             newFileName.c_str());
4675         return false;
4676     }
4677 #endif
4678 
4679     // If the output file format has a different schema, then transfer content
4680     // to an in-memory layer first just to validate schema compatibility.
4681     const bool differentSchema = &fileFormat->GetSchema() != &GetSchema();
4682     if (differentSchema) {
4683         SdfLayerRefPtr tmpLayer =
4684             CreateAnonymous("cross-schema-write-test", fileFormat, args);
4685         TfErrorMark m;
4686         tmpLayer->TransferContent(
4687             SdfLayerHandle(const_cast<SdfLayer *>(this)));
4688         if (!m.IsClean()) {
4689             TF_RUNTIME_ERROR("Failed attempting to write '%s' under a "
4690                              "different schema.  If this is intended, "
4691                              "TransferContent() to a temporary anonymous "
4692                              "layer with the desired schema and handle "
4693                              "the errors, then export that temporary layer",
4694                              newFileName.c_str());
4695             return false;
4696         }
4697     }
4698 
4699     bool ok = fileFormat->WriteToFile(*this, newFileName, comment, args);
4700 
4701     // If we wrote to the backing file then we're now clean.
4702     if (ok && newFileName == GetRealPath()) {
4703        _MarkCurrentStateAsClean();
4704     }
4705 
4706     return ok;
4707 }
4708 
4709 bool
Export(const string & newFileName,const string & comment,const FileFormatArguments & args) const4710 SdfLayer::Export(const string& newFileName, const string& comment,
4711                  const FileFormatArguments& args) const
4712 {
4713     return _WriteToFile(
4714         newFileName,
4715         comment,
4716         // If the layer's current format supports the extension, use it,
4717         // otherwise pass TfNullPtr, which instructs the callee to use the
4718         // primary format for the output's extension.
4719         GetFileFormat()->IsSupportedExtension(newFileName)
4720             ? GetFileFormat() : TfNullPtr,
4721         args);
4722 }
4723 
4724 bool
Save(bool force) const4725 SdfLayer::Save(bool force) const
4726 {
4727     return _Save(force);
4728 }
4729 
4730 bool
_Save(bool force) const4731 SdfLayer::_Save(bool force) const
4732 {
4733     TRACE_FUNCTION();
4734 
4735     if (IsMuted()) {
4736         TF_CODING_ERROR("Cannot save muted layer @%s@",
4737                         GetIdentifier().c_str());
4738         return false;
4739     }
4740 
4741     if (IsAnonymous()) {
4742         TF_CODING_ERROR("Cannot save anonymous layer @%s@",
4743             GetIdentifier().c_str());
4744         return false;
4745     }
4746 
4747     const ArResolvedPath path = GetResolvedPath();
4748     if (path.empty())
4749         return false;
4750 
4751     // Skip saving if the file exists and the layer is clean.
4752     if (!force && !IsDirty() && TfPathExists(path))
4753         return true;
4754 
4755     if (!_WriteToFile(path, std::string(),
4756                       GetFileFormat(), GetFileFormatArguments()))
4757         return false;
4758 
4759     // Layer hints are invalidated by authoring so _hints must be reset now
4760     // that the layer has been marked as clean.  See GetHints().
4761     _hints = SdfLayerHints{};
4762 
4763     // Record modification timestamp.
4764     VtValue timestamp(ArGetResolver().GetModificationTimestamp(
4765         GetIdentifier(), path));
4766 #if AR_VERSION == 1
4767     if (timestamp.IsEmpty()) {
4768         TF_CODING_ERROR(
4769             "Unable to get modification timestamp for '%s (%s)'",
4770             GetIdentifier().c_str(), path.GetPathString().c_str());
4771         return false;
4772     }
4773 #endif
4774     _assetModificationTime.Swap(timestamp);
4775 
4776     SdfNotice::LayerDidSaveLayerToFile().Send(_self);
4777 
4778     return true;
4779 }
4780 
4781 PXR_NAMESPACE_CLOSE_SCOPE
4782