// public facing API // ---------------------------------------------------------------------------- bool UsdUtilsStitchClipsTopology(const SdfLayerHandle& topologyLayer, const _ClipFileVector& clipLayerFiles) { // XXX: This is necessary for any C++ API which may be called though // python. Since this will spawn workers(in WorkParallelForN) which // will need to acquire the GIL, we need to explicitly release it. TF_PY_ALLOW_THREADS_IN_SCOPE(); // Prepare topology layer for editing if (!_LayerIsWritable(topologyLayer)) { return false; } else { topologyLayer->Clear(); } // Open all clip layers and validate clipPath SdfLayerRefPtrVector clipLayers; const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, clipLayerFiles, SdfPath::AbsoluteRootPath()); if (!clipLayersAreValid || !_UsdUtilsStitchClipsTopologyImpl(topologyLayer, clipLayers)) { return false; } topologyLayer->Save(); return true; }
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; }