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