Skip to content
GitLab
Menu
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
bab26ba7
Commit
bab26ba7
authored
Nov 26, 2020
by
Jean-Baptiste Mardelle
Browse files
Various mix and transition fixes.
Fixes
#851
parent
1b506986
Changes
11
Hide whitespace changes
Inline
Side-by-side
data/transitions/luma.xml
View file @
bab26ba7
<!DOCTYPE kpartgui>
<transition
tag=
"luma"
id=
"luma"
type=
"hidden"
>
<transition
tag=
"luma"
id=
"luma"
>
<name>
Luma
</name>
<description>
Applies a stationary transition between the current and next frames.
</description>
<author>
Dan Dennedy
</author>
...
...
src/assets/assetpanel.cpp
View file @
bab26ba7
...
...
@@ -73,6 +73,8 @@ AssetPanel::AssetPanel(QWidget *parent)
connect
(
m_switchCompoButton
,
static_cast
<
void
(
QComboBox
::*
)(
int
)
>
(
&
QComboBox
::
activated
),
this
,
[
&
]()
{
if
(
m_transitionWidget
->
stackOwner
().
first
==
ObjectType
::
TimelineComposition
)
{
emit
switchCurrentComposition
(
m_transitionWidget
->
stackOwner
().
second
,
m_switchCompoButton
->
currentData
().
toString
());
}
else
if
(
m_mixWidget
->
isVisible
())
{
emit
switchCurrentComposition
(
m_mixWidget
->
stackOwner
().
second
,
m_switchCompoButton
->
currentData
().
toString
());
}
});
m_switchCompoButton
->
setToolTip
(
i18n
(
"Change composition type"
));
...
...
@@ -146,6 +148,7 @@ AssetPanel::AssetPanel(QWidget *parent)
connect
(
m_effectStackWidget
,
&
EffectStackView
::
seekToPos
,
this
,
&
AssetPanel
::
seekToPos
);
connect
(
m_effectStackWidget
,
&
EffectStackView
::
reloadEffect
,
this
,
&
AssetPanel
::
reloadEffect
);
connect
(
m_transitionWidget
,
&
TransitionStackView
::
seekToTransPos
,
this
,
&
AssetPanel
::
seekToPos
);
connect
(
m_mixWidget
,
&
MixStackView
::
seekToTransPos
,
this
,
&
AssetPanel
::
seekToPos
);
connect
(
m_effectStackWidget
,
&
EffectStackView
::
updateEnabledState
,
this
,
[
this
]()
{
m_enableStackButton
->
setActive
(
m_effectStackWidget
->
isStackEnabled
());
});
}
...
...
@@ -158,8 +161,7 @@ void AssetPanel::showTransition(int tid, const std::shared_ptr<AssetParameterMod
return
;
}
clear
();
QString
transitionId
=
transitionModel
->
getAssetId
();
m_switchCompoButton
->
setCurrentIndex
(
m_switchCompoButton
->
findData
(
transitionId
));
m_switchCompoButton
->
setCurrentIndex
(
m_switchCompoButton
->
findData
(
transitionModel
->
getAssetId
()));
m_switchAction
->
setVisible
(
true
);
m_titleAction
->
setVisible
(
false
);
m_assetTitle
->
clear
();
...
...
@@ -181,12 +183,13 @@ void AssetPanel::showMix(int cid, const std::shared_ptr<AssetParameterModel> &tr
return
;
}
clear
();
m_switchAction
->
setVisible
(
fals
e
);
m_switchAction
->
setVisible
(
tru
e
);
m_titleAction
->
setVisible
(
false
);
m_assetTitle
->
clear
();
m_mixWidget
->
setVisible
(
true
);
m_timelineButton
->
setVisible
(
false
);
m_enableStackButton
->
setVisible
(
false
);
m_switchCompoButton
->
setCurrentIndex
(
m_switchCompoButton
->
findData
(
transitionModel
->
getAssetId
()));
m_mixWidget
->
setModel
(
transitionModel
,
QSize
(),
true
);
}
...
...
@@ -269,11 +272,16 @@ void AssetPanel::clearAssetPanel(int itemId)
ObjectId
id
=
m_effectStackWidget
->
stackOwner
();
if
(
id
.
first
==
ObjectType
::
TimelineClip
&&
id
.
second
==
itemId
)
{
clear
();
}
else
{
id
=
m_transitionWidget
->
stackOwner
();
if
(
id
.
first
==
ObjectType
::
TimelineComposition
&&
id
.
second
==
itemId
)
{
clear
();
}
return
;
}
id
=
m_transitionWidget
->
stackOwner
();
if
(
id
.
first
==
ObjectType
::
TimelineComposition
&&
id
.
second
==
itemId
)
{
clear
();
return
;
}
id
=
m_mixWidget
->
stackOwner
();
if
(
id
.
first
==
ObjectType
::
TimelineMix
&&
id
.
second
==
itemId
)
{
clear
();
}
}
...
...
@@ -303,6 +311,7 @@ void AssetPanel::updatePalette()
setStyleSheet
(
styleSheet
);
m_transitionWidget
->
setStyleSheet
(
styleSheet
);
m_effectStackWidget
->
setStyleSheet
(
styleSheet
);
m_mixWidget
->
setStyleSheet
(
styleSheet
);
}
// static
...
...
@@ -387,22 +396,25 @@ void AssetPanel::processSplitEffect(bool enable)
void
AssetPanel
::
showKeyframes
(
bool
enable
)
{
if
(
m_transitionWidget
->
isVisible
())
{
pCore
->
showClipKeyframes
(
m_transitionWidget
->
stackOwner
(),
enable
);
}
else
{
if
(
m_effectStackWidget
->
isVisible
())
{
pCore
->
showClipKeyframes
(
m_effectStackWidget
->
stackOwner
(),
enable
);
}
else
if
(
m_transitionWidget
->
isVisible
())
{
pCore
->
showClipKeyframes
(
m_transitionWidget
->
stackOwner
(),
enable
);
}
}
ObjectId
AssetPanel
::
effectStackOwner
()
{
if
(
m_effectStackWidget
->
isVisible
())
{
return
m_effectStackWidget
->
stackOwner
();
}
if
(
m_transitionWidget
->
isVisible
())
{
return
m_transitionWidget
->
stackOwner
();
}
if
(
!
m_
effectStack
Widget
->
isVisible
())
{
return
ObjectId
(
ObjectType
::
NoItem
,
-
1
);
if
(
m_
mix
Widget
->
isVisible
())
{
return
m_mixWidget
->
stackOwner
(
);
}
return
m_effectStackWidget
->
stackOwner
(
);
return
ObjectId
(
ObjectType
::
NoItem
,
-
1
);
}
bool
AssetPanel
::
addEffect
(
const
QString
&
effectId
)
...
...
src/core.cpp
View file @
bab26ba7
...
...
@@ -452,6 +452,13 @@ int Core::getItemPosition(const ObjectId &id)
return
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
getCompositionPosition
(
id
.
second
);
}
break
;
case
ObjectType
::
TimelineMix
:
if
(
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
isClip
(
id
.
second
))
{
return
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
getMixInOut
(
id
.
second
).
first
;
}
else
{
qDebug
()
<<
"// ERROR QUERYING NON CLIP PROPERTIES
\n\n
!!!!!!!!!!!!!!!!!!!!!!!!!!"
;
}
break
;
case
ObjectType
::
BinClip
:
case
ObjectType
::
TimelineTrack
:
case
ObjectType
::
Master
:
...
...
@@ -477,6 +484,7 @@ int Core::getItemIn(const ObjectId &id)
qDebug
()
<<
"// ERROR QUERYING NON CLIP PROPERTIES
\n\n
!!!!!!!!!!!!!!!!!!!!!!!!!!"
;
}
break
;
case
ObjectType
::
TimelineMix
:
case
ObjectType
::
TimelineComposition
:
case
ObjectType
::
BinClip
:
case
ObjectType
::
TimelineTrack
:
...
...
@@ -536,6 +544,14 @@ int Core::getItemDuration(const ObjectId &id)
case
ObjectType
::
TimelineTrack
:
case
ObjectType
::
Master
:
return
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
duration
()
-
1
;
case
ObjectType
::
TimelineMix
:
if
(
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
isClip
(
id
.
second
))
{
std
::
pair
<
int
,
int
>
mixInOut
=
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
getMixInOut
(
id
.
second
);
return
(
mixInOut
.
second
-
mixInOut
.
first
);
}
else
{
qDebug
()
<<
"// ERROR QUERYING NON CLIP PROPERTIES
\n\n
!!!!!!!!!!!!!!!!!!!!!!!!!!"
;
}
break
;
default:
qDebug
()
<<
"ERROR: unhandled object type"
;
}
...
...
@@ -548,6 +564,7 @@ int Core::getItemTrack(const ObjectId &id)
switch
(
id
.
first
)
{
case
ObjectType
::
TimelineClip
:
case
ObjectType
::
TimelineComposition
:
case
ObjectType
::
TimelineMix
:
return
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
getItemTrackId
(
id
.
second
);
break
;
default:
...
...
@@ -561,6 +578,7 @@ void Core::refreshProjectItem(const ObjectId &id)
if
(
!
m_guiConstructed
||
m_mainWindow
->
getCurrentTimeline
()
->
loading
)
return
;
switch
(
id
.
first
)
{
case
ObjectType
::
TimelineClip
:
case
ObjectType
::
TimelineMix
:
if
(
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
getModel
()
->
isClip
(
id
.
second
))
{
m_mainWindow
->
getCurrentTimeline
()
->
controller
()
->
refreshItem
(
id
.
second
);
}
...
...
src/mainwindow.cpp
View file @
bab26ba7
...
...
@@ -388,6 +388,7 @@ void MainWindow::init()
case
ObjectType
::
TimelineClip
:
case
ObjectType
::
TimelineComposition
:
case
ObjectType
::
Master
:
case
ObjectType
::
TimelineMix
:
m_projectMonitor
->
requestSeek
(
pos
);
break
;
case
ObjectType
::
BinClip
:
...
...
src/timeline2/model/timelinemodel.cpp
View file @
bab26ba7
...
...
@@ -5122,6 +5122,29 @@ std::unordered_set<int> TimelineModel::getAllTracksIds() const
void
TimelineModel
::
switchComposition
(
int
cid
,
const
QString
&
compoId
)
{
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
if
(
isClip
(
cid
))
{
// We are working on a mix
requestClearSelection
(
true
);
int
tid
=
getClipTrackId
(
cid
);
MixInfo
mixData
=
getTrackById_const
(
tid
)
->
getMixInfo
(
cid
).
first
;
getTrackById
(
tid
)
->
switchMix
(
cid
,
compoId
,
undo
,
redo
);
Fun
local_update
=
[
cid
,
mixData
,
this
]()
{
requestMixSelection
(
cid
);
int
in
=
mixData
.
secondClipInOut
.
first
;
int
out
=
mixData
.
firstClipInOut
.
second
;
emit
invalidateZone
(
in
,
out
);
checkRefresh
(
in
,
out
);
return
true
;
};
PUSH_LAMBDA
(
local_update
,
redo
);
PUSH_FRONT_LAMBDA
(
local_update
,
undo
);
if
(
redo
())
{
pCore
->
pushUndo
(
undo
,
redo
,
i18n
(
"Change composition"
));
}
return
;
}
Q_ASSERT
(
isComposition
(
cid
));
std
::
shared_ptr
<
CompositionModel
>
compo
=
m_allCompositions
.
at
(
cid
);
int
currentPos
=
compo
->
getPosition
();
...
...
@@ -5129,8 +5152,6 @@ void TimelineModel::switchComposition(int cid, const QString &compoId)
int
currentTrack
=
compo
->
getCurrentTrackId
();
int
a_track
=
compo
->
getATrack
();
int
forcedTrack
=
compo
->
getForcedTrack
();
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
// Clear selection
requestClearSelection
(
true
);
if
(
m_groups
->
isInGroup
(
cid
))
{
...
...
@@ -5171,13 +5192,13 @@ void TimelineModel::plantMix(int tid, Mlt::Transition *t)
bool
TimelineModel
::
resizeStartMix
(
int
cid
,
int
duration
,
bool
singleResize
)
{
Q_ASSERT
(
isClip
(
cid
));
int
tid
=
m_allClips
[
cid
]
->
getCurrentTrackId
();
int
tid
=
m_allClips
.
at
(
cid
)
->
getCurrentTrackId
();
if
(
tid
>
-
1
)
{
std
::
pair
<
MixInfo
,
MixInfo
>
mixData
=
getTrackById_const
(
tid
)
->
getMixInfo
(
cid
);
if
(
mixData
.
first
.
firstClipId
>
-
1
)
{
int
clipToResize
=
mixData
.
first
.
firstClipId
;
Q_ASSERT
(
isClip
(
clipToResize
));
int
updatedDuration
=
m_allClips
[
cid
]
->
getPosition
()
+
duration
-
m_allClips
[
clipToResize
]
->
getPosition
();
int
updatedDuration
=
m_allClips
.
at
(
cid
)
->
getPosition
()
+
duration
-
m_allClips
[
clipToResize
]
->
getPosition
();
int
result
=
requestItemResize
(
clipToResize
,
updatedDuration
,
true
,
true
,
0
,
singleResize
);
return
result
>
-
1
;
}
...
...
@@ -5185,6 +5206,19 @@ bool TimelineModel::resizeStartMix(int cid, int duration, bool singleResize)
return
false
;
}
std
::
pair
<
int
,
int
>
TimelineModel
::
getMixInOut
(
int
cid
)
const
{
Q_ASSERT
(
isClip
(
cid
));
int
tid
=
m_allClips
.
at
(
cid
)
->
getCurrentTrackId
();
if
(
tid
>
-
1
)
{
MixInfo
mixData
=
getTrackById_const
(
tid
)
->
getMixInfo
(
cid
).
first
;
if
(
mixData
.
firstClipId
>
-
1
)
{
return
{
mixData
.
secondClipInOut
.
first
,
mixData
.
firstClipInOut
.
second
};
}
}
return
{
-
1
,
-
1
};
}
void
TimelineModel
::
setSubModel
(
std
::
shared_ptr
<
SubtitleModel
>
model
)
{
m_subtitleModel
=
std
::
move
(
model
);
...
...
src/timeline2/model/timelinemodel.hpp
View file @
bab26ba7
...
...
@@ -217,6 +217,7 @@ public:
Q_INVOKABLE
int
getCompositionPosition
(
int
compoId
)
const
;
int
getSubtitlePosition
(
int
subId
)
const
;
int
getCompositionPlaytime
(
int
compoId
)
const
;
std
::
pair
<
int
,
int
>
getMixInOut
(
int
cid
)
const
;
/* Returns an item position, item can be clip or composition */
Q_INVOKABLE
int
getItemPosition
(
int
itemId
)
const
;
...
...
src/timeline2/model/trackmodel.cpp
View file @
bab26ba7
...
...
@@ -1292,6 +1292,13 @@ Fun TrackModel::requestCompositionDeletion_lambda(int compoId, bool updateView,
return
[
compoId
,
old_in
,
old_out
,
updateView
,
finalMove
,
this
]()
{
if
(
isLocked
())
return
false
;
int
old_clip_index
=
getRowfromComposition
(
compoId
);
if
(
finalMove
&&
m_allCompositions
[
compoId
]
->
selected
)
{
m_allCompositions
[
compoId
]
->
selected
=
false
;
if
(
auto
ptr
=
m_parent
.
lock
())
{
// item was selected, unselect
ptr
->
requestClearSelection
(
true
);
}
}
auto
ptr
=
m_parent
.
lock
();
if
(
updateView
)
{
ptr
->
_beginRemoveRows
(
ptr
->
makeTrackIndexFromID
(
getId
()),
old_clip_index
,
old_clip_index
);
...
...
@@ -1546,6 +1553,8 @@ bool TrackModel::requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &r
}
if
(
result
)
{
PUSH_LAMBDA
(
local_redo
,
redo
);
QString
assetId
=
m_sameCompositions
[
clipIds
.
second
]
->
getAssetId
();
QVector
<
QPair
<
QString
,
QVariant
>>
params
=
m_sameCompositions
[
clipIds
.
second
]
->
getAllParameters
();
Fun
replay
=
[
this
,
clipIds
,
secondInPos
,
clipHasEndMix
,
src_track
]()
{
if
(
src_track
==
1
&&
!
clipHasEndMix
)
{
// Revert clip to playlist 0 since it has no mix
...
...
@@ -1570,7 +1579,7 @@ bool TrackModel::requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &r
return
true
;
};
replay
();
Fun
reverse
=
[
this
,
clipIds
,
mixDuration
,
mixPosition
,
mixCutPos
,
secondInPos
,
clipHasEndMix
,
src_track
]()
{
Fun
reverse
=
[
this
,
clipIds
,
assetId
,
params
,
mixDuration
,
mixPosition
,
mixCutPos
,
secondInPos
,
clipHasEndMix
,
src_track
]()
{
// First restore correct playlist
if
(
src_track
==
1
&&
!
clipHasEndMix
)
{
// Revert clip to playlist 1
...
...
@@ -1582,31 +1591,24 @@ bool TrackModel::requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &r
movedClip
->
setMixDuration
(
mixDuration
,
mixCutPos
);
// Insert mix transition
QString
assetName
;
std
::
unique_ptr
<
Mlt
::
Transition
>
t
;
if
(
isAudioTrack
())
{
t
.
reset
(
new
Mlt
::
Transition
(
*
ptr
->
getProfile
(),
"mix"
));
t
->
set_in_and_out
(
mixPosition
,
mixPosition
+
mixDuration
);
t
->
set
(
"kdenlive:mixcut"
,
mixCutPos
);
t
->
set
(
"start"
,
-
1
);
t
->
set
(
"accepts_blanks"
,
1
);
if
(
src_track
==
0
)
{
t
->
set
(
"reverse"
,
1
);
}
m_track
->
plant_transition
(
*
t
.
get
(),
0
,
1
);
assetName
=
QStringLiteral
(
"mix"
);
}
else
{
t
.
reset
(
new
Mlt
::
Transition
(
*
ptr
->
getProfile
(),
"luma"
));
t
->
set_in_and_out
(
mixPosition
,
mixPosition
+
mixDuration
);
t
->
set
(
"kdenlive:mixcut"
,
mixCutPos
);
if
(
src_track
==
0
)
{
t
->
set
(
"reverse"
,
1
);
std
::
unique_ptr
<
Mlt
::
Transition
>
t
=
TransitionsRepository
::
get
()
->
getTransition
(
assetId
);
t
->
set_in_and_out
(
mixPosition
,
mixPosition
+
mixDuration
);
t
->
set
(
"kdenlive:mixcut"
,
mixCutPos
);
t
->
set
(
"kdenlive_id"
,
assetId
.
toUtf8
().
constData
());
m_track
->
plant_transition
(
*
t
.
get
(),
0
,
1
);
QDomElement
xml
=
TransitionsRepository
::
get
()
->
getXml
(
assetId
);
QDomNodeList
xmlParams
=
xml
.
elementsByTagName
(
QStringLiteral
(
"parameter"
));
for
(
int
i
=
0
;
i
<
xmlParams
.
count
();
++
i
)
{
QDomElement
currentParameter
=
xmlParams
.
item
(
i
).
toElement
();
QString
paramName
=
currentParameter
.
attribute
(
QStringLiteral
(
"name"
));
for
(
const
auto
&
p
:
qAsConst
(
params
))
{
if
(
p
.
first
==
paramName
)
{
currentParameter
.
setAttribute
(
QStringLiteral
(
"value"
),
p
.
second
.
toString
());
break
;
}
}
m_track
->
plant_transition
(
*
t
.
get
(),
0
,
1
);
assetName
=
QStringLiteral
(
"luma"
);
}
QDomElement
xml
=
TransitionsRepository
::
get
()
->
getXml
(
assetName
);
std
::
shared_ptr
<
AssetParameterModel
>
asset
(
new
AssetParameterModel
(
std
::
move
(
t
),
xml
,
assetName
,
{
ObjectType
::
TimelineMix
,
clipIds
.
second
},
QString
()));
std
::
shared_ptr
<
AssetParameterModel
>
asset
(
new
AssetParameterModel
(
std
::
move
(
t
),
xml
,
assetId
,
{
ObjectType
::
TimelineMix
,
clipIds
.
second
},
QString
()));
m_sameCompositions
[
clipIds
.
second
]
=
asset
;
m_mixList
.
insert
(
clipIds
.
first
,
clipIds
.
second
);
QModelIndex
ix2
=
ptr
->
makeClipIndexFromID
(
clipIds
.
second
);
...
...
@@ -1837,6 +1839,7 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, int mixDuration, bo
t
.
reset
(
new
Mlt
::
Transition
(
*
ptr
->
getProfile
(),
"luma"
));
t
->
set_in_and_out
(
mixPosition
,
mixPosition
+
mixDuration
);
t
->
set
(
"kdenlive:mixcut"
,
secondClipCut
);
t
->
set
(
"kdenlive_id"
,
"luma"
);
if
(
dest_track
==
0
)
{
t
->
set
(
"reverse"
,
1
);
}
...
...
@@ -2031,6 +2034,7 @@ bool TrackModel::createMix(MixInfo info, bool isAudio)
}
else
{
t
.
reset
(
new
Mlt
::
Transition
(
*
ptr
->
getProfile
(),
"luma"
));
t
->
set_in_and_out
(
in
,
out
);
t
->
set
(
"kdenlive_id"
,
"luma"
);
if
(
reverse
)
{
t
->
set
(
"reverse"
,
1
);
}
...
...
@@ -2072,6 +2076,7 @@ bool TrackModel::createMix(std::pair<int, int> clipIds, std::pair<int, int> mixD
assetName
=
QStringLiteral
(
"mix"
);
}
else
{
t
.
reset
(
new
Mlt
::
Transition
(
*
ptr
->
getProfile
(),
"luma"
));
t
->
set
(
"kdenlive_id"
,
"luma"
);
t
->
set_in_and_out
(
mixData
.
first
,
mixData
.
first
+
mixData
.
second
);
if
(
reverse
)
{
t
->
set
(
"reverse"
,
1
);
...
...
@@ -2184,7 +2189,10 @@ bool TrackModel::loadMix(Mlt::Transition *t)
if
(
cid1
<
0
||
cid2
<
0
)
{
return
false
;
}
const
QString
assetId
(
t
->
get
(
"mlt_service"
));
QString
assetId
(
t
->
get
(
"kdenlive_id"
));
if
(
assetId
.
isEmpty
())
{
assetId
=
QString
(
t
->
get
(
"mlt_service"
));
}
std
::
unique_ptr
<
Mlt
::
Transition
>
tr
(
t
);
QDomElement
xml
=
TransitionsRepository
::
get
()
->
getXml
(
assetId
);
// Paste parameters from existing mix
...
...
@@ -2226,3 +2234,57 @@ bool TrackModel::reAssignEndMix(int currentId, int newId)
m_mixList
.
insert
(
newId
,
mixedClip
);
return
true
;
}
void
TrackModel
::
switchMix
(
int
cid
,
const
QString
composition
,
Fun
&
undo
,
Fun
&
redo
)
{
// First remove exisiting mix
// lock MLT playlist so that we don't end up with invalid frames in monitor
const
QString
currentAsset
=
m_sameCompositions
[
cid
]
->
getAssetId
();
Fun
local_redo
=
[
this
,
cid
,
composition
]()
{
m_playlists
[
0
].
lock
();
m_playlists
[
1
].
lock
();
Mlt
::
Transition
&
transition
=
*
static_cast
<
Mlt
::
Transition
*>
(
m_sameCompositions
[
cid
]
->
getAsset
());
int
in
=
transition
.
get_in
();
int
out
=
transition
.
get_out
();
QScopedPointer
<
Mlt
::
Field
>
field
(
m_track
->
field
());
field
->
lock
();
field
->
disconnect_service
(
transition
);
field
->
unlock
();
m_sameCompositions
.
erase
(
cid
);
if
(
auto
ptr
=
m_parent
.
lock
())
{
std
::
unique_ptr
<
Mlt
::
Transition
>
t
=
TransitionsRepository
::
get
()
->
getTransition
(
composition
);
t
->
set_in_and_out
(
in
,
out
);
m_track
->
plant_transition
(
*
t
.
get
(),
0
,
1
);
QDomElement
xml
=
TransitionsRepository
::
get
()
->
getXml
(
composition
);
std
::
shared_ptr
<
AssetParameterModel
>
asset
(
new
AssetParameterModel
(
std
::
move
(
t
),
xml
,
composition
,
{
ObjectType
::
TimelineMix
,
cid
},
QString
()));
m_sameCompositions
[
cid
]
=
asset
;
}
m_playlists
[
0
].
unlock
();
m_playlists
[
1
].
unlock
();
return
true
;
};
Fun
local_undo
=
[
this
,
cid
,
currentAsset
]()
{
m_playlists
[
0
].
lock
();
m_playlists
[
1
].
lock
();
Mlt
::
Transition
&
transition
=
*
static_cast
<
Mlt
::
Transition
*>
(
m_sameCompositions
[
cid
]
->
getAsset
());
int
in
=
transition
.
get_in
();
int
out
=
transition
.
get_out
();
QScopedPointer
<
Mlt
::
Field
>
field
(
m_track
->
field
());
field
->
lock
();
field
->
disconnect_service
(
transition
);
field
->
unlock
();
m_sameCompositions
.
erase
(
cid
);
if
(
auto
ptr
=
m_parent
.
lock
())
{
std
::
unique_ptr
<
Mlt
::
Transition
>
t
=
TransitionsRepository
::
get
()
->
getTransition
(
currentAsset
);
t
->
set_in_and_out
(
in
,
out
);
m_track
->
plant_transition
(
*
t
.
get
(),
0
,
1
);
QDomElement
xml
=
TransitionsRepository
::
get
()
->
getXml
(
currentAsset
);
std
::
shared_ptr
<
AssetParameterModel
>
asset
(
new
AssetParameterModel
(
std
::
move
(
t
),
xml
,
currentAsset
,
{
ObjectType
::
TimelineMix
,
cid
},
QString
()));
m_sameCompositions
[
cid
]
=
asset
;
}
m_playlists
[
0
].
unlock
();
m_playlists
[
1
].
unlock
();
return
true
;
};
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
}
src/timeline2/model/trackmodel.hpp
View file @
bab26ba7
...
...
@@ -134,6 +134,7 @@ public:
bool
createMix
(
MixInfo
info
,
bool
isAudio
);
/** @brief Change id of first clip in a mix (in case of clip cut) */
bool
reAssignEndMix
(
int
currentId
,
int
newId
);
void
switchMix
(
int
cid
,
const
QString
composition
,
Fun
&
undo
,
Fun
&
redo
);
/** @brief Ensure we don't have unsynced mixes in the playlist (mixes without owner clip) */
void
syncronizeMixes
(
bool
finalMove
);
/** @brief Switch a clip from one playlist to the other */
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
bab26ba7
...
...
@@ -489,6 +489,8 @@ void TimelineController::deleteSelectedClips()
// Check if a mix is selected
if
(
m_model
->
m_selectedMix
>
-
1
&&
m_model
->
isClip
(
m_model
->
m_selectedMix
))
{
m_model
->
removeMix
(
m_model
->
m_selectedMix
);
m_model
->
clearAssetView
(
m_model
->
m_selectedMix
);
m_model
->
requestClearSelection
(
true
);
}
return
;
}
...
...
src/transitions/view/mixstackview.cpp
View file @
bab26ba7
...
...
@@ -40,6 +40,7 @@ MixStackView::MixStackView(QWidget *parent)
void
MixStackView
::
setModel
(
const
std
::
shared_ptr
<
AssetParameterModel
>
&
model
,
QSize
frameSize
,
bool
addSpacer
)
{
AssetParameterView
::
setModel
(
model
,
frameSize
,
addSpacer
);
m_model
->
setActive
(
true
);
auto
kfr
=
model
->
getKeyframeModel
();
if
(
kfr
)
{
connect
(
kfr
.
get
(),
&
KeyframeModelList
::
modelChanged
,
this
,
&
AssetParameterView
::
slotRefresh
);
...
...
@@ -58,6 +59,7 @@ void MixStackView::setModel(const std::shared_ptr<AssetParameterModel> &model, Q
void
MixStackView
::
unsetModel
()
{
if
(
m_model
)
{
m_model
->
setActive
(
false
);
auto
kfr
=
m_model
->
getKeyframeModel
();
if
(
kfr
)
{
disconnect
(
kfr
.
get
(),
&
KeyframeModelList
::
modelChanged
,
this
,
&
AssetParameterView
::
slotRefresh
);
...
...
src/transitions/view/transitionstackview.cpp
View file @
bab26ba7
...
...
@@ -66,6 +66,7 @@ void TransitionStackView::setModel(const std::shared_ptr<AssetParameterModel> &m
auto
*
lay
=
new
QHBoxLayout
;
m_trackBox
=
new
QComboBox
(
this
);
AssetParameterView
::
setModel
(
model
,
frameSize
,
addSpacer
);
model
->
setActive
(
true
);
refreshTracks
();
QLabel
*
title
=
new
QLabel
(
i18n
(
"Composition track:"
),
this
);
lay
->
addWidget
(
title
);
...
...
@@ -91,6 +92,7 @@ void TransitionStackView::setModel(const std::shared_ptr<AssetParameterModel> &m
void
TransitionStackView
::
unsetModel
()
{
if
(
m_model
)
{
m_model
->
setActive
(
false
);
disconnect
(
m_model
.
get
(),
&
AssetParameterModel
::
compositionTrackChanged
,
this
,
&
TransitionStackView
::
checkCompoTrack
);
auto
kfr
=
m_model
->
getKeyframeModel
();
if
(
kfr
)
{
...
...
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