Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Kdenlive
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
258
Issues
258
List
Boards
Labels
Service Desk
Milestones
Merge Requests
15
Merge Requests
15
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Multimedia
Kdenlive
Commits
32423ba3
Commit
32423ba3
authored
Jun 14, 2019
by
Jean-Baptiste Mardelle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial implementation of clip speed change on Ctrl + resize
parent
738b8e13
Pipeline
#4319
passed with stage
in 18 minutes and 39 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
213 additions
and
62 deletions
+213
-62
src/timeline2/model/clipmodel.cpp
src/timeline2/model/clipmodel.cpp
+35
-29
src/timeline2/model/clipmodel.hpp
src/timeline2/model/clipmodel.hpp
+1
-1
src/timeline2/model/timelinemodel.cpp
src/timeline2/model/timelinemodel.cpp
+94
-13
src/timeline2/model/timelinemodel.hpp
src/timeline2/model/timelinemodel.hpp
+9
-2
src/timeline2/view/qml/Clip.qml
src/timeline2/view/qml/Clip.qml
+12
-8
src/timeline2/view/qml/Track.qml
src/timeline2/view/qml/Track.qml
+57
-4
src/timeline2/view/timelinecontroller.cpp
src/timeline2/view/timelinecontroller.cpp
+1
-1
tests/timewarptest.cpp
tests/timewarptest.cpp
+4
-4
No files found.
src/timeline2/model/clipmodel.cpp
View file @
32423ba3
...
...
@@ -152,11 +152,13 @@ bool ClipModel::requestResize(int size, bool right, Fun &undo, Fun &redo, bool l
int
out
=
m_producer
->
get_out
();
int
old_in
=
in
,
old_out
=
out
;
// check if there is enough space on the chosen side
if
(
!
right
&&
in
+
delta
<
0
&&
!
m_endlessResize
)
{
return
false
;
}
if
(
!
m_endlessResize
&&
right
&&
(
out
-
delta
>=
m_producer
->
get_length
()))
{
return
false
;
if
(
!
m_endlessResize
)
{
if
(
!
right
&&
in
+
delta
<
0
)
{
return
false
;
}
if
(
right
&&
(
out
-
delta
>=
m_producer
->
get_length
()))
{
return
false
;
}
}
if
(
right
)
{
out
-=
delta
;
...
...
@@ -212,28 +214,30 @@ bool ClipModel::requestResize(int size, bool right, Fun &undo, Fun &redo, bool l
return
false
;
};
if
(
operation
())
{
// Now, we are in the state in which the timeline should be when we try to revert current action. So we can build the reverse action from here
if
(
m_currentTrackId
!=
-
1
)
{
if
(
auto
ptr
=
m_parent
.
lock
())
{
track_reverse
=
ptr
->
getTrackById
(
m_currentTrackId
)
->
requestClipResize_lambda
(
m_id
,
old_in
,
old_out
,
right
);
Fun
reverse
=
[]()
{
return
true
;
};
if
(
logUndo
)
{
// Now, we are in the state in which the timeline should be when we try to revert current action. So we can build the reverse action from here
if
(
m_currentTrackId
!=
-
1
)
{
if
(
auto
ptr
=
m_parent
.
lock
())
{
track_reverse
=
ptr
->
getTrackById
(
m_currentTrackId
)
->
requestClipResize_lambda
(
m_id
,
old_in
,
old_out
,
right
);
}
}
}
Fun
reverse
=
[
this
,
old_in
,
old_out
,
track_reverse
,
roles
](
)
{
if
(
track_reverse
())
{
setInOut
(
old_in
,
old_out
);
if
(
m_currentTrackId
>
-
1
)
{
if
(
auto
ptr
=
m_parent
.
lock
())
{
QModelIndex
ix
=
ptr
->
makeClipIndexFromID
(
m_id
);
ptr
->
dataChanged
(
ix
,
ix
,
roles
);
reverse
=
[
this
,
old_in
,
old_out
,
track_reverse
,
roles
]()
{
if
(
track_reverse
()
)
{
setInOut
(
old_in
,
old_out
);
if
(
m_currentTrackId
>
-
1
)
{
if
(
auto
ptr
=
m_parent
.
lock
()
)
{
QModelIndex
ix
=
ptr
->
makeClipIndexFromID
(
m_id
);
ptr
->
dataChanged
(
ix
,
ix
,
roles
);
}
}
return
true
;
}
return
true
;
}
return
false
;
};
qDebug
()
<<
"----------
\n
-----------
\n
// ADJUSTING EFFECT LENGTH, LOGUNDO "
<<
logUndo
<<
", "
<<
old_in
<<
"/"
<<
inPoint
<<
", "
return
false
;
};
qDebug
()
<<
"----------
\n
-----------
\n
// ADJUSTING EFFECT LENGTH, LOGUNDO "
<<
logUndo
<<
", "
<<
old_in
<<
"/"
<<
inPoint
<<
", "
<<
m_producer
->
get_playtime
();
if
(
logUndo
)
{
adjustEffectLength
(
right
,
old_in
,
inPoint
,
old_out
-
old_in
,
m_producer
->
get_playtime
(),
offset
,
reverse
,
operation
,
logUndo
);
}
UPDATE_UNDO_REDO
(
operation
,
reverse
,
undo
,
redo
);
...
...
@@ -411,7 +415,7 @@ void ClipModel::refreshProducerFromBin()
refreshProducerFromBin
(
m_currentState
);
}
bool
ClipModel
::
useTimewarpProducer
(
double
speed
,
Fun
&
undo
,
Fun
&
redo
)
bool
ClipModel
::
useTimewarpProducer
(
double
speed
,
bool
changeDuration
,
Fun
&
undo
,
Fun
&
redo
)
{
if
(
m_endlessResize
)
{
// no timewarp for endless producers
...
...
@@ -430,7 +434,7 @@ bool ClipModel::useTimewarpProducer(double speed, Fun &undo, Fun &redo)
int
oldIn
=
getIn
();
auto
operation
=
useTimewarpProducer_lambda
(
speed
);
auto
reverse
=
useTimewarpProducer_lambda
(
previousSpeed
);
if
(
oldOut
>=
newDuration
)
{
if
(
changeDuration
&&
oldOut
>=
newDuration
)
{
// in that case, we are going to shrink the clip when changing the producer. We must undo that when reloading the old producer
reverse
=
[
reverse
,
oldIn
,
oldOut
,
this
]()
{
bool
res
=
reverse
();
...
...
@@ -443,10 +447,12 @@ bool ClipModel::useTimewarpProducer(double speed, Fun &undo, Fun &redo)
if
(
operation
())
{
UPDATE_UNDO_REDO
(
operation
,
reverse
,
local_undo
,
local_redo
);
// When calculating duration, result can be a few frames longer than possible duration so adjust
bool
res
=
requestResize
(
qMin
(
newDuration
,
getMaxDuration
()),
true
,
local_undo
,
local_redo
,
true
);
if
(
!
res
)
{
local_undo
();
return
false
;
if
(
changeDuration
)
{
bool
res
=
requestResize
(
qMin
(
newDuration
,
getMaxDuration
()),
true
,
local_undo
,
local_redo
,
true
);
if
(
!
res
)
{
local_undo
();
return
false
;
}
}
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
return
true
;
...
...
src/timeline2/model/clipmodel.hpp
View file @
32423ba3
...
...
@@ -183,7 +183,7 @@ protected:
/* @brief This functions replaces the current producer with a slowmotion one
It also resizes the producer so that set of frames contained in the clip is the same
*/
bool
useTimewarpProducer
(
double
speed
,
Fun
&
undo
,
Fun
&
redo
);
bool
useTimewarpProducer
(
double
speed
,
bool
changeDuration
,
Fun
&
undo
,
Fun
&
redo
);
// @brief Lambda that merely changes the speed (in and out are untouched)
Fun
useTimewarpProducer_lambda
(
double
speed
);
...
...
src/timeline2/model/timelinemodel.cpp
View file @
32423ba3
...
...
@@ -96,7 +96,7 @@ RTTR_REGISTRATION
// .method("requestCompositionInsertion", select_overload<bool(const QString &, int, int, int, std::unique_ptr<Mlt::Properties>, int &, bool)>(
// &TimelineModel::requestCompositionInsertion))(
// parameter_names("transitionId", "trackId", "position", "length", "transProps", "id", "logUndo"))
.
method
(
"requestClipTimeWarp"
,
select_overload
<
bool
(
int
,
double
)
>
(
&
TimelineModel
::
requestClipTimeWarp
))(
parameter_names
(
"clipId"
,
"speed
"
));
.
method
(
"requestClipTimeWarp"
,
select_overload
<
bool
(
int
,
double
,
bool
)
>
(
&
TimelineModel
::
requestClipTimeWarp
))(
parameter_names
(
"clipId"
,
"speed"
,
"changeDuration
"
));
}
int
TimelineModel
::
next_id
=
0
;
...
...
@@ -1665,20 +1665,83 @@ const std::vector<int> TimelineModel::getBoundaries(int itemId)
return
boundaries
;
}
int
TimelineModel
::
request
ItemResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
,
int
snapDistance
,
bool
allowSingleResize
)
int
TimelineModel
::
request
ClipResizeAndTimeWarp
(
int
itemId
,
int
size
,
bool
right
,
int
snapDistance
,
bool
allowSingleResize
,
double
speed
)
{
if
(
logUndo
)
{
qDebug
()
<<
"---------------------
\n
---------------------
\n
RESIZE W/UNDO CALLED
\n
++++++++++++++++
\n
++++"
;
}
QWriteLocker
locker
(
&
m_lock
);
TRACE
(
itemId
,
size
,
right
,
logUndo
,
snapDistance
,
allowSingleResize
);
Q_ASSERT
(
is
Item
(
itemId
));
TRACE
(
itemId
,
size
,
right
,
true
,
snapDistance
,
allowSingleResize
);
Q_ASSERT
(
is
Clip
(
itemId
));
if
(
size
<=
0
)
{
TRACE_RES
(
-
1
);
return
-
1
;
}
int
in
=
getItemPosition
(
itemId
);
int
out
=
in
+
getItemPlaytime
(
itemId
);
//size = requestItemResizeInfo(itemId, in, out, size, right, snapDistance);
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
std
::
unordered_set
<
int
>
all_items
;
if
(
!
allowSingleResize
&&
m_groups
->
isInGroup
(
itemId
))
{
int
groupId
=
m_groups
->
getRootId
(
itemId
);
std
::
unordered_set
<
int
>
items
;
if
(
m_groups
->
getType
(
groupId
)
==
GroupType
::
AVSplit
)
{
// Only resize group elements if it is an avsplit
items
=
m_groups
->
getLeaves
(
groupId
);
}
else
{
all_items
.
insert
(
itemId
);
}
for
(
int
id
:
items
)
{
if
(
id
==
itemId
)
{
all_items
.
insert
(
id
);
continue
;
}
int
start
=
getItemPosition
(
id
);
int
end
=
in
+
getItemPlaytime
(
id
);
if
(
right
)
{
if
(
out
==
end
)
{
all_items
.
insert
(
id
);
}
}
else
if
(
start
==
in
)
{
all_items
.
insert
(
id
);
}
}
}
else
{
all_items
.
insert
(
itemId
);
}
bool
result
=
true
;
for
(
int
id
:
all_items
)
{
int
tid
=
getItemTrackId
(
id
);
if
(
tid
>
-
1
&&
getTrackById_const
(
tid
)
->
isLocked
())
{
continue
;
}
// First delete clip, then timewarp, resize and reinsert
int
pos
=
getItemPosition
(
id
);
if
(
!
right
)
{
pos
+=
getItemPlaytime
(
id
)
-
size
;
}
result
=
getTrackById
(
tid
)
->
requestClipDeletion
(
id
,
true
,
true
,
undo
,
redo
,
false
,
true
);
result
=
result
&&
requestClipTimeWarp
(
id
,
speed
,
false
,
undo
,
redo
);
result
=
result
&&
requestItemResize
(
id
,
size
,
true
,
true
,
undo
,
redo
);
result
=
result
&&
getTrackById
(
tid
)
->
requestClipInsertion
(
id
,
pos
,
true
,
true
,
undo
,
redo
);
if
(
!
result
)
{
break
;
}
}
if
(
!
result
)
{
bool
undone
=
undo
();
Q_ASSERT
(
undone
);
TRACE_RES
(
-
1
);
return
-
1
;
}
if
(
result
)
{
PUSH_UNDO
(
undo
,
redo
,
i18n
(
"Resize clip speed"
));
}
int
res
=
result
?
size
:
-
1
;
TRACE_RES
(
res
);
return
res
;
}
int
TimelineModel
::
requestItemResizeInfo
(
int
itemId
,
int
in
,
int
out
,
int
size
,
bool
right
,
int
snapDistance
)
{
if
(
snapDistance
>
0
&&
getItemTrackId
(
itemId
)
!=
-
1
)
{
Fun
temp_undo
=
[]()
{
return
true
;
};
Fun
temp_redo
=
[]()
{
return
true
;
};
...
...
@@ -1713,6 +1776,24 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
}
}
}
return
size
;
}
int
TimelineModel
::
requestItemResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
,
int
snapDistance
,
bool
allowSingleResize
)
{
if
(
logUndo
)
{
qDebug
()
<<
"---------------------
\n
---------------------
\n
RESIZE W/UNDO CALLED
\n
++++++++++++++++
\n
++++"
;
}
QWriteLocker
locker
(
&
m_lock
);
TRACE
(
itemId
,
size
,
right
,
logUndo
,
snapDistance
,
allowSingleResize
);
Q_ASSERT
(
isItem
(
itemId
));
if
(
size
<=
0
)
{
TRACE_RES
(
-
1
);
return
-
1
;
}
int
in
=
getItemPosition
(
itemId
);
int
out
=
in
+
getItemPlaytime
(
itemId
);
size
=
requestItemResizeInfo
(
itemId
,
in
,
out
,
size
,
right
,
snapDistance
);
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
std
::
unordered_set
<
int
>
all_items
;
...
...
@@ -3013,7 +3094,7 @@ void TimelineModel::requestClipUpdate(int clipId, const QVector<int> &roles)
notifyChange
(
modelIndex
,
modelIndex
,
roles
);
}
bool
TimelineModel
::
requestClipTimeWarp
(
int
clipId
,
double
speed
,
Fun
&
undo
,
Fun
&
redo
)
bool
TimelineModel
::
requestClipTimeWarp
(
int
clipId
,
double
speed
,
bool
changeDuration
,
Fun
&
undo
,
Fun
&
redo
)
{
QWriteLocker
locker
(
&
m_lock
);
if
(
qFuzzyCompare
(
speed
,
m_allClips
[
clipId
]
->
getSpeed
()))
{
...
...
@@ -3029,7 +3110,7 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, Fun &undo, Fun
success
=
success
&&
getTrackById
(
trackId
)
->
requestClipDeletion
(
clipId
,
true
,
true
,
local_undo
,
local_redo
,
false
,
false
);
}
if
(
success
)
{
success
=
m_allClips
[
clipId
]
->
useTimewarpProducer
(
speed
,
local_undo
,
local_redo
);
success
=
m_allClips
[
clipId
]
->
useTimewarpProducer
(
speed
,
changeDuration
,
local_undo
,
local_redo
);
}
if
(
trackId
!=
-
1
)
{
success
=
success
&&
getTrackById
(
trackId
)
->
requestClipInsertion
(
clipId
,
oldPos
,
true
,
true
,
local_undo
,
local_redo
);
...
...
@@ -3042,7 +3123,7 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, Fun &undo, Fun
return
success
;
}
bool
TimelineModel
::
requestClipTimeWarp
(
int
clipId
,
double
speed
)
bool
TimelineModel
::
requestClipTimeWarp
(
int
clipId
,
double
speed
,
bool
changeDuration
)
{
QWriteLocker
locker
(
&
m_lock
);
TRACE
(
clipId
,
speed
);
...
...
@@ -3055,10 +3136,10 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed)
// Check if clip has a split partner
int
splitId
=
m_groups
->
getSplitPartner
(
clipId
);
if
(
splitId
>
-
1
)
{
result
=
requestClipTimeWarp
(
splitId
,
speed
/
100.0
,
undo
,
redo
);
result
=
requestClipTimeWarp
(
splitId
,
speed
/
100.0
,
changeDuration
,
undo
,
redo
);
}
if
(
result
)
{
result
=
requestClipTimeWarp
(
clipId
,
speed
/
100.0
,
undo
,
redo
);
result
=
requestClipTimeWarp
(
clipId
,
speed
/
100.0
,
changeDuration
,
undo
,
redo
);
}
if
(
!
result
)
{
pCore
->
displayMessage
(
i18n
(
"Change speed failed"
),
ErrorMessage
);
...
...
@@ -3068,7 +3149,7 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed)
}
}
else
{
// If clip is not inserted on a track, we just change the producer
result
=
m_allClips
[
clipId
]
->
useTimewarpProducer
(
speed
,
undo
,
redo
);
result
=
m_allClips
[
clipId
]
->
useTimewarpProducer
(
speed
,
changeDuration
,
undo
,
redo
);
}
if
(
result
)
{
PUSH_UNDO
(
undo
,
redo
,
i18n
(
"Change clip speed"
));
...
...
src/timeline2/model/timelinemodel.hpp
View file @
32423ba3
...
...
@@ -466,6 +466,8 @@ public:
Q_INVOKABLE
const
QVariantList
getGroupData
(
int
itemId
);
Q_INVOKABLE
void
processGroupResize
(
QVariantList
startPos
,
QVariantList
endPos
,
bool
right
);
Q_INVOKABLE
int
requestClipResizeAndTimeWarp
(
int
itemId
,
int
size
,
bool
right
,
int
snapDistance
,
bool
allowSingleResize
,
double
speed
);
/* @brief Group together a set of ids
The ids are either a group ids or clip ids. The involved clip must already be inserted in a track
This action is undoable
...
...
@@ -536,6 +538,11 @@ protected:
@returns best snap position or -1 if no snap point is near
*/
int
getBestSnapPos
(
int
pos
,
int
length
,
const
std
::
vector
<
int
>
&
pts
=
std
::
vector
<
int
>
(),
int
cursorPosition
=
0
,
int
snapDistance
=
-
1
);
/* @brief Returns the best possible size for a clip on resize
*/
int
requestItemResizeInfo
(
int
itemId
,
int
in
,
int
out
,
int
size
,
bool
right
,
int
snapDistance
);
/* @brief Returns a list of in/out of all items in the group of itemId
*/
const
std
::
vector
<
int
>
getBoundaries
(
int
itemId
);
...
...
@@ -621,10 +628,10 @@ public:
This functions create an undo object and also apply the effect to the corresponding audio if there is any.
Returns true on success, false otherwise (and nothing is modified)
*/
bool
requestClipTimeWarp
(
int
clipId
,
double
speed
);
Q_INVOKABLE
bool
requestClipTimeWarp
(
int
clipId
,
double
speed
,
bool
changeDuration
);
/* @brief Same function as above, but doesn't check for paired audio and accumulate undo/redo
*/
bool
requestClipTimeWarp
(
int
clipId
,
double
speed
,
Fun
&
undo
,
Fun
&
redo
);
bool
requestClipTimeWarp
(
int
clipId
,
double
speed
,
bool
changeDuration
,
Fun
&
undo
,
Fun
&
redo
);
void
replugClip
(
int
clipId
);
...
...
src/timeline2/view/qml/Clip.qml
View file @
32423ba3
...
...
@@ -75,11 +75,11 @@ Rectangle {
width
:
clipDuration
*
timeScale
;
opacity
:
dragProxyArea
.
drag
.
active
&&
dragProxy
.
draggedItem
==
clipId
?
0.8
:
1.0
signal
trimmingIn
(
var
clip
,
real
newDuration
,
var
mouse
,
bool
shiftTrim
)
signal
trimmedIn
(
var
clip
,
bool
shiftTrim
)
signal
trimmingIn
(
var
clip
,
real
newDuration
,
var
mouse
,
bool
shiftTrim
,
bool
controlTrim
)
signal
trimmedIn
(
var
clip
,
bool
shiftTrim
,
bool
controlTrim
)
signal
initGroupTrim
(
var
clip
)
signal
trimmingOut
(
var
clip
,
real
newDuration
,
var
mouse
,
bool
shiftTrim
)
signal
trimmedOut
(
var
clip
,
bool
shiftTrim
)
signal
trimmingOut
(
var
clip
,
real
newDuration
,
var
mouse
,
bool
shiftTrim
,
bool
controlTrim
)
signal
trimmedOut
(
var
clip
,
bool
shiftTrim
,
bool
controlTrim
)
onIsGrabbedChanged
:
{
if
(
clipRoot
.
isGrabbed
)
{
...
...
@@ -815,6 +815,7 @@ Rectangle {
drag.axis
:
Drag
.
XAxis
drag.smoothed
:
false
property
bool
shiftTrim
:
false
property
bool
controlTrim
:
false
property
bool
sizeChanged
:
false
cursorShape
:
(
containsMouse
?
Qt
.
SizeHorCursor
:
Qt
.
ClosedHandCursor
);
onPressed
:
{
...
...
@@ -823,6 +824,7 @@ Rectangle {
clipRoot
.
originalDuration
=
clipDuration
parent
.
anchors
.
left
=
undefined
shiftTrim
=
mouse
.
modifiers
&
Qt
.
ShiftModifier
controlTrim
=
mouse
.
modifiers
&
Qt
.
ControlModifier
if
(
!
shiftTrim
&&
clipRoot
.
grouped
)
{
clipRoot
.
initGroupTrim
(
clipRoot
)
}
...
...
@@ -832,7 +834,7 @@ Rectangle {
root
.
stopScrolling
=
false
parent
.
anchors
.
left
=
clipRoot
.
left
if
(
sizeChanged
)
{
clipRoot
.
trimmedIn
(
clipRoot
,
shiftTrim
)
clipRoot
.
trimmedIn
(
clipRoot
,
shiftTrim
,
controlTrim
)
sizeChanged
=
false
}
}
...
...
@@ -845,7 +847,7 @@ Rectangle {
}
var
newDuration
=
clipDuration
-
delta
sizeChanged
=
true
clipRoot
.
trimmingIn
(
clipRoot
,
newDuration
,
mouse
,
shiftTrim
)
clipRoot
.
trimmingIn
(
clipRoot
,
newDuration
,
mouse
,
shiftTrim
,
controlTrim
)
}
}
}
...
...
@@ -877,6 +879,7 @@ Rectangle {
anchors.fill
:
parent
hoverEnabled
:
true
property
bool
shiftTrim
:
false
property
bool
controlTrim
:
false
property
bool
sizeChanged
:
false
cursorShape
:
(
containsMouse
?
Qt
.
SizeHorCursor
:
Qt
.
ClosedHandCursor
);
drag.target
:
parent
...
...
@@ -888,6 +891,7 @@ Rectangle {
clipRoot
.
originalDuration
=
clipDuration
parent
.
anchors
.
right
=
undefined
shiftTrim
=
mouse
.
modifiers
&
Qt
.
ShiftModifier
controlTrim
=
mouse
.
modifiers
&
Qt
.
ControlModifier
if
(
!
shiftTrim
&&
clipRoot
.
grouped
)
{
clipRoot
.
initGroupTrim
(
clipRoot
)
}
...
...
@@ -897,7 +901,7 @@ Rectangle {
root
.
stopScrolling
=
false
parent
.
anchors
.
right
=
clipRoot
.
right
if
(
sizeChanged
)
{
clipRoot
.
trimmedOut
(
clipRoot
,
shiftTrim
)
clipRoot
.
trimmedOut
(
clipRoot
,
shiftTrim
,
controlTrim
)
sizeChanged
=
false
}
}
...
...
@@ -906,7 +910,7 @@ Rectangle {
var
newDuration
=
Math
.
round
((
parent
.
x
+
parent
.
width
)
/
timeScale
)
if
(
newDuration
!=
clipDuration
)
{
sizeChanged
=
true
clipRoot
.
trimmingOut
(
clipRoot
,
newDuration
,
mouse
,
shiftTrim
)
clipRoot
.
trimmingOut
(
clipRoot
,
newDuration
,
mouse
,
shiftTrim
,
controlTrim
)
}
}
}
...
...
src/timeline2/view/qml/Track.qml
View file @
32423ba3
...
...
@@ -270,6 +270,15 @@ Column{
clip
.
groupTrimData
=
controller
.
getGroupData
(
clip
.
clipId
)
}
onTrimmingIn
:
{
if
(
controlTrim
)
{
newDuration
=
Math
.
max
(
1
,
newDuration
)
speedController
.
x
=
clip
.
x
+
clip
.
width
-
newDuration
*
trackRoot
.
timeScale
speedController
.
width
=
newDuration
*
trackRoot
.
timeScale
speedController
.
lastValidDuration
=
newDuration
speedController
.
speedText
=
(
100
*
clip
.
originalDuration
*
clip
.
speed
/
speedController
.
lastValidDuration
).
toFixed
(
2
)
+
'
%
'
speedController
.
visible
=
true
return
}
var
new_duration
=
controller
.
requestItemResize
(
clip
.
clipId
,
newDuration
,
false
,
false
,
root
.
snapping
,
shiftTrim
)
if
(
new_duration
>
0
)
{
clip
.
lastValidDuration
=
new_duration
...
...
@@ -285,10 +294,18 @@ Column{
}
onTrimmedIn
:
{
bubbleHelp
.
hide
()
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
)
{
if
(
controlTrim
)
{
speedController
.
visible
=
false
}
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
||
controlTrim
)
{
// We only resize one element
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
false
,
false
,
0
,
shiftTrim
)
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
false
,
true
,
0
,
shiftTrim
)
if
(
controlTrim
)
{
// Update speed
controller
.
requestClipResizeAndTimeWarp
(
clip
.
clipId
,
speedController
.
lastValidDuration
,
false
,
root
.
snapping
,
shiftTrim
,
clip
.
originalDuration
*
clip
.
speed
/
speedController
.
lastValidDuration
)
}
else
{
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
false
,
true
,
0
,
shiftTrim
)
}
}
else
{
var
updatedGroupData
=
controller
.
getGroupData
(
clip
.
clipId
)
controller
.
processGroupResize
(
clip
.
groupTrimData
,
updatedGroupData
,
false
)
...
...
@@ -296,6 +313,15 @@ Column{
clip
.
groupTrimData
=
undefined
}
onTrimmingOut
:
{
if
(
controlTrim
)
{
speedController
.
x
=
clip
.
x
newDuration
=
Math
.
max
(
1
,
newDuration
)
speedController
.
width
=
newDuration
*
trackRoot
.
timeScale
speedController
.
lastValidDuration
=
newDuration
speedController
.
speedText
=
(
100
*
clip
.
originalDuration
*
clip
.
speed
/
speedController
.
lastValidDuration
).
toFixed
(
2
)
+
'
%
'
speedController
.
visible
=
true
return
}
var
new_duration
=
controller
.
requestItemResize
(
clip
.
clipId
,
newDuration
,
true
,
false
,
root
.
snapping
,
shiftTrim
)
if
(
new_duration
>
0
)
{
clip
.
lastValidDuration
=
new_duration
...
...
@@ -310,9 +336,17 @@ Column{
}
onTrimmedOut
:
{
bubbleHelp
.
hide
()
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
)
{
if
(
controlTrim
)
{
speedController
.
visible
=
false
}
if
(
shiftTrim
||
clip
.
groupTrimData
==
undefined
||
controlTrim
)
{
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
originalDuration
,
true
,
false
,
0
,
shiftTrim
)
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
true
,
true
,
0
,
shiftTrim
)
if
(
controlTrim
)
{
// Update speed
controller
.
requestClipResizeAndTimeWarp
(
clip
.
clipId
,
speedController
.
lastValidDuration
,
true
,
root
.
snapping
,
shiftTrim
,
clip
.
originalDuration
*
clip
.
speed
/
speedController
.
lastValidDuration
)
}
else
{
controller
.
requestItemResize
(
clip
.
clipId
,
clip
.
lastValidDuration
,
true
,
true
,
0
,
shiftTrim
)
}
}
else
{
var
updatedGroupData
=
controller
.
getGroupData
(
clip
.
clipId
)
controller
.
processGroupResize
(
clip
.
groupTrimData
,
updatedGroupData
,
true
)
...
...
@@ -366,4 +400,23 @@ Column{
}
}
}
Rectangle
{
id
:
speedController
color
:
'
#aaff0000
'
visible
:
false
height
:
root
.
baseUnit
*
3
property
int
lastValidDuration
:
0
property
string
speedText
:
'
100%
'
Text
{
id
:
speedLabel
text
:
i18n
(
"
Adjusting speed:
\n
"
)
+
speedController
.
speedText
font.pixelSize
:
root
.
baseUnit
*
1.2
anchors.fill
:
parent
verticalAlignment
:
Text
.
AlignVCenter
horizontalAlignment
:
Text
.
AlignHCenter
color
:
'
white
'
style
:
Text
.
Outline
styleColor
:
'
black
'
}
}
}
src/timeline2/view/timelinecontroller.cpp
View file @
32423ba3
...
...
@@ -1515,7 +1515,7 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
speed
=
d
->
getValue
();
qDebug
()
<<
"requesting speed "
<<
speed
;
}
m_model
->
requestClipTimeWarp
(
clipId
,
speed
);
m_model
->
requestClipTimeWarp
(
clipId
,
speed
,
true
);
}
void
TimelineController
::
switchCompositing
(
int
mode
)
...
...
tests/timewarptest.cpp
View file @
32423ba3
...
...
@@ -59,7 +59,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
0.1
,
undo
,
redo
));
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
0.1
,
true
,
undo
,
redo
));
CHECK_UPDATE
(
TimelineModel
::
SpeedRole
);
REQUIRE
(
timeline
->
getClipSpeed
(
cid3
)
==
0.1
);
...
...
@@ -81,7 +81,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
std
::
function
<
bool
(
void
)
>
undo2
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo2
=
[]()
{
return
true
;
};
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
1.2
,
undo2
,
redo2
));
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
1.2
,
true
,
undo2
,
redo2
));
CHECK_UPDATE
(
TimelineModel
::
SpeedRole
);
REQUIRE
(
timeline
->
getClipSpeed
(
cid3
)
==
1.2
);
...
...
@@ -102,7 +102,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
int
curLength
=
timeline
->
getClipPlaytime
(
cid3
);
// This is the limit, should work
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
double
(
curLength
),
undo2
,
redo2
));
REQUIRE
(
timeline
->
requestClipTimeWarp
(
cid3
,
double
(
curLength
),
true
,
undo2
,
redo2
));
CHECK_UPDATE
(
TimelineModel
::
SpeedRole
);
REQUIRE
(
timeline
->
getClipSpeed
(
cid3
)
==
double
(
curLength
));
...
...
@@ -110,7 +110,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
// This is the higher than the limit, should not work
// (we have some error margin in duration rounding, multiply by 10)
REQUIRE_FALSE
(
timeline
->
requestClipTimeWarp
(
cid3
,
double
(
curLength
)
*
10
,
undo2
,
redo2
));
REQUIRE_FALSE
(
timeline
->
requestClipTimeWarp
(
cid3
,
double
(
curLength
)
*
10
,
true
,
undo2
,
redo2
));
}
binModel
->
clean
();
pCore
->
m_projectManager
=
nullptr
;
...
...
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