bool UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const _ClipFileVector& clipLayerFiles, const SdfPath& clipPath, const double startTimeCode, const double endTimeCode, const TfToken& clipSet) { // XXX: See comment in UsdUtilsStitchClipsTopology above. TF_PY_ALLOW_THREADS_IN_SCOPE(); // Prepare result layer for editing if (!_LayerIsWritable(resultLayer)) { return false; } else { resultLayer->Clear(); } // Prepare topology layer for editing, create if necessary bool topologyPreExisting = true; std::string topologyLayerId = UsdUtilsGenerateClipTopologyName(resultLayer->GetIdentifier()); SdfLayerRefPtr topologyLayer = SdfLayer::FindOrOpen(topologyLayerId); if (!topologyLayer) { topologyPreExisting = false; topologyLayer = SdfLayer::CreateNew(topologyLayerId); } if (!_LayerIsWritable(topologyLayer)) { return false; } else { topologyLayer->Clear(); } // Open all clip layers and validate clipPath SdfLayerRefPtrVector clipLayers; const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, clipLayerFiles, clipPath); if (!clipLayersAreValid || !_UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, clipPath, startTimeCode, endTimeCode, clipSet)) { if (!topologyPreExisting) { TfDeleteFile(topologyLayer->GetIdentifier()); } return false; } // Note that we don't apply edits until all other // actions have completed. topologyLayer->Save(); resultLayer->Save(); return true; }
bool UsdUtilsStitchClipsTemplate(const SdfLayerHandle& resultLayer, const SdfLayerHandle& topologyLayer, const SdfPath& clipPath, const std::string& templatePath, const double startTime, const double endTime, const double stride, const double activeOffset, const TfToken& clipSet) { // XXX: See comment in UsdUtilsStitchClipsTopology above. TF_PY_ALLOW_THREADS_IN_SCOPE(); if (!_LayerIsWritable(resultLayer)) { return false; } else { resultLayer->Clear(); } if (!topologyLayer) { return false; } // set prim level metadata auto prim = SdfCreatePrimInLayer(resultLayer, clipPath); const std::string topologyId = _GetRelativePathIfPossible(topologyLayer->GetIdentifier(), topologyLayer->GetRealPath(), resultLayer->GetRealPath()); // set root layer metadata _StitchClipsTopologySubLayerPath(resultLayer, topologyId); VtDictionary clipSetDict; clipSetDict[UsdClipsAPIInfoKeys->primPath] = clipPath.GetString(); clipSetDict[UsdClipsAPIInfoKeys->templateAssetPath] = templatePath; clipSetDict[UsdClipsAPIInfoKeys->templateStartTime] = startTime; clipSetDict[UsdClipsAPIInfoKeys->templateEndTime] = endTime; clipSetDict[UsdClipsAPIInfoKeys->templateStride] = stride; clipSetDict[UsdClipsAPIInfoKeys->manifestAssetPath] = SdfAssetPath(topologyId); if (activeOffset != std::numeric_limits<double>::max()) { clipSetDict[UsdClipsAPIInfoKeys->templateActiveOffset] = activeOffset; } VtDictionary clips; clips[clipSet] = clipSetDict; prim->SetInfo(UsdTokens->clips, VtValue::Take(clips)); resultLayer->SetStartTimeCode(startTime); resultLayer->SetEndTimeCode(endTime); resultLayer->Save(); return true; }
/* static */ void UsdKatanaCache::_SetMutedLayers( const UsdStageRefPtr &stage, const std::string &layerRegex) { // Trace this function to track its performance TRACE_FUNCTION(); // Unmute layers that are currently muted, but not requested to be muted SdfLayerHandleVector stageLayers = stage->GetUsedLayers(); bool regexIsEmpty = layerRegex == "" || layerRegex == "^$"; // use a better regex library? regex_t regex; regcomp(®ex, layerRegex.c_str(), REG_EXTENDED); regmatch_t* rmatch = 0; TF_FOR_ALL(stageLayer, stageLayers) { SdfLayerHandle layer = *stageLayer; if (!layer) { continue; } std::string layerPath = layer->GetRepositoryPath(); const std::string layerIdentifier = layer->GetIdentifier(); bool match = false; if (!regexIsEmpty) { if (layer && !regexec( ®ex, layerIdentifier.c_str(), 0, rmatch, 0)) { match = true; } } if (!match && stage->IsLayerMuted(layerIdentifier)) { TF_DEBUG(USDKATANA_CACHE_RENDERER).Msg("{USD RENDER CACHE} " "Unmuting Layer: '%s'\n", layerIdentifier.c_str()); stage->UnmuteLayer(layerIdentifier); } if (match && !stage->IsLayerMuted(layerIdentifier)) { TF_DEBUG(USDKATANA_CACHE_RENDERER).Msg("{USD RENDER CACHE} " "Muting Layer: '%s'\n", layerIdentifier.c_str()); stage->MuteLayer(layerIdentifier); } }
bool SdfCopySpec( const SdfLayerHandle& srcLayer, const SdfPath& srcPath, const SdfLayerHandle& dstLayer, const SdfPath& dstPath, const SdfShouldCopyValueFn& shouldCopyValueFn, const SdfShouldCopyChildrenFn& shouldCopyChildrenFn) { if (!srcLayer || !dstLayer) { TF_CODING_ERROR("Invalid layer handle"); return false; } if (srcPath.IsEmpty() || dstPath.IsEmpty()) { TF_CODING_ERROR("Invalid empty path"); return false; } // Validate compatible source and destination path types. if ((srcPath.IsAbsoluteRootOrPrimPath() || srcPath.IsPrimVariantSelectionPath()) != (dstPath.IsAbsoluteRootOrPrimPath() || dstPath.IsPrimVariantSelectionPath()) || srcPath.IsPropertyPath() != dstPath.IsPropertyPath() || srcPath.IsTargetPath() != dstPath.IsTargetPath() || srcPath.IsMapperPath() != dstPath.IsMapperPath() || srcPath.IsMapperArgPath() != dstPath.IsMapperArgPath() || srcPath.IsExpressionPath() != dstPath.IsExpressionPath()) { TF_CODING_ERROR("Incompatible source and destination paths"); return false; } // For target paths (relationship targets and connections), verify the // destination spec already exists. See the documentation comment. if (dstPath.IsTargetPath() && !dstLayer->HasSpec(dstPath)) { TF_CODING_ERROR("Spec does not exist at destination target path"); return false; } // This function collects all of the data that will be copied for each // spec into this list, then applies it to the layer at the very end. // This allows us to do some analysis on the data first. _CopyEntryList dataToCopy; // Create a stack of source/dest copy requests, initially populated with // the passed parameters. The copy routine will add additional requests // as needed to handle children etc... and runs until the stack is empty. _CopyStack copyStack(1, _CopyStackEntry(srcPath, dstPath)); while (!copyStack.empty()) { const _CopyStackEntry toCopy = copyStack.front(); copyStack.pop_front(); // If the source path is empty, it indicates that the spec at the // destination path should be removed. Add an entry to the queue // to reflect that. if (toCopy.srcPath.IsEmpty()) { _SpecDataEntry removeEntry(toCopy.dstPath, SdfSpecTypeUnknown); dataToCopy.push_back(removeEntry); continue; } // Figure out the concrete type of the spec we're copying. The spec type // dictates copying behavior below. const SdfSpecType specType = srcLayer->GetSpecType(toCopy.srcPath); if (specType == SdfSpecTypeUnknown) { TF_CODING_ERROR("Cannot copy unknown spec at <%s> from layer <%s>", srcPath.GetText(), srcLayer->GetIdentifier().c_str()); return false; } _SpecDataEntry copyEntry(toCopy.dstPath, specType); // Determine what data is present for the current source and dest specs // and what needs to be copied. Divide the present fields into those // that contain values and those that index children specs. std::vector<TfToken> dstValueFields; std::vector<TfToken> dstChildrenFields; _GetFieldNames( dstLayer, toCopy.dstPath, &dstValueFields, &dstChildrenFields); std::vector<TfToken> srcValueFields; std::vector<TfToken> srcChildrenFields; _GetFieldNames( srcLayer, toCopy.srcPath, &srcValueFields, &srcChildrenFields); // From the list of value fields, retrieve all values that the copy // policy says we need to copy over to the destination. _ForEachField( srcValueFields, dstValueFields, [&](const TfToken& field, bool fieldInSrc, bool fieldInDst) { _AddFieldValueToCopy( specType, field, srcLayer, toCopy.srcPath, fieldInSrc, dstLayer, toCopy.dstPath, fieldInDst, shouldCopyValueFn, ©Entry.dataToCopy); }); // Add an entry for all of the data we're copying for this spec. dataToCopy.push_back(copyEntry); // Now add any children specs that need to be copied to our // copy stack. _ForEachField( srcChildrenFields, dstChildrenFields, [&](const TfToken& field, bool fieldInSrc, bool fieldInDst) { _ProcessChildField( field, srcLayer, toCopy.srcPath, fieldInSrc, dstLayer, toCopy.dstPath, fieldInDst, shouldCopyChildrenFn, ©Stack); }); } // Now that we have all the data we want to copy, set it into the // destination layer. SdfChangeBlock block; for (const _SpecDataEntry& specData : dataToCopy) { if (specData.specType == SdfSpecTypeUnknown) { _RemoveSpecFromLayer(dstLayer, specData); } else { _AddNewSpecToLayer(dstLayer, specData); } for (const _FieldValuePair& fieldValue : specData.dataToCopy) { dstLayer->SetField( specData.dstPath, fieldValue.first, fieldValue.second); } } return true; }
bool UsdPrim::SetPayload(const SdfLayerHandle& layer, const SdfPath& primPath) const { return SetMetadata(SdfFieldKeys->Payload, SdfPayload(layer->GetIdentifier(), primPath)); }