Beispiel #1
0
PXR_NAMESPACE_OPEN_SCOPE


bool 
UsdUtilsCopyLayerMetadata(const SdfLayerHandle &source,
                          const SdfLayerHandle &destination,
                          bool skipSublayers)
{
    if (!TF_VERIFY(source && destination))
        return false;

    SdfPrimSpecHandle sourcePseudo = source->GetPseudoRoot();
    SdfPrimSpecHandle destPseudo = destination->GetPseudoRoot();
    
    std::vector<TfToken> infoKeys = sourcePseudo->ListInfoKeys();
    std::vector<TfToken>::iterator last = infoKeys.end();
    
    if (skipSublayers){
        last = std::remove_if(infoKeys.begin(), last,
                              [](TfToken key) { return (key == SdfFieldKeys->SubLayers || key == SdfFieldKeys->SubLayerOffsets); });
    }

    for (auto key = infoKeys.begin(); key != last; ++key){
        destPseudo->SetInfo(*key, sourcePseudo->GetInfo(*key));
    }

    return true;
}
Beispiel #2
0
// 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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/* 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(&regex, 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(
                &regex, 
                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);
        }
    }
Beispiel #5
0
void 
Sdf_ConnectionListEditor<ChildPolicy>::_OnEdit(
    SdfListOpType op,
    SdfSpecType specType,
    const std::vector<SdfPath>& oldItems, 
    const std::vector<SdfPath>& newItems) const
{
    if (op != SdfListOpTypeAdded and op != SdfListOpTypeExplicit) {
        return;
    }

    const SdfPath propertyPath = GetPath();
    SdfLayerHandle layer = GetLayer();
    const std::set<value_type> oldItemSet(oldItems.begin(), oldItems.end());
    const std::set<value_type> newItemSet(newItems.begin(), newItems.end());

    // Need to remove all children in oldItems that are not in newItems.
    std::vector<SdfPath> childrenToRemove;
    std::set_difference(oldItemSet.begin(), oldItemSet.end(),
                        newItemSet.begin(), newItemSet.end(), 
                        std::back_inserter(childrenToRemove));
    TF_FOR_ALL(child, childrenToRemove) {
        if (not Sdf_ChildrenUtils<ChildPolicy>::RemoveChild(
                layer, propertyPath, *child)) {

            const SdfPath specPath = 
                ChildPolicy::GetChildPath(propertyPath, *child);
            TF_CODING_ERROR("Failed to remove spec at <%s>", specPath.GetText());
        }
    }

    // Need to add all children in newItems that are not in oldItems.
    std::vector<SdfPath> childrenToAdd;
    std::set_difference(newItemSet.begin(), newItemSet.end(), 
                        oldItemSet.begin(), oldItemSet.end(),
                        std::back_inserter(childrenToAdd));
    TF_FOR_ALL(child, childrenToAdd) {
        const SdfPath specPath = ChildPolicy::GetChildPath(propertyPath, *child);
        if (layer->GetObjectAtPath(specPath)) {
            continue;
        }

        if (not Sdf_ChildrenUtils<ChildPolicy>::CreateSpec(layer, specPath,
                specType)) {
            TF_CODING_ERROR("Failed to create spec at <%s>", specPath.GetText());
        }
    }
}
Beispiel #6
0
string
SdfComputeAssetPathRelativeToLayer(
    const SdfLayerHandle& anchor,
    const string& assetPath)
{
    if (not anchor) {
        TF_CODING_ERROR("Invalid anchor layer");
        return string();
    }

    if (assetPath.empty()) {
        TF_CODING_ERROR("Layer path is empty");
        return string();
    }

    TRACE_FUNCTION();

    ArResolver& resolver = ArGetResolver();

    // Relative paths are resolved using the look-here-first scheme, in
    // which we first look relative to the layer, then fall back to search
    // path resolution.
    string finalLayerPath = anchor->ComputeAbsolutePath(assetPath);
    if (not SdfLayer::IsAnonymousLayerIdentifier(finalLayerPath)) {
        if (resolver.IsSearchPath(assetPath) and
            resolver.Resolve(finalLayerPath).empty())
            return assetPath;
    }
    
    return finalLayerPath;
}
Beispiel #7
0
static void
_ProcessChildren(
    const TfToken& childrenField, 
    const VtValue& srcChildrenValue, const VtValue& dstChildrenValue,
    const SdfLayerHandle& srcLayer, const SdfPath& srcPath, bool childrenInSrc,
    const SdfLayerHandle& dstLayer, const SdfPath& dstPath, bool childrenInDst,
    _CopyStack* copyStack)
{
    typedef typename ChildPolicy::FieldType FieldType;
    typedef std::vector<FieldType> ChildrenVector;

    if (!TF_VERIFY(srcChildrenValue.IsHolding<ChildrenVector>() || 
                   srcChildrenValue.IsEmpty()) ||
        !TF_VERIFY(dstChildrenValue.IsHolding<ChildrenVector>() || 
                   dstChildrenValue.IsEmpty())) {
        return;
    }

    const ChildrenVector emptyChildren;
    const ChildrenVector& srcChildren = srcChildrenValue.IsEmpty() ? 
        emptyChildren : srcChildrenValue.UncheckedGet<ChildrenVector>();
    const ChildrenVector& dstChildren = dstChildrenValue.IsEmpty() ? 
        emptyChildren : dstChildrenValue.UncheckedGet<ChildrenVector>();

    for (size_t i = 0; i < srcChildren.size(); ++i) {
        if (srcChildren[i].IsEmpty() || dstChildren[i].IsEmpty()) {
            continue;
        }

        const SdfPath srcChildPath = 
            ChildPolicy::GetChildPath(srcPath, srcChildren[i]);
        const SdfPath dstChildPath = 
            ChildPolicy::GetChildPath(dstPath, dstChildren[i]);

        copyStack->emplace_back(srcChildPath, dstChildPath);
    }

    // Add entries to the copy stack to mark the removal of child specs
    // in the destination layer that aren't included in the list of children
    // to copy.
    if (childrenInDst) {
        const VtValue oldDstChildrenValue = 
            dstLayer->GetField(dstPath, childrenField);
        if (!TF_VERIFY(oldDstChildrenValue.IsHolding<ChildrenVector>())) {
            return;
        }

        for (const auto& oldDstChild : 
                 oldDstChildrenValue.UncheckedGet<ChildrenVector>()) {
            if (std::find(dstChildren.begin(), dstChildren.end(), 
                    oldDstChild) == dstChildren.end()) {
                
                const SdfPath oldDstChildPath = 
                    ChildPolicy::GetChildPath(dstPath, oldDstChild);
                copyStack->emplace_back(SdfPath(), oldDstChildPath);
            }
        }
    }
}
Beispiel #8
0
SdfPathVector 
Sdf_MarkerUtils<Spec>::GetMarkerPaths(const Spec& owner)
{
    SdfPathVector paths;

    const SdfLayerHandle layer = owner.GetLayer();
    const SdfPathVector children = owner.template GetFieldAs<SdfPathVector>(
        _MarkerPolicy::GetChildFieldKey());

    TF_FOR_ALL(path, children) {
        const SdfPath targetSpecPath = owner.GetPath().AppendTarget(*path);
        if (layer->HasField(targetSpecPath, SdfFieldKeys->Marker)) {
            paths.push_back(*path);
        }
    }

    return paths;
}
Beispiel #9
0
void
SdfFileFormat::_SetLayerData(
    const SdfLayerHandle& layer,
    SdfAbstractDataRefPtr& data)
{
    // If layer initialization has not completed, then this
    // is being loaded as a new layer; otherwise we are loading
    // data into an existing layer.
    //
    // Note that this is an optional::bool and we are checking if it has
    // been set, not what its held value is.
    //
    const bool layerIsLoadingAsNew = !layer->_initializationWasSuccessful;
    if (layerIsLoadingAsNew) {
        layer->_SwapData(data);
    }
    else {
        layer->_SetData(data);
    }
}
Beispiel #10
0
// Returns lists of value and children field names to be handled during
// the copy process. The returned lists are sorted using the
// TfTokenFastArbitraryLessThan comparator.
static
void
_GetFieldNames(
    const SdfLayerHandle& layer, const SdfPath& path, 
    std::vector<TfToken>* valueFields, 
    std::vector<TfToken>* childrenFields)
{
    const SdfSchemaBase& schema = layer->GetSchema();
    const std::vector<TfToken> allFields = layer->ListFields(path);
    for (const TfToken& field : allFields) {
        if (schema.HoldsChildren(field)) {
            childrenFields->push_back(field);
        }
        else {
            valueFields->push_back(field);
        }
    }

    TfTokenFastArbitraryLessThan lessThan;
    std::sort(valueFields->begin(), valueFields->end(), lessThan);
    std::sort(childrenFields->begin(), childrenFields->end(), lessThan);
}
Beispiel #11
0
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;
}
Beispiel #12
0
bool 
UsdMtlxFileFormat::ReadFromString(
    const SdfLayerBasePtr& layerBase,
    const std::string& str) const
{
    TRACE_FUNCTION();

    SdfLayerHandle layer = TfDynamic_cast<SdfLayerHandle>(layerBase);
    if (!TF_VERIFY(layer)) {
        return false;
    }

    auto stage = UsdStage::CreateInMemory();
    if (!_Read(stage,
               [&str](mx::DocumentPtr d) {
                    mx::readFromXmlString(d, str);
               })) {
        return false;
    }

    layer->TransferContent(stage->GetRootLayer());
    return true;
}
Beispiel #13
0
// Add a (field, value) entry to the list of fields to copy as directed by
// the given policy. The value may be empty to indicate that the field
// should be removed from the destination.
static void
_AddFieldValueToCopy(
    SdfSpecType specType, const TfToken& field,
    const SdfLayerHandle& srcLayer, const SdfPath& srcPath, bool fieldInSrc,
    const SdfLayerHandle& dstLayer, const SdfPath& dstPath, bool fieldInDst,
    const SdfShouldCopyValueFn& shouldCopyValue, _FieldValueList* valueList)
{
    boost::optional<VtValue> value;
    if (shouldCopyValue(
            specType, field, 
            srcLayer, srcPath, fieldInSrc, dstLayer, dstPath, fieldInDst, 
            &value)) {

        valueList->emplace_back(
            field, value ? *value : srcLayer->GetField(srcPath, field));
    }
}
Beispiel #14
0
static void
_AddNewSpecToLayer(
    const SdfLayerHandle& destLayer, const _SpecDataEntry& specData)
{
    if (destLayer->HasSpec(specData.dstPath)) {
        return;
    }

    switch (specData.specType) {
    case SdfSpecTypeAttribute:
        _DoAddNewPropertySpec<Sdf_AttributeChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeConnection:
        _DoAddNewSpec<Sdf_AttributeConnectionChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeExpression:
        _DoAddNewSpec<Sdf_ExpressionChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeMapper:
        _DoAddNewSpec<Sdf_MapperChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeMapperArg:
        _DoAddNewSpec<Sdf_MapperArgChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypePrim:
        _DoAddNewPrimSpec(destLayer, specData);
        break;
    case SdfSpecTypeRelationship:
        _DoAddNewPropertySpec<Sdf_RelationshipChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeRelationshipTarget:
        _DoAddNewSpec<Sdf_RelationshipTargetChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeVariant:
        _DoAddNewSpec<Sdf_VariantChildPolicy>(destLayer, specData);
        break;
    case SdfSpecTypeVariantSet:
        _DoAddNewSpec<Sdf_VariantSetChildPolicy>(destLayer, specData);
        break;

    case SdfSpecTypePseudoRoot:
    case SdfSpecTypeUnknown:
    case SdfNumSpecTypes:
        break;
    }
}
Beispiel #15
0
static void
_RemoveSpecFromLayer(
    const SdfLayerHandle& dstLayer, const _SpecDataEntry& specData)
{
    switch (dstLayer->GetSpecType(specData.dstPath)) {
    case SdfSpecTypeAttribute:
        _DoRemoveSpec<Sdf_AttributeChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeConnection:
        _DoRemoveSpec<Sdf_AttributeConnectionChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeExpression:
        _DoRemoveSpec<Sdf_ExpressionChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeMapper:
        _DoRemoveSpec<Sdf_MapperChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeMapperArg:
        _DoRemoveSpec<Sdf_MapperArgChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypePrim:
        _DoRemoveSpec<Sdf_PrimChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeRelationship:
        _DoRemoveSpec<Sdf_RelationshipChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeRelationshipTarget:
        _DoRemoveSpec<Sdf_RelationshipTargetChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeVariant:
        _DoRemoveSpec<Sdf_VariantChildPolicy>(dstLayer, specData);
        break;
    case SdfSpecTypeVariantSet:
        _DoRemoveSpec<Sdf_VariantSetChildPolicy>(dstLayer, specData);
        break;

    case SdfSpecTypePseudoRoot:
    case SdfSpecTypeUnknown:
    case SdfNumSpecTypes:
        break;
    }
}
Beispiel #16
0
Sdf_SubLayerListEditor::Sdf_SubLayerListEditor(
    const SdfLayerHandle& owner)
    : Parent(owner->GetPseudoRoot(), 
             SdfFieldKeys->SubLayers, SdfListOpTypeOrdered)
{
}
Beispiel #17
0
static
RootPrimsProxy
_WrapGetRootPrims(const SdfLayerHandle& layer)
{
    return RootPrimsProxy(layer->GetRootPrims(), "prim");
}
Beispiel #18
0
SdfAbstractDataConstPtr
SdfFileFormat::_GetLayerData(const SdfLayerHandle& layer)
{
    return layer->_GetData();
}
Beispiel #19
0
static bool
_WrapIsMuted(const SdfLayerHandle &layer)
{
    return layer->IsMuted();
}
Beispiel #20
0
bool
UsdPrim::SetPayload(const SdfLayerHandle& layer, const SdfPath& primPath) const
{
    return SetMetadata(SdfFieldKeys->Payload,
                       SdfPayload(layer->GetIdentifier(), primPath));
}
Beispiel #21
0
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, &copyEntry.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, &copyStack);
            });
    }

    // 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;
}
Beispiel #22
0
static void
_ProcessChildField(
    const TfToken& childField, 
    const SdfLayerHandle& srcLayer, const SdfPath& srcPath, bool childrenInSrc,
    const SdfLayerHandle& dstLayer, const SdfPath& dstPath, bool childrenInDst,
    const SdfShouldCopyChildrenFn& shouldCopyChildren, _CopyStack* copyStack)
{
    boost::optional<VtValue> srcChildrenToCopy, dstChildrenToCopy;
    if (!shouldCopyChildren(
            childField, 
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            &srcChildrenToCopy, &dstChildrenToCopy)) {
        return;
    }

    if (!srcChildrenToCopy || !dstChildrenToCopy) {
        srcChildrenToCopy = srcLayer->GetField(srcPath, childField);
        dstChildrenToCopy = srcChildrenToCopy;
    }

    const VtValue& srcChildren = *srcChildrenToCopy;
    const VtValue& dstChildren = *dstChildrenToCopy;

    if (childField == SdfChildrenKeys->ConnectionChildren) {
        _ProcessChildren<Sdf_AttributeConnectionChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->MapperChildren) {
        _ProcessChildren<Sdf_MapperChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->MapperArgChildren) {
        _ProcessChildren<Sdf_MapperArgChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->ExpressionChildren) {
        _ProcessChildren<Sdf_ExpressionChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->RelationshipTargetChildren) {
        _ProcessChildren<Sdf_RelationshipTargetChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->VariantChildren) {
        _ProcessChildren<Sdf_VariantChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->VariantSetChildren) {
        _ProcessChildren<Sdf_VariantSetChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->PropertyChildren) {
        _ProcessChildren<Sdf_PropertyChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }
    if (childField == SdfChildrenKeys->PrimChildren) {
        _ProcessChildren<Sdf_PrimChildPolicy>(
            childField, srcChildren, dstChildren,
            srcLayer, srcPath, childrenInSrc, dstLayer, dstPath, childrenInDst,
            copyStack);
        return;
    }

    TF_CODING_ERROR("Unknown child field '%s'", childField.GetText());
}
void 
Sdf_ConnectionListEditor<ChildPolicy>::_OnEditShared(
    SdfListOpType op,
    SdfSpecType specType,
    const std::vector<SdfPath>& oldItems, 
    const std::vector<SdfPath>& newItems) const
{
    // XXX The following code tries to manage lifetime of the target
    // specs associated with this list, but it slightly buggy: if
    // multiple lists mention the same target -- ex. if a target is
    // added, appended, and prepended -- then this proxy for a single
    // list has no way to know if the target also exists in those
    // other lists, and so it cannot mangae lifetime on its own.

    if (op == SdfListOpTypeOrdered || op == SdfListOpTypeDeleted) {
        // These ops do not affect target spec lifetime, so there's
        // nothing to do.
        return;
    }

    const SdfPath propertyPath = GetPath();
    SdfLayerHandle layer = GetLayer();
    const std::set<value_type> oldItemSet(oldItems.begin(), oldItems.end());
    const std::set<value_type> newItemSet(newItems.begin(), newItems.end());

    // Need to remove all children in oldItems that are not in newItems.
    std::vector<SdfPath> childrenToRemove;
    std::set_difference(oldItemSet.begin(), oldItemSet.end(),
                        newItemSet.begin(), newItemSet.end(), 
                        std::back_inserter(childrenToRemove));
    TF_FOR_ALL(child, childrenToRemove) {
        if (!Sdf_ChildrenUtils<ChildPolicy>::RemoveChild(
                layer, propertyPath, *child)) {
            // Some data backends procedurally generate the children specs based
            // on the listops as an optimization, so if we failed to remove a
            // child here, it could be that.  If no spec is present, then we
            // consider things to be okay and do not issue an error.
            const SdfPath specPath = 
                ChildPolicy::GetChildPath(propertyPath, *child);
            if (layer->GetObjectAtPath(specPath)) {
                TF_CODING_ERROR("Failed to remove spec at <%s>",
                                specPath.GetText());
            }
        }
    }

    // Need to add all children in newItems that are not in oldItems.
    std::vector<SdfPath> childrenToAdd;
    std::set_difference(newItemSet.begin(), newItemSet.end(), 
                        oldItemSet.begin(), oldItemSet.end(),
                        std::back_inserter(childrenToAdd));
    TF_FOR_ALL(child, childrenToAdd) {
        const SdfPath specPath = ChildPolicy::GetChildPath(propertyPath, *child);
        if (layer->GetObjectAtPath(specPath)) {
            continue;
        }

        if (!Sdf_ChildrenUtils<ChildPolicy>::CreateSpec(layer, specPath,
                specType)) {
            TF_CODING_ERROR("Failed to create spec at <%s>", specPath.GetText());
        }
    }
}