Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Multimedia
Kdenlive
Commits
006f9dca
Commit
006f9dca
authored
May 09, 2020
by
Jean-Baptiste Mardelle
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2004'
parents
eed22ac4
eb4fc227
Pipeline
#19849
passed with stage
in 9 minutes and 23 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
155 additions
and
65 deletions
+155
-65
src/assets/keyframes/model/keyframemodel.cpp
src/assets/keyframes/model/keyframemodel.cpp
+39
-62
src/assets/keyframes/model/keyframemodellist.cpp
src/assets/keyframes/model/keyframemodellist.cpp
+18
-0
src/assets/keyframes/model/keyframemodellist.hpp
src/assets/keyframes/model/keyframemodellist.hpp
+6
-0
src/assets/keyframes/model/keyframemonitorhelper.cpp
src/assets/keyframes/model/keyframemonitorhelper.cpp
+78
-0
src/assets/keyframes/model/keyframemonitorhelper.hpp
src/assets/keyframes/model/keyframemonitorhelper.hpp
+2
-2
src/assets/view/widgets/keyframewidget.cpp
src/assets/view/widgets/keyframewidget.cpp
+11
-1
src/assets/view/widgets/keyframewidget.hpp
src/assets/view/widgets/keyframewidget.hpp
+1
-0
No files found.
src/assets/keyframes/model/keyframemodel.cpp
View file @
006f9dca
...
...
@@ -917,76 +917,53 @@ QVariant KeyframeModel::getInterpolatedValue(const GenTime &pos) const
if
(
m_keyframeList
.
size
()
==
0
)
{
return
QVariant
();
}
auto
next
=
m_keyframeList
.
upper_bound
(
pos
);
if
(
next
==
m_keyframeList
.
cbegin
())
{
return
(
m_keyframeList
.
cbegin
())
->
second
.
second
;
}
else
if
(
next
==
m_keyframeList
.
cend
())
{
auto
it
=
m_keyframeList
.
cend
();
--
it
;
return
it
->
second
.
second
;
}
auto
prev
=
next
;
--
prev
;
// We now have surrounding keyframes, we use mlt to compute the value
Mlt
::
Properties
prop
;
bool
useOpacity
=
true
;
Mlt
::
Properties
mlt_prop
;
QString
animData
;
int
in
=
0
;
int
out
=
0
;
bool
useOpacity
=
false
;
if
(
auto
ptr
=
m_model
.
lock
())
{
ptr
->
passProperties
(
prop
);
if
(
m_paramType
==
ParamType
::
AnimatedRect
)
{
useOpacity
=
ptr
->
data
(
m_index
,
AssetParameterModel
::
OpacityRole
).
toBool
();
}
ptr
->
passProperties
(
mlt_prop
);
in
=
ptr
->
data
(
m_index
,
AssetParameterModel
::
ParentInRole
).
toInt
();
out
=
ptr
->
data
(
m_index
,
AssetParameterModel
::
ParentDurationRole
).
toInt
();
useOpacity
=
ptr
->
data
(
m_index
,
AssetParameterModel
::
OpacityRole
).
toBool
();
animData
=
ptr
->
data
(
m_index
,
AssetParameterModel
::
ValueRole
).
toString
();
}
QLocale
locale
;
int
p
=
pos
.
frames
(
pCore
->
getCurrentFps
());
if
(
m_paramType
==
ParamType
::
KeyframeParam
)
{
prop
.
anim_set
(
"keyframe"
,
prev
->
second
.
second
.
toDouble
(),
prev
->
first
.
frames
(
pCore
->
getCurrentFps
()),
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
convertToMltType
(
prev
->
second
.
first
));
prop
.
anim_set
(
"keyframe"
,
next
->
second
.
second
.
toDouble
(),
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
convertToMltType
(
next
->
second
.
first
));
return
QVariant
(
prop
.
anim_get_double
(
"keyframe"
,
p
));
}
else
if
(
m_paramType
==
ParamType
::
AnimatedRect
)
{
QStringList
vals
=
prev
->
second
.
second
.
toString
().
split
(
QLatin1Char
(
' '
));
if
(
vals
.
count
()
>=
4
)
{
mlt_rect
rect
;
rect
.
x
=
vals
.
at
(
0
).
toInt
();
rect
.
y
=
vals
.
at
(
1
).
toInt
();
rect
.
w
=
vals
.
at
(
2
).
toInt
();
rect
.
h
=
vals
.
at
(
3
).
toInt
();
if
(
useOpacity
)
{
if
(
vals
.
count
())
{
rect
.
o
=
locale
.
toDouble
(
vals
.
at
(
4
));
}
else
{
rect
.
o
=
1
;
}
}
prop
.
anim_set
(
"keyframe"
,
rect
,
prev
->
first
.
frames
(
pCore
->
getCurrentFps
()),
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
convertToMltType
(
prev
->
second
.
first
));
if
(
!
animData
.
isEmpty
())
{
mlt_prop
.
set
(
"key"
,
animData
.
toUtf8
().
constData
());
// This is a fake query to force the animation to be parsed
(
void
)
mlt_prop
.
anim_get_double
(
"key"
,
0
,
out
);
return
QVariant
(
mlt_prop
.
anim_get_double
(
"key"
,
pos
.
frames
(
pCore
->
getCurrentFps
())));
}
vals
=
next
->
second
.
second
.
toString
().
split
(
QLatin1Char
(
' '
));
if
(
vals
.
count
()
>=
4
)
{
mlt_rect
rect
;
rect
.
x
=
vals
.
at
(
0
).
toInt
();
rect
.
y
=
vals
.
at
(
1
).
toInt
();
rect
.
w
=
vals
.
at
(
2
).
toInt
();
rect
.
h
=
vals
.
at
(
3
).
toInt
();
return
QVariant
();
}
else
if
(
m_paramType
==
ParamType
::
AnimatedRect
)
{
if
(
!
animData
.
isEmpty
())
{
QLocale
locale
;
mlt_prop
.
set
(
"key"
,
animData
.
toUtf8
().
constData
());
// This is a fake query to force the animation to be parsed
(
void
)
mlt_prop
.
anim_get_double
(
"key"
,
0
,
out
);
mlt_rect
rect
=
mlt_prop
.
anim_get_rect
(
"key"
,
pos
.
frames
(
pCore
->
getCurrentFps
()));
QString
res
=
QStringLiteral
(
"%1 %2 %3 %4"
).
arg
((
int
)
rect
.
x
).
arg
((
int
)
rect
.
y
).
arg
((
int
)
rect
.
w
).
arg
((
int
)
rect
.
h
);
if
(
useOpacity
)
{
if
(
vals
.
count
()
>
4
)
{
rect
.
o
=
locale
.
toDouble
(
vals
.
at
(
4
));
}
else
{
rect
.
o
=
1
;
}
res
.
append
(
QStringLiteral
(
" %1"
).
arg
(
locale
.
toString
(
rect
.
o
)));
}
prop
.
anim_set
(
"keyframe"
,
rect
,
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
next
->
first
.
frames
(
pCore
->
getCurrentFps
()),
convertToMltType
(
next
->
second
.
first
));
}
mlt_rect
rect
=
prop
.
anim_get_rect
(
"keyframe"
,
p
);
QString
res
=
QStringLiteral
(
"%1 %2 %3 %4"
).
arg
((
int
)
rect
.
x
).
arg
((
int
)
rect
.
y
).
arg
((
int
)
rect
.
w
).
arg
((
int
)
rect
.
h
);
if
(
useOpacity
)
{
res
.
append
(
QStringLiteral
(
" %1"
).
arg
(
locale
.
toString
(
rect
.
o
)));
return
QVariant
(
res
);
}
return
QVariant
(
res
);
return
QVariant
();
}
else
if
(
m_paramType
==
ParamType
::
Roto_spline
)
{
// interpolate
auto
next
=
m_keyframeList
.
upper_bound
(
pos
);
if
(
next
==
m_keyframeList
.
cbegin
())
{
return
(
m_keyframeList
.
cbegin
())
->
second
.
second
;
}
else
if
(
next
==
m_keyframeList
.
cend
())
{
auto
it
=
m_keyframeList
.
cend
();
--
it
;
return
it
->
second
.
second
;
}
auto
prev
=
next
;
--
prev
;
QSize
frame
=
pCore
->
getCurrentFrameSize
();
QList
<
BPoint
>
p1
=
RotoHelper
::
getPoints
(
prev
->
second
.
second
,
frame
);
QList
<
BPoint
>
p2
=
RotoHelper
::
getPoints
(
next
->
second
.
second
,
frame
);
...
...
@@ -995,7 +972,7 @@ QVariant KeyframeModel::getInterpolatedValue(const GenTime &pos) const
// - equal to 1 on next keyframe
qreal
relPos
=
0
;
if
(
next
->
first
!=
prev
->
first
)
{
relPos
=
(
p
-
prev
->
first
.
frames
(
pCore
->
getCurrentFps
()))
/
(
qreal
)(((
next
->
first
-
prev
->
first
).
frames
(
pCore
->
getCurrentFps
())));
relPos
=
(
p
os
.
frames
(
pCore
->
getCurrentFps
())
-
prev
->
first
.
frames
(
pCore
->
getCurrentFps
()))
/
(
qreal
)(((
next
->
first
-
prev
->
first
).
frames
(
pCore
->
getCurrentFps
())));
}
int
count
=
qMin
(
p1
.
count
(),
p2
.
count
());
QList
<
QVariant
>
vlist
;
...
...
src/assets/keyframes/model/keyframemodellist.cpp
View file @
006f9dca
...
...
@@ -262,6 +262,14 @@ bool KeyframeModelList::isEmpty() const
return
(
m_parameters
.
size
()
==
0
||
m_parameters
.
begin
()
->
second
->
rowCount
()
==
0
);
}
int
KeyframeModelList
::
count
()
const
{
READ_LOCK
();
if
(
m_parameters
.
size
()
>
0
)
return
m_parameters
.
begin
()
->
second
->
rowCount
();
return
0
;
}
Keyframe
KeyframeModelList
::
getNextKeyframe
(
const
GenTime
&
pos
,
bool
*
ok
)
const
{
READ_LOCK
();
...
...
@@ -485,3 +493,13 @@ void KeyframeModelList::checkConsistency()
}
}
}
GenTime
KeyframeModelList
::
getPosAtIndex
(
int
ix
)
{
QList
<
GenTime
>
positions
=
m_parameters
.
begin
()
->
second
->
getKeyframePos
();
std
::
sort
(
positions
.
begin
(),
positions
.
end
());
if
(
ix
<
0
||
ix
>=
positions
.
count
())
{
return
GenTime
();
}
return
positions
.
at
(
ix
);
}
src/assets/keyframes/model/keyframemodellist.hpp
View file @
006f9dca
...
...
@@ -96,6 +96,9 @@ public:
/* @brief Returns true if we only have no keyframe
*/
bool
isEmpty
()
const
;
/* @brief Returns the number of keyframes
*/
int
count
()
const
;
/* @brief Returns the keyframe located after given position.
If there is a keyframe at given position it is ignored.
...
...
@@ -136,6 +139,9 @@ public:
/** @brief Parent item size change, update keyframes*/
void
resizeKeyframes
(
int
oldIn
,
int
oldOut
,
int
in
,
int
out
,
int
offset
,
bool
adjustFromEnd
,
Fun
&
undo
,
Fun
&
redo
);
/** @brief Return position of the nth keyframe (ix = nth)*/
GenTime
getPosAtIndex
(
int
ix
);
/** @brief Check that all keyframable parameters have the same keyframes on loading
* (that's how our model works) */
void
checkConsistency
();
...
...
src/assets/keyframes/model/keyframemonitorhelper.cpp
View file @
006f9dca
...
...
@@ -21,9 +21,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keyframemonitorhelper.hpp"
#include "assets/model/assetparametermodel.hpp"
#include "assets/keyframes/model/keyframemodellist.hpp"
#include "monitor/monitor.h"
#include <utility>
#include <core.h>
KeyframeMonitorHelper
::
KeyframeMonitorHelper
(
Monitor
*
monitor
,
std
::
shared_ptr
<
AssetParameterModel
>
model
,
const
QPersistentModelIndex
&
index
,
QObject
*
parent
)
:
QObject
(
parent
)
,
m_monitor
(
monitor
)
...
...
@@ -52,3 +54,79 @@ void KeyframeMonitorHelper::addIndex(const QPersistentModelIndex &index)
{
m_indexes
<<
index
;
}
void
KeyframeMonitorHelper
::
refreshParams
(
int
pos
)
{
QVariantList
points
;
QVariantList
types
;
std
::
shared_ptr
<
KeyframeModelList
>
keyframes
=
m_model
->
getKeyframeModel
();
for
(
const
auto
&
ix
:
m_indexes
)
{
auto
type
=
m_model
->
data
(
ix
,
AssetParameterModel
::
TypeRole
).
value
<
ParamType
>
();
if
(
type
!=
ParamType
::
AnimatedRect
)
{
continue
;
}
KeyframeModel
*
kfr
=
keyframes
->
getKeyModel
(
ix
);
bool
ok
;
Keyframe
kf
=
kfr
->
getNextKeyframe
(
GenTime
(
-
1
),
&
ok
);
while
(
ok
)
{
if
(
kf
.
second
==
KeyframeType
::
Curve
)
{
types
<<
1
;
}
else
{
types
<<
0
;
}
QString
rectData
=
kfr
->
getInterpolatedValue
(
kf
.
first
).
toString
();
QStringList
data
=
rectData
.
split
(
QLatin1Char
(
' '
));
if
(
data
.
size
()
>
3
)
{
QRectF
r
(
data
.
at
(
0
).
toInt
(),
data
.
at
(
1
).
toInt
(),
data
.
at
(
2
).
toInt
(),
data
.
at
(
3
).
toInt
());
points
.
append
(
QVariant
(
r
.
center
()));
}
kf
=
kfr
->
getNextKeyframe
(
kf
.
first
,
&
ok
);
}
break
;
}
if
(
m_monitor
)
{
m_monitor
->
setUpEffectGeometry
(
QRect
(),
points
,
types
);
}
}
void
KeyframeMonitorHelper
::
slotUpdateFromMonitorData
(
const
QVariantList
&
centers
)
{
std
::
shared_ptr
<
KeyframeModelList
>
keyframes
=
m_model
->
getKeyframeModel
();
if
(
centers
.
count
()
!=
keyframes
->
count
())
{
qDebug
()
<<
"* * * *CENTER POINTS MISMATCH, aborting edit"
;
return
;
}
for
(
const
auto
&
ix
:
m_indexes
)
{
auto
type
=
m_model
->
data
(
ix
,
AssetParameterModel
::
TypeRole
).
value
<
ParamType
>
();
if
(
type
!=
ParamType
::
AnimatedRect
)
{
continue
;
}
KeyframeModel
*
kfr
=
keyframes
->
getKeyModel
(
ix
);
bool
ok
;
Keyframe
kf
=
kfr
->
getNextKeyframe
(
GenTime
(
-
1
),
&
ok
);
int
i
=
0
;
while
(
ok
)
{
QString
rectData
=
kfr
->
getInterpolatedValue
(
kf
.
first
).
toString
();
QStringList
data
=
rectData
.
split
(
QLatin1Char
(
' '
));
if
(
data
.
size
()
>
3
)
{
QRectF
r
(
data
.
at
(
0
).
toInt
(),
data
.
at
(
1
).
toInt
(),
data
.
at
(
2
).
toInt
(),
data
.
at
(
3
).
toInt
());
QPointF
pt
(
r
.
center
());
QPointF
expected
=
centers
.
at
(
i
).
toPointF
();
if
(
pt
!=
expected
)
{
// Center rect to new pos
QPointF
offset
=
expected
-
pt
;
r
.
translate
(
offset
);
QString
res
=
QString
(
"%1 %2 %3 %4"
).
arg
((
int
)
r
.
x
()).
arg
((
int
)
r
.
y
()).
arg
((
int
)
r
.
width
()).
arg
((
int
)
r
.
height
());
if
(
data
.
size
()
>
4
)
{
res
.
append
(
QString
(
" %1"
).
arg
(
data
.
at
(
4
)));
}
kfr
->
updateKeyframe
(
kf
.
first
,
res
);
}
}
kf
=
kfr
->
getNextKeyframe
(
kf
.
first
,
&
ok
);
i
++
;
}
break
;
}
}
src/assets/keyframes/model/keyframemonitorhelper.hpp
View file @
006f9dca
...
...
@@ -53,7 +53,7 @@ public:
bool
connectMonitor
(
bool
activate
);
/** @brief Send data update to the monitor
*/
virtual
void
refreshParams
(
int
pos
)
=
0
;
virtual
void
refreshParams
(
int
pos
);
protected:
Monitor
*
m_monitor
;
...
...
@@ -64,7 +64,7 @@ protected:
bool
m_active
;
private
slots
:
virtual
void
slotUpdateFromMonitorData
(
const
QVariantList
&
v
)
=
0
;
virtual
void
slotUpdateFromMonitorData
(
const
QVariantList
&
v
);
public
slots
:
/** @brief For classes that manage several parameters, add a param index to the list
...
...
src/assets/view/widgets/keyframewidget.cpp
View file @
006f9dca
...
...
@@ -21,6 +21,7 @@
#include "assets/keyframes/model/corners/cornershelper.hpp"
#include "assets/keyframes/model/keyframemodellist.hpp"
#include "assets/keyframes/model/rotoscoping/rotohelper.hpp"
#include "assets/keyframes/model/keyframemonitorhelper.hpp"
#include "assets/keyframes/view/keyframeview.hpp"
#include "assets/model/assetparametermodel.hpp"
#include "assets/view/widgets/keyframeimport.h"
...
...
@@ -98,6 +99,7 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
Monitor
*
monitor
=
pCore
->
getMonitor
(
m_model
->
monitorId
);
connect
(
monitor
,
&
Monitor
::
seekPosition
,
this
,
&
KeyframeWidget
::
monitorSeek
,
Qt
::
UniqueConnection
);
connect
(
monitor
,
&
Monitor
::
seekToKeyframe
,
this
,
&
KeyframeWidget
::
slotSeekToKeyframe
,
Qt
::
UniqueConnection
);
m_time
=
new
TimecodeDisplay
(
pCore
->
timecode
(),
this
);
m_time
->
setRange
(
0
,
duration
-
1
);
...
...
@@ -342,10 +344,11 @@ void KeyframeWidget::addParameter(const QPersistentModelIndex &index)
int
inPos
=
m_model
->
data
(
index
,
AssetParameterModel
::
ParentInRole
).
toInt
();
QPair
<
int
,
int
>
range
(
inPos
,
inPos
+
m_model
->
data
(
index
,
AssetParameterModel
::
ParentDurationRole
).
toInt
());
const
QString
value
=
m_keyframes
->
getInterpolatedValue
(
getPosition
(),
index
).
toString
();
m_monitorHelper
=
new
KeyframeMonitorHelper
(
pCore
->
getMonitor
(
m_model
->
monitorId
),
m_model
,
index
,
this
);
QRect
rect
;
double
opacity
=
0
;
QStringList
vals
=
value
.
split
(
QLatin1Char
(
' '
));
if
(
vals
.
count
()
>
=
4
)
{
if
(
vals
.
count
()
>
3
)
{
rect
=
QRect
(
vals
.
at
(
0
).
toInt
(),
vals
.
at
(
1
).
toInt
(),
vals
.
at
(
2
).
toInt
(),
vals
.
at
(
3
).
toInt
());
if
(
vals
.
count
()
>
4
)
{
opacity
=
locale
.
toDouble
(
vals
.
at
(
4
));
...
...
@@ -506,3 +509,10 @@ void KeyframeWidget::slotRemoveNextKeyframes()
int
pos
=
m_time
->
getValue
()
+
m_model
->
data
(
m_index
,
AssetParameterModel
::
ParentInRole
).
toInt
();
m_keyframes
->
removeNextKeyframes
(
GenTime
(
pos
,
pCore
->
getCurrentFps
()));
}
void
KeyframeWidget
::
slotSeekToKeyframe
(
int
ix
)
{
int
pos
=
m_keyframes
->
getPosAtIndex
(
ix
).
frames
(
pCore
->
getCurrentFps
());
slotSetPosition
(
pos
,
true
);
}
src/assets/view/widgets/keyframewidget.hpp
View file @
006f9dca
...
...
@@ -81,6 +81,7 @@ private slots:
void
slotCopyKeyframes
();
void
slotImportKeyframes
();
void
slotRemoveNextKeyframes
();
void
slotSeekToKeyframe
(
int
ix
);
private:
QVBoxLayout
*
m_lay
;
...
...
Thomas Mitterfellner
@mitterfellner
mentioned in issue
#178 (closed)
·
May 10, 2020
mentioned in issue
#178 (closed)
mentioned in issue #178
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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