* Keyframes: reintroduce default keyframe type (linear, smooth,..)

* Add menu option to remove all keyframes after cursor
* Fix painting of smooth keyframes
parent 6445f1d8
......@@ -1088,3 +1088,54 @@ std::shared_ptr<Mlt::Properties> KeyframeModel::getAnimation(const QString &anim
(void)mlt_prop->anim_get_rect("key", 0, 0);
return mlt_prop;
}
bool KeyframeModel::removeNextKeyframes(GenTime pos, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
std::vector<GenTime> all_pos;
Fun local_undo = []() { return true; };
Fun local_redo = []() { return true; };
int firstPos = 0;
for (const auto &m : m_keyframeList) {
if (m.first <= pos) {
firstPos++;
continue;
}
all_pos.push_back(m.first);
}
int kfrCount = (int)all_pos.size();
// we trigger only one global remove/insertrow event
Fun update_redo_start = [this, firstPos, kfrCount]() {
beginRemoveRows(QModelIndex(), firstPos, kfrCount);
return true;
};
Fun update_redo_end = [this]() {
endRemoveRows();
return true;
};
Fun update_undo_start = [this, firstPos, kfrCount]() {
beginInsertRows(QModelIndex(), firstPos, kfrCount);
return true;
};
Fun update_undo_end = [this]() {
endInsertRows();
return true;
};
PUSH_LAMBDA(update_redo_start, local_redo);
PUSH_LAMBDA(update_undo_start, local_undo);
update_redo_start();
bool res = true;
for (const auto &p : all_pos) {
res = removeKeyframe(p, local_undo, local_redo, false);
if (!res) {
bool undone = local_undo();
Q_ASSERT(undone);
return false;
}
}
update_redo_end();
PUSH_LAMBDA(update_redo_end, local_redo);
PUSH_LAMBDA(update_undo_end, local_undo);
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
}
......@@ -42,7 +42,7 @@ class EffectItemModel;
We store them in a sorted fashion using a std::map
*/
enum class KeyframeType { Linear = 0, Discrete, Curve };
enum class KeyframeType { Linear = mlt_keyframe_linear, Discrete = mlt_keyframe_discrete, Curve = mlt_keyframe_smooth };
Q_DECLARE_METATYPE(KeyframeType)
using Keyframe = std::pair<GenTime, KeyframeType>;
......@@ -84,6 +84,7 @@ protected:
/* @brief Delete all the keyframes of the model */
bool removeAllKeyframes();
bool removeAllKeyframes(Fun &undo, Fun &redo);
bool removeNextKeyframes(GenTime pos, Fun &undo, Fun &redo);
protected:
/* @brief Same function but accumulates undo/redo */
......
......@@ -26,6 +26,7 @@
#include "doc/docundostack.hpp"
#include "keyframemodel.hpp"
#include "klocalizedstring.h"
#include <kdenlivesettings.h>
#include "macros.hpp"
#include <QDebug>
......@@ -93,16 +94,15 @@ bool KeyframeModelList::addKeyframe(int frame, double val)
QWriteLocker locker(&m_lock);
GenTime pos(frame, pCore->getCurrentFps());
Q_ASSERT(m_parameters.size() > 0);
KeyframeType type = keyframeType(GenTime());
bool update = (m_parameters.begin()->second->hasKeyframe(pos) > 0);
auto op = [this, pos, frame, type, val](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo) {
auto op = [this, pos, frame, val](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo) {
QVariant value;
if (m_parameters.begin()->second == param) {
value = param->getNormalizedValue(val);
} else {
value = param->getInterpolatedValue(pos);
}
return param->addKeyframe(pos, type, value, true, undo, redo);
return param->addKeyframe(pos, (KeyframeType)KdenliveSettings::defaultkeyframeinterp(), value, true, undo, redo);
};
return applyOperation(op, update ? i18n("Change keyframe type") : i18n("Add keyframe"));
}
......@@ -123,6 +123,14 @@ bool KeyframeModelList::removeAllKeyframes()
return applyOperation(op, i18n("Delete all keyframes"));
}
bool KeyframeModelList::removeNextKeyframes(GenTime pos)
{
QWriteLocker locker(&m_lock);
Q_ASSERT(m_parameters.size() > 0);
auto op = [pos](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo) { return param->removeNextKeyframes(pos, undo, redo); };
return applyOperation(op, i18n("Delete keyframes"));
}
bool KeyframeModelList::moveKeyframe(GenTime oldPos, GenTime pos, bool logUndo)
{
QWriteLocker locker(&m_lock);
......
......@@ -67,6 +67,8 @@ public:
bool removeKeyframe(GenTime pos);
/* @brief Delete all the keyframes of the model (except first) */
bool removeAllKeyframes();
/* @brief Delete all the keyframes after a certain position (except first) */
bool removeNextKeyframes(GenTime pos);
/* @brief moves a keyframe
@param oldPos is the old position of the keyframe
......
......@@ -37,7 +37,6 @@ KeyframeView::KeyframeView(std::shared_ptr<KeyframeModelList> model, int duratio
, m_currentKeyframeOriginal(-1)
, m_hoverKeyframe(-1)
, m_scale(1)
, m_currentType(KeyframeType::Linear)
{
setMouseTracking(true);
setMinimumSize(QSize(150, 20));
......@@ -88,7 +87,7 @@ void KeyframeView::slotAddKeyframe(int pos)
pos = m_position;
}
int offset = pCore->getItemIn(m_model->getOwnerId());
m_model->addKeyframe(GenTime(pos + offset, pCore->getCurrentFps()), m_currentType);
m_model->addKeyframe(GenTime(pos + offset, pCore->getCurrentFps()), (KeyframeType) KdenliveSettings::defaultkeyframeinterp());
}
void KeyframeView::slotAddRemove()
......@@ -256,7 +255,7 @@ void KeyframeView::mouseDoubleClickEvent(QMouseEvent *event)
}
// add new keyframe
m_model->addKeyframe(position, m_currentType);
m_model->addKeyframe(position, (KeyframeType) KdenliveSettings::defaultkeyframeinterp());
} else {
QWidget::mouseDoubleClickEvent(event);
}
......
......@@ -75,7 +75,6 @@ private:
int m_lineHeight;
double m_scale;
int m_size;
KeyframeType m_currentType;
QColor m_colSelected;
QColor m_colKeyframe;
......
......@@ -29,6 +29,7 @@
#include "monitor/monitor.h"
#include "timecode.h"
#include "timecodedisplay.h"
#include "kdenlivesettings.h"
#include "widgets/doublewidget.h"
#include "widgets/geometrywidget.h"
......@@ -111,9 +112,40 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
connect(copy, &QAction::triggered, this, &KeyframeWidget::slotCopyKeyframes);
QAction *paste = new QAction(i18n("Import keyframes from clipboard"), this);
connect(paste, &QAction::triggered, this, &KeyframeWidget::slotImportKeyframes);
QAction *removeNext = new QAction(i18n("Remove all keyframes after cursor"), this);
connect(removeNext, &QAction::triggered, this, &KeyframeWidget::slotRemoveNextKeyframes);
KSelectAction *kfType = new KSelectAction(i18n("Default keyframe type"), this);
QAction *discrete2 = new QAction(QIcon::fromTheme(QStringLiteral("discrete")), i18n("Discrete"), this);
discrete2->setData((int)mlt_keyframe_discrete);
discrete2->setCheckable(true);
kfType->addAction(discrete2);
QAction *linear2 = new QAction(QIcon::fromTheme(QStringLiteral("linear")), i18n("Linear"), this);
linear2->setData((int)mlt_keyframe_linear);
linear2->setCheckable(true);
kfType->addAction(linear2);
QAction *curve2 = new QAction(QIcon::fromTheme(QStringLiteral("smooth")), i18n("Smooth"), this);
curve2->setData((int)mlt_keyframe_smooth);
curve2->setCheckable(true);
kfType->addAction(curve2);
switch (KdenliveSettings::defaultkeyframeinterp()) {
case mlt_keyframe_discrete:
kfType->setCurrentAction(discrete2);
break;
case mlt_keyframe_smooth:
kfType->setCurrentAction(curve2);
break;
default:
kfType->setCurrentAction(linear2);
break;
}
connect(kfType, static_cast<void (KSelectAction::*)(QAction *)>(&KSelectAction::triggered), [&](QAction *ac) {
KdenliveSettings::setDefaultkeyframeinterp(ac->data().toInt());
});
auto *container = new QMenu(this);
container->addAction(copy);
container->addAction(paste);
container->addAction(kfType);
container->addAction(removeNext);
// Menu toolbutton
auto *menuButton = new QToolButton(this);
......@@ -176,7 +208,14 @@ void KeyframeWidget::slotRefreshParams()
{
int pos = getPosition();
KeyframeType keyType = m_keyframes->keyframeType(GenTime(pos, pCore->getCurrentFps()));
m_selectType->setCurrentItem((int)keyType);
int i = 0;
while (auto ac = m_selectType->action(i)) {
if (ac->data().toInt() == (int) keyType) {
m_selectType->setCurrentItem(i);
break;
}
i++;
}
for (const auto &w : m_parameters) {
ParamType type = m_model->data(w.first, AssetParameterModel::TypeRole).value<ParamType>();
if (type == ParamType::KeyframeParam) {
......@@ -479,3 +518,9 @@ void KeyframeWidget::slotImportKeyframes()
//emit importKeyframes(type, tag, keyframeData);
delete import;
}
void KeyframeWidget::slotRemoveNextKeyframes()
{
m_keyframes->removeNextKeyframes(GenTime(m_time->getValue(), pCore->getCurrentFps()));
}
......@@ -80,6 +80,7 @@ private slots:
void slotUpdateKeyframesFromMonitor(QPersistentModelIndex index, const QVariant &res);
void slotCopyKeyframes();
void slotImportKeyframes();
void slotRemoveNextKeyframes();
private:
QVBoxLayout *m_lay;
......
......@@ -139,8 +139,8 @@ Rectangle
width: root.baseUnit
height: width
radius: width / 2
color: Qt.rgba(1,0,0, 0.4)
border.color: keyframeContainer.activeFrame == keyframe.frame ? 'black' : kf1MouseArea.containsMouse ? 'blue' : 'transparent'
color: keyframeContainer.activeFrame == keyframe.frame ? 'red' : kf1MouseArea.containsMouse || kf1MouseArea.pressed ? root.textColor : root.videoColor
border.color: kf1MouseArea.containsMouse || kf1MouseArea.pressed ? activePalette.highlight : root.textColor
MouseArea {
id: kf1MouseArea
anchors.fill: parent
......@@ -232,9 +232,9 @@ Rectangle
var ypos
for(var i = 0; i < keyframes.count; i++)
{
var type = keyframes.itemAt(i).frameType
var type = i > 0 ? keyframes.itemAt(i-1).frameType : keyframes.itemAt(i).frameType
xpos = keyframes.itemAt(i).tmpPos
if (type == 1) {
if (type == 0) {
// discrete
paths.push(compline.createObject(keyframecanvas, {"x": xpos, "y": ypos} ))
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment