summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <jb@kdenlive.org>2016-11-28 23:25:04 (GMT)
committerJean-Baptiste Mardelle <jb@kdenlive.org>2016-11-28 23:25:04 (GMT)
commitb2235e3ff5fea9c987752cdbd3899e87abedf4d0 (patch)
tree5269d88c45631e92fcb53c91ad15307e563f30b2
parent13535766c1b1317f06bcc013c2f81472e691a081 (diff)
Fix several issues with effect keyframes behaving incorrectly
-rw-r--r--src/effectstack/dragvalue.cpp1
-rw-r--r--src/effectstack/effectstackview2.cpp17
-rw-r--r--src/effectstack/effectstackview2.h3
-rw-r--r--src/effectstack/widgets/animationwidget.cpp6
-rw-r--r--src/timeline/abstractclipitem.cpp15
-rw-r--r--src/timeline/abstractclipitem.h1
-rw-r--r--src/timeline/clipitem.cpp20
-rw-r--r--src/timeline/clipitem.h4
-rw-r--r--src/timeline/customtrackview.cpp4
-rw-r--r--src/timeline/keyframeview.cpp25
-rw-r--r--src/timeline/keyframeview.h2
11 files changed, 80 insertions, 18 deletions
diff --git a/src/effectstack/dragvalue.cpp b/src/effectstack/dragvalue.cpp
index fd79856..1f8ab01 100644
--- a/src/effectstack/dragvalue.cpp
+++ b/src/effectstack/dragvalue.cpp
@@ -363,7 +363,6 @@ void DragValue::setInTimelineProperty(bool intimeline)
style()->polish(m_doubleEdit);
m_doubleEdit->update();
}
-
}
CustomLabel::CustomLabel(const QString &label, bool showSlider, int range, QWidget* parent) :
diff --git a/src/effectstack/effectstackview2.cpp b/src/effectstack/effectstackview2.cpp
index 77037cf..9fdc97d 100644
--- a/src/effectstack/effectstackview2.cpp
+++ b/src/effectstack/effectstackview2.cpp
@@ -67,6 +67,10 @@ EffectStackView2::EffectStackView2(Monitor *projectMonitor, QWidget *parent) :
connect(m_effect->checkAll, SIGNAL(stateChanged(int)), this, SLOT(slotCheckAll(int)));
connect(m_effect->effectCompare, &QToolButton::toggled, this, &EffectStackView2::slotSwitchCompare);
+ m_scrollTimer.setSingleShot(true);
+ m_scrollTimer.setInterval(200);
+ connect(&m_scrollTimer, &QTimer::timeout, this, &EffectStackView2::slotCheckWheelEventFilter);
+
m_layout.addWidget(m_effect);
m_layout.addWidget(m_transition);
m_transition->setHidden(true);
@@ -278,12 +282,19 @@ void EffectStackView2::slotTrackItemSelected(int ix, const TrackInfo &info, Moni
void EffectStackView2::setupListView()
{
blockSignals(true);
+ m_scrollTimer.stop();
m_monitorSceneWanted = MonitorSceneDefault;
m_draggedEffect = NULL;
m_draggedGroup = NULL;
disconnect(m_effectMetaInfo.monitor, SIGNAL(renderPosition(int)), this, SLOT(slotRenderPos(int)));
QWidget *view = m_effect->container->takeWidget();
if (view) {
+ /*QList<CollapsibleEffect *> allChildren = view->findChildren<CollapsibleEffect *>();
+ qDebug()<<" * * *FOUND CHLD: "<<allChildren.count();
+ foreach(CollapsibleEffect *eff, allChildren) {
+ eff->setEnabled(false);
+ }*/
+ //delete view;
view->setEnabled(false);
view->setHidden(true);
view->deleteLater();
@@ -409,7 +420,7 @@ void EffectStackView2::setupListView()
slotUpdateCheckAllButton();
// Wait a little bit for the new layout to be ready, then check if we have a scrollbar
- QTimer::singleShot(200, this, SLOT(slotCheckWheelEventFilter()));
+ m_scrollTimer.start();
}
int EffectStackView2::activeEffectIndex() const
@@ -759,7 +770,7 @@ void EffectStackView2::slotUpdateEffectParams(const QDomElement &old, const QDom
else if (m_status == MASTER_CLIP) {
emit updateMasterEffect(m_masterclipref->clipId(), old, e, ix);
}
- QTimer::singleShot(200, this, SLOT(slotCheckWheelEventFilter()));
+ m_scrollTimer.start();
}
void EffectStackView2::slotSetCurrentEffect(int ix)
@@ -992,7 +1003,7 @@ void EffectStackView2::slotCreateRegion(int ix, QUrl url)
// Check drag & drop
currentEffect->installEventFilter( this );
- QTimer::singleShot(200, this, SLOT(slotCheckWheelEventFilter()));
+ m_scrollTimer.start();
}
diff --git a/src/effectstack/effectstackview2.h b/src/effectstack/effectstackview2.h
index 4a80911..9b97619 100644
--- a/src/effectstack/effectstackview2.h
+++ b/src/effectstack/effectstackview2.h
@@ -27,6 +27,8 @@
#include "collapsibleeffect.h"
#include "collapsiblegroup.h"
+#include <QTimer>
+
class EffectsList;
class ClipItem;
class Transition;
@@ -124,6 +126,7 @@ private:
/** @brief The current effect may require an on monitor scene. */
MonitorSceneType m_monitorSceneWanted;
QMutex m_mutex;
+ QTimer m_scrollTimer;
/** If in track mode: Info of the edited track to be able to access its duration. */
TrackInfo m_trackInfo;
diff --git a/src/effectstack/widgets/animationwidget.cpp b/src/effectstack/widgets/animationwidget.cpp
index 31417d4..71ab9d2 100644
--- a/src/effectstack/widgets/animationwidget.cpp
+++ b/src/effectstack/widgets/animationwidget.cpp
@@ -269,11 +269,11 @@ void AnimationWidget::slotPrevious()
void AnimationWidget::slotNext()
{
int next = m_animController.next_key(m_timePos->getValue() - m_offset + 1) + m_offset;
- if (!m_animController.is_key(next)) {
+ if (!m_animController.is_key(next - m_offset)) {
// No keyframe after current pos, return end position
next = m_timePos->maximum();
} else {
- m_ruler->setActiveKeyframe(next);
+ m_ruler->setActiveKeyframe(next - m_offset);
}
slotPositionChanged(next, true);
}
@@ -350,7 +350,7 @@ void AnimationWidget::slotAddDeleteKeyframe(bool add, int pos)
for (int i = 0; i < paramNames.count(); i++) {
m_animController = m_animProperties.get_animation(paramNames.at(i).toUtf8().constData());
if (!m_animController.is_key(pos - m_offset)) {
- doAddKeyframe(pos - m_offset, paramNames.at(i), false);
+ doAddKeyframe(pos, paramNames.at(i), false);
}
}
m_ruler->setActiveKeyframe(pos);
diff --git a/src/timeline/abstractclipitem.cpp b/src/timeline/abstractclipitem.cpp
index 0f0f325..09c318e 100644
--- a/src/timeline/abstractclipitem.cpp
+++ b/src/timeline/abstractclipitem.cpp
@@ -624,3 +624,18 @@ QString AbstractClipItem::resizeAnimations(QDomElement effect, int previousDurat
}
return keyframes;
}
+
+bool AbstractClipItem::switchKeyframes(QDomElement param, int in, int oldin, int out, int oldout)
+{
+ QString animation = param.attribute(QStringLiteral("value"));
+ if (in != oldin)
+ animation = KeyframeView::switchAnimation(animation, in, oldin, out, oldout, param.attribute(QStringLiteral("type")) == QLatin1String("animatedrect"));
+ if (out != oldout)
+ animation = KeyframeView::switchAnimation(animation, out - 1, oldout - 1, out, oldout, param.attribute(QStringLiteral("type")) == QLatin1String("animatedrect"));
+ if (animation != param.attribute(QStringLiteral("value"))) {
+ param.setAttribute(QStringLiteral("value"), animation);
+ return true;
+ }
+ return false;
+}
+
diff --git a/src/timeline/abstractclipitem.h b/src/timeline/abstractclipitem.h
index 5b1ebbd..fcd33f8 100644
--- a/src/timeline/abstractclipitem.h
+++ b/src/timeline/abstractclipitem.h
@@ -123,6 +123,7 @@ protected:
int posForTrack(int track);
bool resizeGeometries(QDomElement effect, int width, int height, int previousDuration, int start, int duration, int cropstart);
QString resizeAnimations(QDomElement effect, int previousDuration, int start, int duration, int cropstart);
+ bool switchKeyframes(QDomElement param, int in, int oldin, int out, int oldout);
signals:
void selectItem(AbstractClipItem*);
diff --git a/src/timeline/clipitem.cpp b/src/timeline/clipitem.cpp
index eefa5ff..579a7d8 100644
--- a/src/timeline/clipitem.cpp
+++ b/src/timeline/clipitem.cpp
@@ -1735,7 +1735,7 @@ void ClipItem::setState(PlaylistState::ClipState state)
QMap<int, QDomElement> ClipItem::adjustEffectsToDuration(const ItemInfo &oldInfo)
{
QMap<int, QDomElement> effects;
- qDebug()<<"Adjusting effect to duraion";
+ //qDebug()<<"Adjusting effect to duration: "<<oldInfo.cropStart.frames(25)<<" - "<<cropStart().frames(25);
for (int i = 0; i < m_effectList.count(); ++i) {
QDomElement effect = m_effectList.at(i);
@@ -1790,7 +1790,6 @@ QMap<int, QDomElement> ClipItem::adjustEffectsToDuration(const ItemInfo &oldInfo
QDomNodeList params = effect.elementsByTagName(QStringLiteral("parameter"));
for (int j = 0; j < params.count(); ++j) {
QDomElement param = params.item(j).toElement();
-
QString type = param.attribute(QStringLiteral("type"));
if (type == QLatin1String("geometry") && !param.hasAttribute(QStringLiteral("fixed"))) {
if (!effects.contains(i)) {
@@ -1805,10 +1804,13 @@ QMap<int, QDomElement> ClipItem::adjustEffectsToDuration(const ItemInfo &oldInfo
if (!effects.contains(i))
effects[i] = effect.cloneNode().toElement();
updateNormalKeyframes(param, oldInfo);
- } else if (type == QLatin1String("animated")) {
+ } else if (type.startsWith(QLatin1String("animated"))) {
if (effect.attribute(QStringLiteral("sync_in_out")) == 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);
}
effects[i] = effect.cloneNode().toElement();
} else if (type == QLatin1String("roto-spline")) {
@@ -1823,7 +1825,17 @@ QMap<int, QDomElement> ClipItem::adjustEffectsToDuration(const ItemInfo &oldInfo
return effects;
}
-bool ClipItem::updateNormalKeyframes(QDomElement parameter, ItemInfo oldInfo)
+
+bool ClipItem::updateAnimatedKeyframes(int ix, QDomElement parameter, const ItemInfo &oldInfo)
+{
+ int in = cropStart().frames(m_fps);
+ int out = (cropStart() + cropDuration()).frames(m_fps) - 1;
+ int oldin = oldInfo.cropStart.frames(m_fps);
+ int oldout = oldin + oldInfo.cropDuration.frames(m_fps) - 1;
+ return switchKeyframes(parameter, in, oldin, out, oldout);
+}
+
+bool ClipItem::updateNormalKeyframes(QDomElement parameter, const ItemInfo &oldInfo)
{
int in = cropStart().frames(m_fps);
int out = (cropStart() + cropDuration()).frames(m_fps) - 1;
diff --git a/src/timeline/clipitem.h b/src/timeline/clipitem.h
index ecc2839..88a0794 100644
--- a/src/timeline/clipitem.h
+++ b/src/timeline/clipitem.h
@@ -166,8 +166,8 @@ public:
QPixmap endThumb() const;
void setState(PlaylistState::ClipState state);
void updateState(const QString &id, int aIndex, int vIndex, PlaylistState::ClipState originalState);
-
- bool updateNormalKeyframes(QDomElement parameter, ItemInfo oldInfo);
+ bool updateAnimatedKeyframes(int ix, QDomElement parameter, const ItemInfo &oldInfo);
+ bool updateNormalKeyframes(QDomElement parameter, const ItemInfo &oldInfo);
/** @brief Adjusts effects after a clip duration change. */
QMap<int, QDomElement> adjustEffectsToDuration(const ItemInfo &oldInfo);
diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp
index 0d112fc..6700af7 100644
--- a/src/timeline/customtrackview.cpp
+++ b/src/timeline/customtrackview.cpp
@@ -7791,10 +7791,6 @@ void CustomTrackView::adjustEffects(ClipItem* item, ItemInfo oldInfo, QUndoComma
++i;
}
}
- if (item == m_dragItem) {
- // clip is selected, update effect stack
- emit clipItemSelected(item);
- }
}
diff --git a/src/timeline/keyframeview.cpp b/src/timeline/keyframeview.cpp
index 45885f7..93b5028 100644
--- a/src/timeline/keyframeview.cpp
+++ b/src/timeline/keyframeview.cpp
@@ -529,7 +529,7 @@ void KeyframeView::updateKeyFramePos(QRectF br, int frame, const double y)
}
int prev = m_keyAnim.key_count() <= 1 || m_keyAnim.key_get_frame(0) == activeKeyframe ? 0 : m_keyAnim.previous_key(activeKeyframe - 1) + 1;
prev = qMax(prev, -m_offset);
- int next = m_keyAnim.key_count() <= 1 || m_keyAnim.key_get_frame(m_keyAnim.key_count() - 1) == activeKeyframe ? duration - m_offset : m_keyAnim.next_key(activeKeyframe + 1) - 1;
+ int next = m_keyAnim.key_count() <= 1 || m_keyAnim.key_get_frame(m_keyAnim.key_count() - 1) == activeKeyframe ? duration - m_offset - 1 : m_keyAnim.next_key(activeKeyframe + 1) - 1;
if (next < 0) next += duration;
int newpos = qBound(prev, frame - m_offset, next);
double newval = keyframeUnmap(br, y);
@@ -961,6 +961,29 @@ QString KeyframeView::cutAnimation(const QString &animation, int start, int dura
return anim.serialize_cut(start, start + duration);
}
+//static
+QString KeyframeView::switchAnimation(QString animation, int newPos, int oldPos, int newDuration, int oldDuration, bool isRect)
+{
+ Mlt::Properties props;
+ props.set("keyframes", animation.toUtf8().constData());
+ props.anim_get_double("keyframes", 0, oldDuration);
+ Mlt::Animation anim = props.get_animation("keyframes");
+ if (anim.is_key(oldPos)) {
+ // insert new keyframe at start
+ if (isRect) {
+ mlt_rect rect = props.anim_get_rect("keyframes", oldPos);
+ props.anim_set("keyframes", rect, newPos, newDuration, anim.keyframe_type(oldPos));
+ anim.remove(oldPos);
+ } else {
+ double value = props.anim_get_double("keyframes", oldPos, oldDuration);
+ props.anim_set("keyframes", value, newPos, newDuration, anim.keyframe_type(oldPos));
+ anim.remove(oldPos);
+ }
+ }
+ return anim.serialize_cut();
+ //return anim.serialize_cut(start, start + duration);
+}
+
/*
void KeyframeView::updateAnimatedKeyframes(QDomElement effect, int paramIndex, ItemInfo oldInfo)
diff --git a/src/timeline/keyframeview.h b/src/timeline/keyframeview.h
index 5b16715..2eef776 100644
--- a/src/timeline/keyframeview.h
+++ b/src/timeline/keyframeview.h
@@ -93,6 +93,8 @@ public:
void showMenu(QWidget *parent, QPoint pos);
QAction *parseKeyframeActions(QList <QAction *>actions);
static QString cutAnimation(const QString &animation, int start, int duration, int fullduration, bool doCut = true);
+ /** @brief when an animation is resized, update in / out point keyframes */
+ static QString switchAnimation(QString animation, int newPos, int oldPos, int newDuration, int oldDuration, bool isRect);
/** @brief when loading an animation from a serialized string, check where is the first negative keyframe) */
static int checkNegatives(const QString &data, int maxDuration);
/** @brief returns true if currently edited parameter name is name */