Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
ad834a2c
Commit
ad834a2c
authored
Oct 13, 2017
by
Jean-Baptiste Mardelle
Browse files
Allow changing keyframe type
parent
bf407756
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/assets/keyframes/model/keyframemodel.cpp
View file @
ad834a2c
...
...
@@ -240,6 +240,40 @@ bool KeyframeModel::updateKeyframe(GenTime pos, QVariant value)
return
res
;
}
KeyframeType
convertFromMltType
(
mlt_keyframe_type
type
)
{
switch
(
type
)
{
case
mlt_keyframe_linear
:
return
KeyframeType
::
Linear
;
case
mlt_keyframe_discrete
:
return
KeyframeType
::
Discrete
;
case
mlt_keyframe_smooth
:
return
KeyframeType
::
Curve
;
}
return
KeyframeType
::
Linear
;
}
bool
KeyframeModel
::
updateKeyframeType
(
GenTime
pos
,
int
type
,
Fun
&
undo
,
Fun
&
redo
)
{
QWriteLocker
locker
(
&
m_lock
);
Q_ASSERT
(
m_keyframeList
.
count
(
pos
)
>
0
);
KeyframeType
oldType
=
m_keyframeList
[
pos
].
first
;
KeyframeType
newType
=
convertFromMltType
((
mlt_keyframe_type
)
type
);
QVariant
value
=
m_keyframeList
[
pos
].
second
;
// Check if keyframe is different
if
(
m_paramType
==
ParamType
::
KeyframeParam
)
{
if
(
oldType
==
newType
)
return
true
;
}
auto
operation
=
updateKeyframe_lambda
(
pos
,
newType
,
value
,
true
);
auto
reverse
=
updateKeyframe_lambda
(
pos
,
oldType
,
value
,
true
);
bool
res
=
operation
();
if
(
res
)
{
UPDATE_UNDO_REDO
(
operation
,
reverse
,
undo
,
redo
);
}
return
res
;
}
Fun
KeyframeModel
::
updateKeyframe_lambda
(
GenTime
pos
,
KeyframeType
type
,
QVariant
value
,
bool
notify
)
{
QWriteLocker
locker
(
&
m_lock
);
...
...
@@ -250,7 +284,7 @@ Fun KeyframeModel::updateKeyframe_lambda(GenTime pos, KeyframeType type, QVarian
m_keyframeList
[
pos
].
first
=
type
;
m_keyframeList
[
pos
].
second
=
value
;
if
(
notify
)
emit
dataChanged
(
index
(
row
),
index
(
row
),
{
ValueRole
,
NormalizedValueRole
});
emit
dataChanged
(
index
(
row
),
index
(
row
),
{
ValueRole
,
NormalizedValueRole
,
TypeRole
});
return
true
;
};
}
...
...
@@ -515,18 +549,6 @@ mlt_keyframe_type convertToMltType(KeyframeType type)
}
return
mlt_keyframe_linear
;
}
KeyframeType
convertFromMltType
(
mlt_keyframe_type
type
)
{
switch
(
type
)
{
case
mlt_keyframe_linear
:
return
KeyframeType
::
Linear
;
case
mlt_keyframe_discrete
:
return
KeyframeType
::
Discrete
;
case
mlt_keyframe_smooth
:
return
KeyframeType
::
Curve
;
}
return
KeyframeType
::
Linear
;
}
void
KeyframeModel
::
parseAnimProperty
(
const
QString
&
prop
)
{
...
...
src/assets/keyframes/model/keyframemodel.hpp
View file @
ad834a2c
...
...
@@ -44,7 +44,7 @@ class EffectItemModel;
enum
class
KeyframeType
{
Linear
,
Linear
=
0
,
Discrete
,
Curve
};
...
...
@@ -106,6 +106,7 @@ public:
@param value is the new value of the param
*/
bool
updateKeyframe
(
GenTime
pos
,
QVariant
value
);
bool
updateKeyframeType
(
GenTime
pos
,
int
type
,
Fun
&
undo
,
Fun
&
redo
);
bool
updateKeyframe
(
GenTime
pos
,
QVariant
value
,
Fun
&
undo
,
Fun
&
redo
);
/* @brief Returns a keyframe data at given pos
...
...
src/assets/keyframes/model/keyframemodellist.cpp
View file @
ad834a2c
...
...
@@ -129,6 +129,23 @@ bool KeyframeModelList::updateKeyframe(GenTime pos, QVariant value, const QPersi
return
res
;
}
bool
KeyframeModelList
::
updateKeyframeType
(
GenTime
pos
,
int
type
,
const
QPersistentModelIndex
&
index
)
{
QWriteLocker
locker
(
&
m_lock
);
Q_ASSERT
(
m_parameters
.
count
(
index
)
>
0
);
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
if
(
singleKeyframe
())
{
bool
ok
=
false
;
Keyframe
kf
=
m_parameters
.
begin
()
->
second
->
getNextKeyframe
(
GenTime
(
-
1
),
&
ok
);
pos
=
kf
.
first
;
}
bool
res
=
m_parameters
.
at
(
index
)
->
updateKeyframeType
(
pos
,
type
,
undo
,
redo
);
if
(
res
)
{
PUSH_UNDO
(
undo
,
redo
,
i18n
(
"Update keyframe"
));
}
return
res
;
}
Keyframe
KeyframeModelList
::
getKeyframe
(
const
GenTime
&
pos
,
bool
*
ok
)
const
{
...
...
src/assets/keyframes/model/keyframemodellist.hpp
View file @
ad834a2c
...
...
@@ -81,6 +81,7 @@ public:
@param index is the index of the wanted keyframe
*/
bool
updateKeyframe
(
GenTime
pos
,
QVariant
value
,
const
QPersistentModelIndex
&
index
);
bool
updateKeyframeType
(
GenTime
pos
,
int
type
,
const
QPersistentModelIndex
&
index
);
/* @brief Returns a keyframe data at given pos
ok is a return parameter, set to true if everything went good
...
...
src/assets/keyframes/view/keyframeview.cpp
View file @
ad834a2c
...
...
@@ -87,6 +87,13 @@ void KeyframeView::slotAddRemove()
}
}
void
KeyframeView
::
slotEditType
(
int
type
,
const
QPersistentModelIndex
&
index
)
{
if
(
m_model
->
hasKeyframe
(
m_position
))
{
m_model
->
updateKeyframeType
(
GenTime
(
m_position
,
pCore
->
getCurrentFps
()),
type
,
index
);
}
}
void
KeyframeView
::
slotRemoveKeyframe
(
int
pos
)
{
if
(
pos
<
0
)
{
...
...
@@ -258,9 +265,22 @@ void KeyframeView::paintEvent(QPaintEvent *event)
}
else
{
p
.
setBrush
(
m_colKeyframe
);
}
int
scaledPos
=
pos
*
m_scale
;
p
.
drawLine
(
scaledPos
,
headOffset
,
scaledPos
,
m_lineHeight
+
(
headOffset
/
2
));
p
.
drawEllipse
(
scaledPos
-
headOffset
/
2
,
0
,
headOffset
,
headOffset
);
double
scaledPos
=
pos
*
m_scale
;
p
.
drawLine
(
QPointF
(
scaledPos
,
headOffset
),
QPointF
(
scaledPos
,
m_lineHeight
+
headOffset
/
2.0
));
switch
(
keyframe
.
second
.
first
)
{
case
KeyframeType
::
Linear
:
{
QPolygonF
position
=
QPolygonF
()
<<
QPointF
(
-
headOffset
/
2.0
,
headOffset
/
2.0
)
<<
QPointF
(
0
,
0
)
<<
QPointF
(
headOffset
/
2.0
,
headOffset
/
2.0
)
<<
QPointF
(
0
,
headOffset
);
position
.
translate
(
scaledPos
,
0
);
p
.
drawPolygon
(
position
);
break
;
}
case
KeyframeType
::
Discrete
:
p
.
drawRect
(
QRectF
(
scaledPos
-
headOffset
/
2.0
,
0
,
headOffset
,
headOffset
));
break
;
default:
p
.
drawEllipse
(
QRectF
(
scaledPos
-
headOffset
/
2.0
,
0
,
headOffset
,
headOffset
));
break
;
}
}
p
.
setPen
(
palette
().
dark
().
color
());
...
...
src/assets/keyframes/view/keyframeview.hpp
View file @
ad834a2c
...
...
@@ -53,6 +53,7 @@ public slots:
void
slotGoToNext
();
void
slotGoToPrev
();
void
slotModelChanged
();
void
slotEditType
(
int
type
,
const
QPersistentModelIndex
&
index
);
protected:
void
paintEvent
(
QPaintEvent
*
event
)
override
;
...
...
src/assets/view/widgets/keyframewidget.cpp
View file @
ad834a2c
...
...
@@ -29,9 +29,9 @@
#include
"widgets/doublewidget.h"
#include
"widgets/geometrywidget.h"
#include
<Q
Grid
Layout>
#include
<Q
VBox
Layout>
#include
<QToolButton>
#include
<KSelectAction>
#include
<klocalizedstring.h>
KeyframeWidget
::
KeyframeWidget
(
std
::
shared_ptr
<
AssetParameterModel
>
model
,
QModelIndex
index
,
QWidget
*
parent
)
...
...
@@ -41,7 +41,7 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Preferred
);
m_lay
=
new
Q
Grid
Layout
(
this
);
m_lay
=
new
Q
VBox
Layout
(
this
);
bool
ok
=
false
;
int
duration
=
m_model
->
data
(
m_index
,
AssetParameterModel
::
ParentDurationRole
).
toInt
(
&
ok
);
...
...
@@ -64,15 +64,37 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
m_buttonNext
->
setIcon
(
KoIconUtils
::
themedIcon
(
QStringLiteral
(
"media-skip-forward"
)));
m_buttonNext
->
setToolTip
(
i18n
(
"Go to next keyframe"
));
// Keyframe type widget
m_selectType
=
new
KSelectAction
(
KoIconUtils
::
themedIcon
(
QStringLiteral
(
"keyframes"
)),
i18n
(
"Keyframe interpolation"
),
this
);
QAction
*
discrete
=
new
QAction
(
KoIconUtils
::
themedIcon
(
QStringLiteral
(
"discrete"
)),
i18n
(
"Discrete"
),
this
);
discrete
->
setData
((
int
)
mlt_keyframe_discrete
);
discrete
->
setCheckable
(
true
);
m_selectType
->
addAction
(
discrete
);
QAction
*
linear
=
new
QAction
(
KoIconUtils
::
themedIcon
(
QStringLiteral
(
"linear"
)),
i18n
(
"Linear"
),
this
);
linear
->
setData
((
int
)
mlt_keyframe_linear
);
linear
->
setCheckable
(
true
);
m_selectType
->
addAction
(
linear
);
QAction
*
curve
=
new
QAction
(
KoIconUtils
::
themedIcon
(
QStringLiteral
(
"smooth"
)),
i18n
(
"Smooth"
),
this
);
curve
->
setData
((
int
)
mlt_keyframe_smooth
);
curve
->
setCheckable
(
true
);
m_selectType
->
addAction
(
curve
);
m_selectType
->
setCurrentAction
(
linear
);
connect
(
m_selectType
,
SIGNAL
(
triggered
(
QAction
*
)),
this
,
SLOT
(
slotEditKeyframeType
(
QAction
*
)));
m_selectType
->
setToolBarMode
(
KSelectAction
::
ComboBoxMode
);
QToolBar
*
toolbar
=
new
QToolBar
(
this
);
Monitor
*
monitor
=
pCore
->
getMonitor
(
m_model
->
monitorId
);
m_time
=
new
TimecodeDisplay
(
monitor
->
timecode
(),
this
);
m_time
->
setRange
(
0
,
duration
);
m_lay
->
addWidget
(
m_keyframeview
,
0
,
0
,
1
,
-
1
);
m_lay
->
addWidget
(
m_buttonPrevious
,
1
,
0
);
m_lay
->
addWidget
(
m_buttonAddDelete
,
1
,
1
);
m_lay
->
addWidget
(
m_buttonNext
,
1
,
2
);
m_lay
->
addWidget
(
m_time
,
1
,
3
,
Qt
::
AlignRight
);
toolbar
->
addWidget
(
m_buttonPrevious
);
toolbar
->
addWidget
(
m_buttonAddDelete
);
toolbar
->
addWidget
(
m_buttonNext
);
toolbar
->
addAction
(
m_selectType
);
toolbar
->
addWidget
(
m_time
);
m_lay
->
addWidget
(
m_keyframeview
);
m_lay
->
addWidget
(
toolbar
);
slotSetPosition
(
0
,
false
);
connect
(
m_time
,
&
TimecodeDisplay
::
timeCodeEditingFinished
,
[
&
](){
slotSetPosition
(
-
1
,
true
);});
...
...
@@ -103,6 +125,13 @@ void KeyframeWidget::monitorSeek(int pos)
m_keyframeview
->
slotSetPosition
(
qBound
(
in
,
pos
,
out
)
-
in
);
}
void
KeyframeWidget
::
slotEditKeyframeType
(
QAction
*
action
)
{
int
type
=
action
->
data
().
toInt
();
m_keyframeview
->
slotEditType
(
type
,
m_index
);
}
void
KeyframeWidget
::
slotRefreshParams
()
{
int
pos
=
getPosition
();
...
...
@@ -232,6 +261,6 @@ void KeyframeWidget::addParameter(const QPersistentModelIndex& index)
}
if
(
paramWidget
)
{
m_parameters
[
index
]
=
paramWidget
;
m_lay
->
addWidget
(
paramWidget
,
1
+
(
int
)
m_parameters
.
size
(),
0
,
1
,
-
1
);
m_lay
->
addWidget
(
paramWidget
);
}
}
src/assets/view/widgets/keyframewidget.hpp
View file @
ad834a2c
...
...
@@ -31,9 +31,10 @@ class AssetParameterModel;
class
DoubleWidget
;
class
KeyframeView
;
class
KeyframeModelList
;
class
Q
Grid
Layout
;
class
Q
VBox
Layout
;
class
QToolButton
;
class
TimecodeDisplay
;
class
KSelectAction
;
class
KeyframeWidget
:
public
AbstractParamWidget
{
...
...
@@ -60,15 +61,17 @@ private slots:
void
slotRefreshParams
();
void
slotAtKeyframe
(
bool
atKeyframe
,
bool
singleKeyframe
);
void
monitorSeek
(
int
pos
);
void
slotEditKeyframeType
(
QAction
*
action
);
private:
Q
Grid
Layout
*
m_lay
;
Q
VBox
Layout
*
m_lay
;
std
::
shared_ptr
<
KeyframeModelList
>
m_keyframes
;
KeyframeView
*
m_keyframeview
;
QToolButton
*
m_buttonAddDelete
;
QToolButton
*
m_buttonPrevious
;
QToolButton
*
m_buttonNext
;
KSelectAction
*
m_selectType
;
TimecodeDisplay
*
m_time
;
std
::
unordered_map
<
QPersistentModelIndex
,
QWidget
*>
m_parameters
;
...
...
src/timeline2/view/qml/Clip.qml
View file @
ad834a2c
...
...
@@ -389,7 +389,7 @@ Rectangle {
Rectangle
{
id
:
keyframe
property
int
frame
:
model
.
frame
property
int
t
ype
:
model
.
type
property
int
frameT
ype
:
model
.
type
x
:
model
.
frame
*
timeScale
height
:
parent
.
height
*
model
.
normalizedValue
anchors.bottom
:
parent
.
bottom
...
...
@@ -455,13 +455,13 @@ Rectangle {
var
ypos
for
(
var
i
=
0
;
i
<
keyframes
.
count
;
i
++
)
{
var
type
=
keyframes
.
itemAt
(
i
).
frameType
xpos
=
keyframes
.
itemAt
(
i
).
x
if
(
type
==
1
)
{
// discrete
paths
.
push
(
compline
.
createObject
(
keyframecanvas
,
{
"
x
"
:
xpos
,
"
y
"
:
ypos
}
))
}
ypos
=
parent
.
height
-
keyframes
.
itemAt
(
i
).
height
var
type
=
keyframes
.
itemAt
(
i
).
type
if
(
type
<
2
)
{
// linear
paths
.
push
(
compline
.
createObject
(
keyframecanvas
,
{
"
x
"
:
xpos
,
"
y
"
:
ypos
}
))
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment