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()); } } }
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()); } } }