void MultipleKnobEditsUndoCommand::redo() { // The first time, everything is handled within setValue/setValueAtTime already if (!firstRedoCalled) { firstRedoCalled = true; return; } assert( !knobs.empty() ); KnobHolderPtr holder = knobs.begin()->first.lock()->getHolder(); // Make sure we get a single evaluation if (holder) { holder->beginChanges(); } for (ParamsMap::iterator it = knobs.begin(); it != knobs.end(); ++it) { KnobIPtr knob = it->first.lock(); if (!knob) { continue; } if (it->second.empty()) { continue; } // All knobs must belong to the same node! assert(knob->getHolder() == holder); KnobIntBasePtr isInt = toKnobIntBase(knob); KnobBoolBasePtr isBool = toKnobBoolBase(knob); KnobDoubleBasePtr isDouble = toKnobDoubleBase(knob); KnobStringBasePtr isString = toKnobStringBase(knob); bool hasChanged = false; std::list<ValueToSet>::iterator next = it->second.begin(); ++next; if (it->second.size() > 1) { // block knobChanged handler for this knob until the last change so we don't clutter the main-thread with useless action calls knob->blockValueChanges(); } for (std::list<ValueToSet>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { if (next == it->second.end() && it->second.size() > 1) { // Re-enable knobChanged for the last change on this knob knob->unblockValueChanges(); } if (it2->setKeyFrame) { if (isInt) { it2->setValueRetCode = isInt->setValueAtTime(it2->time, it2->newValue.toInt(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isBool) { it2->setValueRetCode = isBool->setValueAtTime(it2->time, it2->newValue.toBool(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isDouble) { it2->setValueRetCode = isDouble->setValueAtTime(it2->time, it2->newValue.toDouble(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isString) { it2->setValueRetCode = isString->setValueAtTime(it2->time, it2->newValue.toString().toStdString(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else { assert(false); } } else { if (isInt) { it2->setValueRetCode = isInt->setValue(it2->newValue.toInt(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isBool) { it2->setValueRetCode = isBool->setValue(it2->newValue.toBool(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isDouble) { it2->setValueRetCode = isDouble->setValue(it2->newValue.toDouble(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else if (isString) { it2->setValueRetCode = isString->setValue(it2->newValue.toString().toStdString(), it2->view, it2->dimension, it2->reason, 0, hasChanged); } else { assert(false); } } hasChanged |= it2->setValueRetCode != eValueChangedReturnCodeNothingChanged; if (next != it->second.end()) { ++next; } } } if (holder) { holder->endChanges(); } } // redo
void MultipleKnobEditsUndoCommand::undo() { assert( !knobs.empty() ); KnobHolderPtr holder = knobs.begin()->first.lock()->getHolder(); if (holder) { holder->beginChanges(); } for (ParamsMap::iterator it = knobs.begin(); it != knobs.end(); ++it) { KnobIPtr knob = it->first.lock(); if (!knob) { continue; } if (it->second.empty()) { continue; } // All knobs must belong to the same node! assert(knob->getHolder() == holder); KnobIntBasePtr isInt = toKnobIntBase(knob); KnobBoolBasePtr isBool = toKnobBoolBase(knob); KnobDoubleBasePtr isDouble = toKnobDoubleBase(knob); KnobStringBasePtr isString = toKnobStringBase(knob); bool hasChanged = false; std::list<ValueToSet>::iterator next = it->second.begin(); ++next; if (it->second.size() > 1) { // block knobChanged handler for this knob until the last change so we don't clutter the main-thread with useless action calls knob->blockValueChanges(); } for (std::list<ValueToSet>::reverse_iterator it2 = it->second.rbegin(); it2 != it->second.rend(); ++it2) { if (next == it->second.end() && it->second.size() > 1) { // Re-enable knobChanged for the last change on this knob knob->unblockValueChanges(); } // If we added a keyframe (due to auto-keying or not) remove it if (it2->setValueRetCode == eValueChangedReturnCodeKeyframeAdded) { knob->deleteValueAtTime(it2->time, it2->view, it2->dimension, eValueChangedReasonUserEdited); } int nDims = knob->getNDimensions(); std::list<ViewIdx> allViews = knob->getViewsList(); if (it2->dimension.isAll()) { for (int i = 0; i < nDims; ++i) { if (it2->view.isAll()) { for (std::list<ViewIdx>::const_iterator it3 = allViews.begin(); it3!=allViews.end(); ++it3) { hasChanged |= setOldValueForDimView(isInt, isBool, isDouble, isString, it2->reason, it2->setKeyFrame, it2->time, hasChanged, it2->setValueRetCode, DimIdx(i), *it3, it2->oldValues) != eValueChangedReturnCodeNothingChanged; } } else { ViewIdx view_i = knob->getViewIdxFromGetSpec(ViewGetSpec(it2->view)); hasChanged |= setOldValueForDimView(isInt, isBool, isDouble, isString, it2->reason, it2->setKeyFrame, it2->time, hasChanged, it2->setValueRetCode, DimIdx(i), view_i, it2->oldValues) != eValueChangedReturnCodeNothingChanged; } } } else { if (it2->view.isAll()) { for (std::list<ViewIdx>::const_iterator it3 = allViews.begin(); it3!=allViews.end(); ++it3) { hasChanged |= setOldValueForDimView(isInt, isBool, isDouble, isString, it2->reason, it2->setKeyFrame, it2->time, hasChanged, it2->setValueRetCode, DimIdx(it2->dimension), *it3, it2->oldValues) != eValueChangedReturnCodeNothingChanged; } } else { ViewIdx view_i = knob->getViewIdxFromGetSpec(ViewGetSpec(it2->view)); hasChanged |= setOldValueForDimView(isInt, isBool, isDouble, isString, it2->reason, it2->setKeyFrame, it2->time, hasChanged, it2->setValueRetCode, DimIdx(it2->dimension), view_i, it2->oldValues) != eValueChangedReturnCodeNothingChanged; } } if (next != it->second.end()) { ++next; } } } // for all knobs if (holder) { holder->endChanges(); } } // MultipleKnobEditsUndoCommand::undo