void PasteKnobClipBoardUndoCommand::copyFrom(const SERIALIZATION_NAMESPACE::KnobSerializationPtr& serializedKnob, const KnobIPtr& fromKnob, bool isRedo) { KnobIPtr internalKnob = _imp->knob.lock(); if (!internalKnob) { return; } // Get the target type KnobIntBasePtr isInt = toKnobIntBase( internalKnob ); KnobBoolBasePtr isBool = toKnobBoolBase( internalKnob ); KnobDoubleBasePtr isDouble = toKnobDoubleBase( internalKnob ); KnobStringBasePtr isString = toKnobStringBase( internalKnob ); // Get view names std::vector<std::string> projectViewNames; if (internalKnob->getHolder() && internalKnob->getHolder()->getApp()) { projectViewNames = internalKnob->getHolder()->getApp()->getProject()->getProjectViewNames(); } // group changes under the same evaluation internalKnob->beginChanges(); std::list<ViewIdx> targetKnobViews = internalKnob->getViewsList(); StringAnimationManagerPtr fromAnimString; if (fromKnob) { fromAnimString = fromKnob->getStringAnimation(); } for (std::list<ViewIdx>::const_iterator it = targetKnobViews.begin(); it != targetKnobViews.end(); ++it) { if ( ( !_imp->targetView.isAll()) && ( *it != _imp->targetView) ) { continue; } // If dimensions are folded, expand them when linking if (_imp->targetDimension.isAll() && !internalKnob->getAllDimensionsVisible(*it)) { internalKnob->setAllDimensionsVisible(*it, true); } for (int i = 0; i < internalKnob->getNDimensions(); ++i) { if ( ( !_imp->targetDimension.isAll()) && ( i != _imp->targetDimension) ) { continue; } ViewIdx fromView; DimIdx fromDim; if ( !_imp->targetDimension.all() && !_imp->fromDimension.isAll() ) { fromDim = DimIdx(_imp->fromDimension); } else { // If the source knob dimension is all or target dimension is all copy dimension to dimension respectively fromDim = DimIdx(i); } if ( !_imp->targetView.isAll() && !_imp->fromView.isAll() ) { fromView = ViewIdx(_imp->fromView); } else { // If the source knob view is all or target view is all copy view to view respectively fromView = *it; } switch (_imp->type) { case eKnobClipBoardTypeCopyAnim: { std::string fromViewName; if (fromView >= 0 && fromView < (int)projectViewNames.size()) { fromViewName = projectViewNames[_imp->fromView]; } else { fromViewName = "Main"; } SERIALIZATION_NAMESPACE::KnobSerialization::PerViewValueSerializationMap::const_iterator foundFromView = serializedKnob->_values.find(fromViewName); if (foundFromView == serializedKnob->_values.end()) { continue; } if (fromDim < 0 || fromDim >= (int) foundFromView->second.size()) { continue; } // Read the curve from the clipboard CurvePtr fromCurve(new Curve()); if (!foundFromView->second[_imp->fromDimension]._animationCurve.keys.empty()) { fromCurve->fromSerialization(foundFromView->second[_imp->fromDimension]._animationCurve); } internalKnob->cloneCurve(*it, DimIdx(i), *fromCurve, 0 /*offset*/, 0 /*range*/, fromAnimString.get()); break; } case eKnobClipBoardTypeCopyValue: { std::string fromViewName; if (fromView >= 0 && fromView < (int)projectViewNames.size()) { fromViewName = projectViewNames[_imp->fromView]; } else { fromViewName = "Main"; } SERIALIZATION_NAMESPACE::KnobSerialization::PerViewValueSerializationMap::const_iterator foundFromView = serializedKnob->_values.find(fromViewName); if (foundFromView == serializedKnob->_values.end()) { continue; } if (fromDim < 0 || fromDim >= (int) foundFromView->second.size()) { continue; } internalKnob->restoreValueFromSerialization(foundFromView->second[fromDim], DimIdx(i), *it); break; } case eKnobClipBoardTypeCopyLink: { if (isRedo) { internalKnob->slaveTo(fromKnob, DimIdx(i), fromDim, *it, fromView); } else { internalKnob->unSlave(DimIdx(i), *it, false /*copyState*/); } break; } case eKnobClipBoardTypeCopyExpressionLink: case eKnobClipBoardTypeCopyExpressionMultCurveLink: { if (isRedo) { std::string expression = makeLinkExpression(projectViewNames, internalKnob, _imp->type == eKnobClipBoardTypeCopyExpressionMultCurveLink, fromKnob, _imp->fromDimension, _imp->fromView, _imp->targetDimension, _imp->targetView); const bool hasRetVar = false; try { // Don't fail if exception is invalid, it should have been tested prior to creating an undo/redo command, otherwise user is going // to hit CTRL-Z and nothing will happen internalKnob->setExpression(DimIdx(i), *it, expression, hasRetVar, /*failIfInvalid*/ false); } catch (...) { } } else { // !isRedo internalKnob->clearExpression(DimIdx(i), *it, true); } // isRedo break; } }; // switch } // for all dimensions } // for all views internalKnob->endChanges(); } // redo