From kde-commits Wed Nov 30 23:06:22 2016 From: Jean-Baptiste Mardelle Date: Wed, 30 Nov 2016 23:06:22 +0000 To: kde-commits Subject: [kdenlive/Applications/16.12] src: Fix many issues with volume keyframes Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=148054719230792 Git commit b348355e43285c37456bfc2625a055811b790b8f by Jean-Baptiste Mardel= le. Committed on 30/11/2016 at 23:05. Pushed by mardelle into branch 'Applications/16.12'. Fix many issues with volume keyframes M +1 -1 src/doc/documentvalidator.cpp M +5 -5 src/effectstack/widgets/animationwidget.cpp M +1 -1 src/effectstack/widgets/animationwidget.h M +11 -9 src/mltcontroller/effectscontroller.cpp M +6 -5 src/timeline/abstractclipitem.cpp M +3 -5 src/timeline/clipitem.cpp M +1 -2 src/timeline/customtrackview.cpp M +1 -2 src/timeline/effectmanager.cpp M +62 -7 src/timeline/keyframeview.cpp M +2 -0 src/timeline/keyframeview.h M +3 -3 src/timeline/track.cpp https://commits.kde.org/kdenlive/b348355e43285c37456bfc2625a055811b790b8f diff --git a/src/doc/documentvalidator.cpp b/src/doc/documentvalidator.cpp index 595f76f..7e524d6 100644 --- a/src/doc/documentvalidator.cpp +++ b/src/doc/documentvalidator.cpp @@ -1497,7 +1497,7 @@ bool DocumentValidator::upgrade(double version, const= double currentVersion) } } EffectsList::setProperty(eff, conversionParams.at(2), = parsedValues.join(";")); - EffectsList::setProperty(eff, QStringLiteral("kdenlive= :sync_in_out"), QStringLiteral("1")); + //EffectsList::setProperty(eff, QStringLiteral("kdenli= ve:sync_in_out"), QStringLiteral("1")); eff.setAttribute(QStringLiteral("out"), out); } } diff --git a/src/effectstack/widgets/animationwidget.cpp b/src/effectstack/= widgets/animationwidget.cpp index 71ab9d2..aaffa78 100644 --- a/src/effectstack/widgets/animationwidget.cpp +++ b/src/effectstack/widgets/animationwidget.cpp @@ -232,9 +232,9 @@ void AnimationWidget::finishSetup() } = //static -QString AnimationWidget::getDefaultKeyframes(const QString &defaultValue, = bool linearOnly) +QString AnimationWidget::getDefaultKeyframes(int start, const QString &def= aultValue, bool linearOnly) { - QString keyframes =3D QStringLiteral("0"); + QString keyframes =3D QString::number(start); if (linearOnly) { keyframes.append(QStringLiteral("=3D")); } else { @@ -671,7 +671,7 @@ void AnimationWidget::addParameter(const QDomElement &e) keyframes =3D e.attribute(QStringLiteral("value")); } if (keyframes.isEmpty()) { - keyframes =3D getDefaultKeyframes(e.attribute(QStringLiteral("defa= ult"))); + keyframes =3D getDefaultKeyframes(m_inPoint, e.attribute(QStringLi= teral("default"))); if (keyframes.contains('%')) { keyframes =3D EffectsController::getStringRectEval(m_monitor->= profileInfo(), keyframes); } @@ -1012,7 +1012,7 @@ void AnimationWidget::loadPresets(QString currentText) QMap defaultEntry; QStringList paramNames =3D m_doubleWidgets.keys(); for (int i =3D 0; i < paramNames.count(); i++) { - defaultEntry.insert(paramNames.at(i), getDefaultKeyframes(m_params= .at(i).attribute(QStringLiteral("default")))); + defaultEntry.insert(paramNames.at(i), getDefaultKeyframes(m_inPoin= t, m_params.at(i).attribute(QStringLiteral("default")))); } m_presetCombo->addItem(i18n("Default"), defaultEntry); loadPreset(dir.absoluteFilePath(m_xml.attribute(QStringLiteral("type")= ))); @@ -1304,7 +1304,7 @@ void AnimationWidget::reload(const QString &tag, cons= t QString &data) if (!m_rectParameter.isEmpty() && tag !=3D m_rectParameter) { // reset geometry keyframes // simple anim parameter, get default value - QString def =3D getDefaultKeyframes(defaultValue(m_rectParameter)); + QString def =3D getDefaultKeyframes(m_inPoint, defaultValue(m_rect= Parameter)); // Clear current keyframes m_animProperties.set(m_rectParameter.toUtf8().constData(), def.toU= tf8().constData()); // Add default keyframes diff --git a/src/effectstack/widgets/animationwidget.h b/src/effectstack/wi= dgets/animationwidget.h index 4e13503..869dae5 100644 --- a/src/effectstack/widgets/animationwidget.h +++ b/src/effectstack/widgets/animationwidget.h @@ -51,7 +51,7 @@ public: void updateTimecodeFormat(); void addParameter(const QDomElement &e); const QMap getAnimation(); - static QString getDefaultKeyframes(const QString &defaultValue, bool l= inearOnly =3D false); + static QString getDefaultKeyframes(int start, const QString &defaultVa= lue, bool linearOnly =3D false); void setActiveKeyframe(int frame); void finishSetup(); /** @brief Returns true if currently active param is name */ diff --git a/src/mltcontroller/effectscontroller.cpp b/src/mltcontroller/ef= fectscontroller.cpp index 2bc2ec9..026092f 100644 --- a/src/mltcontroller/effectscontroller.cpp +++ b/src/mltcontroller/effectscontroller.cpp @@ -103,8 +103,9 @@ EffectsParameterList EffectsController::getEffectArgs(c= onst ProfileInfo &info, c parameters.addParam(QStringLiteral("tag"), effect.attribute(QStringLit= eral("tag"))); //if (effect.hasAttribute("region")) parameters.addParam("region", eff= ect.attribute("region")); parameters.addParam(QStringLiteral("kdenlive_ix"), effect.attribute(QS= tringLiteral("kdenlive_ix"))); - if (effect.hasAttribute(QStringLiteral("sync_in_out"))) + if (effect.hasAttribute(QStringLiteral("sync_in_out"))) { parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), effect= .attribute(QStringLiteral("sync_in_out"))); + } parameters.addParam(QStringLiteral("kdenlive_info"), effect.attribute(= QStringLiteral("kdenlive_info"))); parameters.addParam(QStringLiteral("id"), effect.attribute(QStringLite= ral("id"))); if (effect.hasAttribute(QStringLiteral("src"))) parameters.addParam(QS= tringLiteral("src"), effect.attribute(QStringLiteral("src"))); @@ -137,10 +138,11 @@ void EffectsController::adjustEffectParameters(Effect= sParameterList ¶meters, for (int i =3D 0; i < params.count(); ++i) { QDomElement e =3D params.item(i).toElement(); QString paramname =3D prefix + e.attribute(QStringLiteral("name")); - if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1String("anim= ated") || (e.attribute(QStringLiteral("type")) =3D=3D QLatin1String("geomet= ry") && !e.hasAttribute(QStringLiteral("fixed")))) { + /*if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1String("an= imated") || (e.attribute(QStringLiteral("type")) =3D=3D QLatin1String("geom= etry") && !e.hasAttribute(QStringLiteral("fixed")))) { // effects with geometry param need in / out synced with the c= lip, request it... - //parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), = QStringLiteral("1")); - } + parameters.addParam(QStringLiteral("kdenlive:sync_in_out"), QS= tringLiteral("1")); + qDebug()<<" ** * ADDIN EFFECT ANIM SYN TRUE"; + }*/ if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1String("anim= ated")) { parameters.addParam(paramname, e.attribute(QStringLiteral("val= ue"))); } else if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1Strin= g("simplekeyframe")) { @@ -229,7 +231,7 @@ void EffectsController::initTrackEffect(ProfileInfo pIn= fo, QDomElement effect) bool hasValue =3D e.hasAttribute(QStringLiteral("value")); // Check if this effect has a variable parameter, init effects def= ault value if ((type =3D=3D QLatin1String("animatedrect") || type =3D=3D QLat= in1String("geometry")) && !hasValue) { - QString kfr =3D AnimationWidget::getDefaultKeyframes(e.attribu= te(QStringLiteral("default")), type =3D=3D QLatin1String("geometry")); + QString kfr =3D AnimationWidget::getDefaultKeyframes(0, e.attr= ibute(QStringLiteral("default")), type =3D=3D QLatin1String("geometry")); if (kfr.contains("%")) { kfr =3D EffectsController::getStringRectEval(pInfo, kfr); } @@ -244,7 +246,7 @@ void EffectsController::initTrackEffect(ProfileInfo pIn= fo, QDomElement effect) } else e.setAttribute(QStringLiteral("value"), evaluatedValue); } else { if (type =3D=3D QLatin1String("animated") && !hasValue) { - e.setAttribute(QStringLiteral("value"), AnimationWidget::g= etDefaultKeyframes(e.attribute(QStringLiteral("default")))); + e.setAttribute(QStringLiteral("value"), AnimationWidget::g= etDefaultKeyframes(0, e.attribute(QStringLiteral("default")))); } else if (!hasValue) { e.setAttribute(QStringLiteral("value"), e.attribute(QStrin= gLiteral("default"))); @@ -273,7 +275,7 @@ void EffectsController::initEffect(ItemInfo info, Profi= leInfo pInfo, EffectsList bool hasValue =3D e.hasAttribute(QStringLiteral("value")); // Check if this effect has a variable parameter, init effects def= ault value if ((type =3D=3D QLatin1String("animatedrect") || type =3D=3D QLat= in1String("geometry")) && !hasValue) { - QString kfr =3D AnimationWidget::getDefaultKeyframes(e.attribu= te(QStringLiteral("default")), type =3D=3D QLatin1String("geometry")); + QString kfr =3D AnimationWidget::getDefaultKeyframes(info.crop= Start.frames(fps), e.attribute(QStringLiteral("default")), type =3D=3D QLat= in1String("geometry")); if (kfr.contains("%")) { kfr =3D EffectsController::getStringRectEval(pInfo, kfr); } @@ -288,7 +290,7 @@ void EffectsController::initEffect(ItemInfo info, Profi= leInfo pInfo, EffectsList } else e.setAttribute(QStringLiteral("value"), evaluatedValue); } else { if (type =3D=3D QLatin1String("animated") && !hasValue) { - e.setAttribute(QStringLiteral("value"), AnimationWidget::g= etDefaultKeyframes(e.attribute(QStringLiteral("default")))); + e.setAttribute(QStringLiteral("value"), AnimationWidget::g= etDefaultKeyframes(info.cropStart.frames(fps), e.attribute(QStringLiteral("= default")))); } else if (!hasValue) { e.setAttribute(QStringLiteral("value"), e.attribute(QStrin= gLiteral("default"))); @@ -312,7 +314,7 @@ void EffectsController::initEffect(ItemInfo info, Profi= leInfo pInfo, EffectsList } } = - if (type.startsWith(QStringLiteral("animated")) || (type =3D=3D Q= Latin1String("geometry") && !e.hasAttribute(QStringLiteral("fixed")))) { + if (EffectsList::parameter(effect, QStringLiteral("kdenlive:sync_i= n_out")) =3D=3D QLatin1String("1") || (type =3D=3D QLatin1String("geometry= ") && !e.hasAttribute(QStringLiteral("fixed")))) { // Effects with a geometry parameter need to sync in / out wit= h parent clip effect.setAttribute(QStringLiteral("in"), QString::number((int= ) info.cropStart.frames(fps))); effect.setAttribute(QStringLiteral("out"), QString::number((in= t) (info.cropStart + info.cropDuration).frames(fps) - 1)); diff --git a/src/timeline/abstractclipitem.cpp b/src/timeline/abstractclipi= tem.cpp index 09c318e..4f4a876 100644 --- a/src/timeline/abstractclipitem.cpp +++ b/src/timeline/abstractclipitem.cpp @@ -200,7 +200,6 @@ void AbstractClipItem::resizeStart(int posx, bool hasSi= zeLimit, bool /*emitChang } m_info.startPos +=3D durationDiff; m_keyframeView.setOffset(durationDiff.frames(m_fps)); - // set to true if crop from start is negative (possible for color clip= s, images as they have no size limit) bool negCropStart =3D false; if (type() =3D=3D AVWidget) { @@ -616,7 +615,7 @@ QString AbstractClipItem::resizeAnimations(QDomElement = effect, int previousDurat effect.setAttribute(QStringLiteral("out"), QString::number= (start + duration)); } else { - keyframes =3D KeyframeView::cutAnimation(animation, cropst= art, duration, previousDuration, false); + keyframes =3D KeyframeView::addBorderKeyframes(animation, = cropstart, duration); } // TODO: in case of multiple animated params, use _intimeline = to detect active one e.setAttribute(QStringLiteral("value"), keyframes); @@ -628,10 +627,12 @@ QString AbstractClipItem::resizeAnimations(QDomElemen= t effect, int previousDurat bool AbstractClipItem::switchKeyframes(QDomElement param, int in, int oldi= n, int out, int oldout) { QString animation =3D param.attribute(QStringLiteral("value")); - if (in !=3D oldin) + if (in !=3D oldin) { animation =3D KeyframeView::switchAnimation(animation, in, oldin, = out, oldout, param.attribute(QStringLiteral("type")) =3D=3D QLatin1String("= animatedrect")); - if (out !=3D oldout) - animation =3D KeyframeView::switchAnimation(animation, out - 1, ol= dout - 1, out, oldout, param.attribute(QStringLiteral("type")) =3D=3D QLati= n1String("animatedrect")); + } + if (out !=3D oldout) { + animation =3D KeyframeView::switchAnimation(animation, out, oldout= , out, oldout, param.attribute(QStringLiteral("type")) =3D=3D QLatin1String= ("animatedrect")); + } if (animation !=3D param.attribute(QStringLiteral("value"))) { param.setAttribute(QStringLiteral("value"), animation); return true; diff --git a/src/timeline/clipitem.cpp b/src/timeline/clipitem.cpp index 579a7d8..687b978 100644 --- a/src/timeline/clipitem.cpp +++ b/src/timeline/clipitem.cpp @@ -1453,7 +1453,7 @@ EffectsParameterList ClipItem::addEffect(ProfileInfo = info, QDomElement effect, b else if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1Str= ing("animated")) { parameters.addParam(e.attribute(QStringLiteral("name")), e= .attribute(QStringLiteral("value"))); // Effects with a animated parameter need to sync in / out with parent c= lip - if (!e.hasAttribute(QStringLiteral("sync_in_out")) || e.at= tribute(QStringLiteral("sync_in_out")) =3D=3D QLatin1String("1")) { + if (e.attribute(QStringLiteral("sync_in_out")) =3D=3D QLa= tin1String("1")) { needInOutSync =3D true; } } else if (e.attribute(QStringLiteral("type")) =3D=3D QLatin1S= tring("simplekeyframe")) { @@ -1808,10 +1808,9 @@ QMap ClipItem::adjustEffectsToDura= tion(const ItemInfo &oldInfo if (effect.attribute(QStringLiteral("sync_in_out")) =3D=3D= QLatin1String("1")) { effect.setAttribute(QStringLiteral("in"), cropStart().= frames(m_fps)); effect.setAttribute(QStringLiteral("out"), (cropStart(= ) + cropDuration()).frames(m_fps) - 1); - } else { - // Check if we have keyframes at in/out points - updateAnimatedKeyframes(i, param, oldInfo); } + // Check if we have keyframes at in/out points + updateAnimatedKeyframes(i, param, oldInfo); effects[i] =3D effect.cloneNode().toElement(); } else if (type =3D=3D QLatin1String("roto-spline")) { if (!effects.contains(i)) @@ -1856,7 +1855,6 @@ bool ClipItem::updateNormalKeyframes(QDomElement para= meter, const ItemInfo &oldI keyframes[keyframepos] =3D locale.toDouble(keyframe.section('=3D',= 1, 1)); } = - QMap::iterator i =3D keyframes.end(); int lastPos =3D -1; double lastValue =3D 0; diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackvie= w.cpp index 6700af7..71736aa 100644 --- a/src/timeline/customtrackview.cpp +++ b/src/timeline/customtrackview.cpp @@ -1380,7 +1380,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEve= nt *event) ClipItem * item =3D static_cast (m_dragItem); QDomElement oldEffect =3D item->selectedEffect().cloneNode().toEle= ment(); if (single =3D=3D 1) { - item->insertKeyframe(m_document->getProfileInfo(), item->getEf= fectAtIndex(item->selectedEffectIndex()), (item->cropDuration()).frames(m_d= ocument->fps()) - 1, -1, true); + item->insertKeyframe(m_document->getProfileInfo(), item->getEf= fectAtIndex(item->selectedEffectIndex()), (item->cropStart() + item->cropDu= ration()).frames(m_document->fps()) - 1, -1, true); } //QString previous =3D item->keyframes(item->selectedEffectIndex()= ); item->insertKeyframe(m_document->getProfileInfo(), item->getEffect= AtIndex(item->selectedEffectIndex()), keyFramePos.frames(m_document->fps())= , val); @@ -1906,7 +1906,6 @@ bool CustomTrackView::itemCollision(AbstractClipItem = *item, const ItemInfo &newP = void CustomTrackView::slotRefreshEffects(ClipItem *clip) { - // Does not seem used anywhere... int track =3D clip->track(); GenTime pos =3D clip->startPos(); if (!m_timeline->track(track)->removeEffect(pos.seconds(), -1, false))= { diff --git a/src/timeline/effectmanager.cpp b/src/timeline/effectmanager.cpp index 75d38d2..bcfb84b 100644 --- a/src/timeline/effectmanager.cpp +++ b/src/timeline/effectmanager.cpp @@ -316,8 +316,7 @@ bool EffectManager::editEffect(EffectsParameterList par= ams, int duration, bool r if (params.paramValue(QStringLiteral("kdenlive:sync_in_out")) =3D= =3D QLatin1String("1")) { // This effect must sync in / out with parent clip //params.removeParam(QStringLiteral("sync_in_out")); - Mlt::Producer prod(m_producer); - filter->set_in_and_out(prod.get_in(), prod.get_out()); + filter->set_in_and_out(m_producer.get_int("in"), m_producer.ge= t_int("out")); } else { // Reset in/out properties filter->set("in", (char*)NULL); diff --git a/src/timeline/keyframeview.cpp b/src/timeline/keyframeview.cpp index 93b5028..30586c7 100644 --- a/src/timeline/keyframeview.cpp +++ b/src/timeline/keyframeview.cpp @@ -23,7 +23,6 @@ along with this program. If not, see . #include #include #include - #include "klocalizedstring.h" = #include "keyframeview.h" @@ -142,14 +141,28 @@ void KeyframeView::drawKeyFrames(QRectF br, int lengt= h, bool active, QPainter *p Mlt::Animation drawAnim =3D m_keyProperties.get_animation(paramNam= e.toUtf8().constData()); if (!drawAnim.is_valid()) continue; QPainterPath path; - int frame =3D drawAnim.key_get_frame(0); + // Find first key before our clip start, get frame for rect left f= irst + int firstKF =3D qMax(0, drawAnim.previous_key(-m_offset)); + int lastKF =3D drawAnim.next_key(duration - m_offset); + if (lastKF < duration - m_offset) { + lastKF =3D duration - m_offset; + } + int frame =3D firstKF; double value =3D m_keyProperties.anim_get_double(paramName.toUtf8(= ).constData(), frame, duration - m_offset); QPointF start =3D keyframePoint(br, frame + m_offset, value, info.= factor, info.min, info.max); path.moveTo(br.x(), br.bottom()); path.lineTo(br.x(), start.y()); path.lineTo(start); + int currentFrame; painter->setPen(paramName =3D=3D m_inTimeline ? QColor(Qt::white) = : Qt::NoPen); for(int i =3D 0; i < drawAnim.key_count(); ++i) { + currentFrame =3D drawAnim.key_get_frame(i); + if (currentFrame < firstKF) { + continue; + } + if (currentFrame > lastKF) { + break; + } if (active && paramName =3D=3D m_inTimeline) { painter->setBrush((drawAnim.key_get_frame(i) =3D=3D active= Keyframe) ? QColor(Qt::red) : QColor(Qt::blue)); painter->drawEllipse(QRectF(transformation.map(start) - h/= 2, transformation.map(start) + h / 2)); @@ -170,10 +183,10 @@ void KeyframeView::drawKeyFrames(QRectF br, int lengt= h, bool active, QPainter *p case mlt_keyframe_smooth: frame =3D drawAnim.key_get_frame(qMax(i - 1, 0)); value =3D m_keyProperties.anim_get_double(paramNam= e.toUtf8().constData(), frame, duration - m_offset); - QPointF pre =3D keyframePoint(br, frame, value, in= fo.factor, info.min, info.max); + QPointF pre =3D keyframePoint(br, frame + m_offset= , value, info.factor, info.min, info.max); frame =3D drawAnim.key_get_frame(qMin(i + 2, drawA= nim.key_count() - 1)); value =3D m_keyProperties.anim_get_double(paramNam= e.toUtf8().constData(), frame, duration - m_offset); - QPointF post =3D keyframePoint(br, frame, value, i= nfo.factor, info.min, info.max); + QPointF post =3D keyframePoint(br, frame + m_offse= t, value, info.factor, info.min, info.max); QPointF c1 =3D (end - pre) / 6.0; // + start QPointF c2 =3D (start - post) / 6.0; // + end double mid =3D (end.x() - start.x()) / 2; @@ -832,7 +845,7 @@ bool KeyframeView::loadKeyframes(const QLocale locale, = QDomElement effect, int c } attachToEnd =3D -2; m_useOffset =3D effect.attribute(QStringLiteral("kdenlive:sync_in_out"= )) !=3D QLatin1String("1"); - m_offset =3D effect.attribute("in").toInt() - cropStart; + m_offset =3D effect.attribute(QStringLiteral("in")).toInt() - cropStar= t; QDomNodeList params =3D effect.elementsByTagName(QStringLiteral("param= eter")); for (int i =3D 0; i < params.count(); ++i) { QDomElement e =3D params.item(i).toElement(); @@ -891,9 +904,23 @@ bool KeyframeView::loadKeyframes(const QLocale locale,= QDomElement effect, int c = void KeyframeView::setOffset(int frames) { - if (m_useOffset) { + if (!m_keyAnim.is_valid()) + return; + if (m_keyAnim.is_key(-m_offset)) { + mlt_keyframe_type type =3D m_keyAnim.keyframe_type(-m_offset); + double value =3D m_keyProperties.anim_get_double(m_inTimeline.toUt= f8().constData(), -m_offset, duration - m_offset); + m_keyAnim.remove(-m_offset); + if (activeKeyframe =3D=3D -m_offset) { + activeKeyframe -=3D frames; + } + m_offset -=3D frames; + m_keyProperties.anim_set(m_inTimeline.toUtf8().constData(), value,= - m_offset, duration - m_offset, type); + //addKeyframe(-m_offset, value, type); + } else { m_offset -=3D frames; } + //double value =3D m_keyProperties.anim_get_double(m_inTimeline.toUtf8= ().constData(), 0, duration - m_offset); + //} } = // static @@ -962,6 +989,34 @@ QString KeyframeView::cutAnimation(const QString &anim= ation, int start, int dura } = //static +const QString KeyframeView::addBorderKeyframes(const QString &animation, i= nt start, int duration) +{ + bool modified =3D false; + Mlt::Properties props; + props.set("keyframes", animation.toUtf8().constData()); + props.anim_get_double("keyframes", 0, start+duration); + Mlt::Animation anim =3D props.get_animation("keyframes"); + if (!anim.is_key(start)) { + double value =3D props.anim_get_double("keyframes", start, start+d= uration); + int previous =3D anim.previous_key(start); + mlt_keyframe_type type =3D anim.keyframe_type(previous); + props.anim_set("keyframes", value, start, start+duration, type); + modified =3D true; + } + if (!anim.is_key(start+duration)) { + double value =3D props.anim_get_double("keyframes", start+duration= , start+duration); + int previous =3D anim.previous_key(start+duration); + mlt_keyframe_type type =3D anim.keyframe_type(previous); + props.anim_set("keyframes", value, start+duration, start+duration,= type); + modified =3D true; + } + if (modified) { + return anim.serialize_cut(); + } + return animation; +} + +//static QString KeyframeView::switchAnimation(QString animation, int newPos, int o= ldPos, int newDuration, int oldDuration, bool isRect) { Mlt::Properties props; @@ -971,7 +1026,7 @@ QString KeyframeView::switchAnimation(QString animatio= n, int newPos, int oldPos, if (anim.is_key(oldPos)) { // insert new keyframe at start if (isRect) { - mlt_rect rect =3D props.anim_get_rect("keyframes", oldPos); + mlt_rect rect =3D props.anim_get_rect("keyframes", oldPos, old= Duration); props.anim_set("keyframes", rect, newPos, newDuration, anim.ke= yframe_type(oldPos)); anim.remove(oldPos); } else { diff --git a/src/timeline/keyframeview.h b/src/timeline/keyframeview.h index 2eef776..342b50f 100644 --- a/src/timeline/keyframeview.h +++ b/src/timeline/keyframeview.h @@ -97,6 +97,8 @@ public: static QString switchAnimation(QString animation, int newPos, int oldP= os, int newDuration, int oldDuration, bool isRect); /** @brief when loading an animation from a serialized string, check w= here is the first negative keyframe) */ static int checkNegatives(const QString &data, int maxDuration); + /** @brief Add keyframes at start / end points if not existing */ + static const QString addBorderKeyframes(const QString &animation, int = start, int duration); /** @brief returns true if currently edited parameter name is name */ bool activeParam(const QString &name) const; /** @brief Sets a temporary offset for drawing keyframes when resizing= clip start */ diff --git a/src/timeline/track.cpp b/src/timeline/track.cpp index 32aa837..43ce2ad 100644 --- a/src/timeline/track.cpp +++ b/src/timeline/track.cpp @@ -905,9 +905,9 @@ bool Track::editEffect(double start, EffectsParameterLi= st params, bool replace) if (!clip) { return false; } - Mlt::Service clipService(clip->get_service()); - EffectManager effect(clipService); - return effect.editEffect(params, duration, replace); + EffectManager effect(*clip.data()); + bool result =3D effect.editEffect(params, duration, replace); + return result; } = bool Track::editTrackEffect(EffectsParameterList params, bool replace)