Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Improve timeline keyframe handling (allow free move)

parent b4c76e7d
......@@ -154,7 +154,7 @@ bool KeyframeModel::removeKeyframe(GenTime pos)
return res;
}
bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, Fun &undo, Fun &redo)
bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, double newVal, Fun &undo, Fun &redo)
{
qDebug() << "starting to move keyframe" << oldPos.frames(pCore->getCurrentFps()) << pos.frames(pCore->getCurrentFps());
QWriteLocker locker(&m_lock);
......@@ -170,7 +170,16 @@ bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, Fun &undo, Fun &re
qDebug() << "Move keyframe finished deletion:" << res;
qDebug() << getAnimProperty();
if (res) {
res = addKeyframe(pos, oldType, oldValue, true, local_undo, local_redo);
if (newVal > -1) {
if (auto ptr = m_model.lock()) {
double min = ptr->data(m_index, AssetParameterModel::MinRole).toDouble();
double max = ptr->data(m_index, AssetParameterModel::MaxRole).toDouble();
double realValue = newVal * (max - min) + min;
res = addKeyframe(pos, oldType, realValue, true, local_undo, local_redo);
}
} else {
res = addKeyframe(pos, oldType, oldValue, true, local_undo, local_redo);
}
qDebug() << "Move keyframe finished insertion:" << res;
qDebug() << getAnimProperty();
}
......@@ -187,17 +196,24 @@ bool KeyframeModel::moveKeyframe(int oldPos, int pos, bool logUndo)
{
GenTime oPos(oldPos, pCore->getCurrentFps());
GenTime nPos(pos, pCore->getCurrentFps());
return moveKeyframe(oPos, nPos, logUndo);
return moveKeyframe(oPos, nPos, -1, logUndo);
}
bool KeyframeModel::moveKeyframe(int oldPos, int pos, double newVal)
{
GenTime oPos(oldPos, pCore->getCurrentFps());
GenTime nPos(pos, pCore->getCurrentFps());
return moveKeyframe(oPos, nPos, newVal, true);
}
bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, bool logUndo)
bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, double newVal, bool logUndo)
{
QWriteLocker locker(&m_lock);
Q_ASSERT(m_keyframeList.count(oldPos) > 0);
if (oldPos == pos) return true;
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool res = moveKeyframe(oldPos, pos, undo, redo);
bool res = moveKeyframe(oldPos, pos, newVal, undo, redo);
if (res && logUndo) {
PUSH_UNDO(undo, redo, i18n("Move keyframe"));
}
......
......@@ -78,6 +78,7 @@ protected:
public:
/* @brief Removes the keyframe at the given position. */
Q_INVOKABLE bool removeKeyframe(int frame);
Q_INVOKABLE bool moveKeyframe(int oldPos, int pos, double newVal);
bool removeKeyframe(GenTime pos);
/* @brief Delete all the keyframes of the model */
bool removeAllKeyframes();
......@@ -94,8 +95,8 @@ public:
@param logUndo if true, then an undo object is created
*/
Q_INVOKABLE bool moveKeyframe(int oldPos, int pos, bool logUndo);
bool moveKeyframe(GenTime oldPos, GenTime pos, bool logUndo);
bool moveKeyframe(GenTime oldPos, GenTime pos, Fun &undo, Fun &redo);
bool moveKeyframe(GenTime oldPos, GenTime pos, double newVal, bool logUndo);
bool moveKeyframe(GenTime oldPos, GenTime pos, double newVal, Fun &undo, Fun &redo);
/* @brief updates the value of a keyframe
@param old is the position of the keyframe
......
......@@ -99,7 +99,7 @@ bool KeyframeModelList::moveKeyframe(GenTime oldPos, GenTime pos, bool logUndo)
{
QWriteLocker locker(&m_lock);
Q_ASSERT(m_parameters.size() > 0);
auto op = [oldPos, pos](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo) { return param->moveKeyframe(oldPos, pos, undo, redo); };
auto op = [oldPos, pos](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo) { return param->moveKeyframe(oldPos, pos, -1, undo, redo); };
return applyOperation(op, logUndo ? i18n("Move keyframe") : QString());
}
......
......@@ -417,8 +417,8 @@ Rectangle {
}
KeyframeView {
id: effectRow
visible: clipRoot.showKeyframes
id: effectRow
visible: clipRoot.showKeyframes
}
}
......
......@@ -28,6 +28,7 @@ Rectangle
property alias kfrCount : keyframes.count
anchors.fill: parent
color: Qt.rgba(1,1,1, 0.6)
id: keyframeContainer
onKfrCountChanged: {
keyframecanvas.requestPaint()
......@@ -40,7 +41,8 @@ Rectangle
property int frame : model.frame
property int frameType : model.type
x: model.frame * timeScale
height: parent.height * model.normalizedValue
height: parent.height // * model.normalizedValue
property int value: parent.height * model.normalizedValue
anchors.bottom: parent.bottom
onFrameTypeChanged: {
keyframecanvas.requestPaint()
......@@ -48,15 +50,50 @@ Rectangle
onHeightChanged: {
keyframecanvas.requestPaint()
}
width: Math.max(2, timeScale)
width: 1 //Math.max(2, timeScale)
color: 'darkred'
border.color: 'red'
Rectangle {
x: - root.baseUnit / 2
y: parent.height - keyframe.value - root.baseUnit / 2
width: root.baseUnit
height: width
radius: width / 2
color: Qt.rgba(1,0,0, 0.4)
border.color: kf1MouseArea.containsMouse ? 'red' : 'transparent'
MouseArea {
id: kf1MouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
drag.target: parent
drag.smoothed: false
onReleased: {
root.stopScrolling = false
var newPos = Math.round((keyframe.x + parent.x + root.baseUnit / 2) / timeScale)
var newVal = (keyframeContainer.height - (parent.y + mouse.y)) / keyframeContainer.height
console.log('.............\n\nKFRHGT: ', clipRoot.height,' - ', mouse.y)
keyframeModel.moveKeyframe(frame, newPos, newVal)
}
onPositionChanged: {
if (mouse.buttons === Qt.LeftButton) {
var newPos = Math.round(parent.x / timeScale)
parent.x = newPos * timeScale
keyframecanvas.requestPaint()
}
}
onDoubleClicked: {
keyframeModel.removeKeyframe(frame);
}
}
}
MouseArea {
id: kfMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
drag.target: parent
drag.smoothed: false
drag.axis: Drag.XAxis
onReleased: {
root.stopScrolling = false
......@@ -72,9 +109,6 @@ Rectangle
keyframecanvas.requestPaint()
}
}
onDoubleClicked: {
keyframeModel.removeKeyframe(frame);
}
}
}
}
......@@ -113,7 +147,7 @@ Rectangle
// discrete
paths.push(compline.createObject(keyframecanvas, {"x": xpos, "y": ypos} ))
}
ypos = parent.height - keyframes.itemAt(i).height
ypos = parent.height - keyframes.itemAt(i).value
if (type < 2) {
// linear
paths.push(compline.createObject(keyframecanvas, {"x": xpos, "y": ypos} ))
......
......@@ -211,7 +211,7 @@ TEST_CASE("Keyframe model", "[KeyframeModel]")
};
state1(1.1);
REQUIRE(model->moveKeyframe(GenTime(1.1), GenTime(2.6), true));
REQUIRE(model->moveKeyframe(GenTime(1.1), GenTime(2.6), -1, true));
state1(2.6);
undoStack->undo();
......@@ -219,7 +219,7 @@ TEST_CASE("Keyframe model", "[KeyframeModel]")
undoStack->redo();
state1(2.6);
REQUIRE(model->moveKeyframe(GenTime(2.6), GenTime(6.1), true));
REQUIRE(model->moveKeyframe(GenTime(2.6), GenTime(6.1), -1, true));
state1(6.1);
undoStack->undo();
......@@ -232,7 +232,7 @@ TEST_CASE("Keyframe model", "[KeyframeModel]")
state1(6.1);
REQUIRE(model->addKeyframe(GenTime(12.6), KeyframeType::Discrete, 33));
REQUIRE_FALSE(model->moveKeyframe(GenTime(6.1), GenTime(12.6), true));
REQUIRE_FALSE(model->moveKeyframe(GenTime(6.1), GenTime(12.6), -1, true));
undoStack->undo();
state1(6.1);
}
......
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