Commit 026f2109 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Another round of mix resize issues, with added tests

parent 4a7218d6
......@@ -79,8 +79,8 @@ bool TimelineFunctions::cloneClip(const std::shared_ptr<TimelineItemModel> &time
int duration = timeline->getClipPlaytime(clipId);
int init_duration = timeline->getClipPlaytime(newId);
if (duration != init_duration) {
int in = timeline->m_allClips[clipId]->getIn();
res = res && timeline->requestItemResize(newId, init_duration - in, false, true, undo, redo);
init_duration -= timeline->m_allClips[clipId]->getIn();
res = res && timeline->requestItemResize(newId, init_duration, false, true, undo, redo);
res = res && timeline->requestItemResize(newId, duration, true, true, undo, redo);
}
if (!res) {
......@@ -133,14 +133,16 @@ bool TimelineFunctions::processClipCut(const std::shared_ptr<TimelineItemModel>
// Check if clip has an end Mix
bool res = cloneClip(timeline, clipId, newId, state, undo, redo);
timeline->m_blockRefresh = true;
res = res && timeline->requestItemResize(clipId, position - start, true, true, undo, redo);
int updatedDuration = position - start;
res = res && timeline->requestItemResize(clipId, updatedDuration, true, true, undo, redo);
int newDuration = timeline->getClipPlaytime(clipId);
// parse effects
std::shared_ptr<EffectStackModel> sourceStack = timeline->getClipEffectStackModel(clipId);
sourceStack->cleanFadeEffects(true, undo, redo);
std::shared_ptr<EffectStackModel> destStack = timeline->getClipEffectStackModel(newId);
destStack->cleanFadeEffects(false, undo, redo);
res = res && timeline->requestItemResize(newId, duration - newDuration, false, true, undo, redo);
updatedDuration = duration - newDuration;
res = res && timeline->requestItemResize(newId, updatedDuration, false, true, undo, redo);
// The next requestclipmove does not check for duration change since we don't invalidate timeline, so check duration change now
bool durationChanged = trackDuration != timeline->getTrackById_const(trackId)->trackDuration();
timeline->m_allClips[newId]->setSubPlaylistIndex(timeline->m_allClips[clipId]->getSubPlaylistIndex(), trackId);
......
......@@ -1586,9 +1586,11 @@ bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, Playl
int initLength = m_allClips[clipId]->getPlaytime();
bool res = true;
if (in != 0) {
res = requestItemResize(clipId, initLength - in, false, true, local_undo, local_redo);
initLength -= in;
res = requestItemResize(clipId, initLength, false, true, local_undo, local_redo);
}
res = res && requestItemResize(clipId, out - in + 1, true, true, local_undo, local_redo);
int updatedDuration = out - in + 1;
res = res && requestItemResize(clipId, updatedDuration, true, true, local_undo, local_redo);
if (!res) {
bool undone = local_undo();
Q_ASSERT(undone);
......@@ -2796,7 +2798,8 @@ void TimelineModel::processGroupResize(QVariantList startPos, QVariantList endPo
}
for (int id : qAsConst(changedItems)) {
QPair<int, int> endItemPos = endData.value(id);
result = result & requestItemResize(id, endItemPos.second, right, true, undo, redo, false);
int duration = endItemPos.second;
result = result & requestItemResize(id, duration, right, true, undo, redo, false);
if (!result) {
break;
}
......@@ -3079,7 +3082,7 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
if (getTrackById_const(tid)->hasEndMix(itemId)) {
tracksWithMixes << tid;
std::pair<MixInfo, MixInfo> mixData = getTrackById_const(tid)->getMixInfo(itemId);
if (in + size <= mixData.second.secondClipInOut.first + m_allClips[mixData.second.secondClipId]->getMixDuration() - m_allClips[mixData.second.secondClipId]->getMixCutPosition()) {
if (in + size < mixData.second.secondClipInOut.first + m_allClips[mixData.second.secondClipId]->getMixDuration() - m_allClips[mixData.second.secondClipId]->getMixCutPosition()) {
// Clip resized outside of mix zone, mix will be deleted
bool res = removeMixWithUndo(mixData.second.secondClipId, undo, redo);
if (res) {
......@@ -3263,6 +3266,9 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
finalSize = qMax(0, getItemPosition(id)) + getItemPlaytime(id) - finalPos;
}
result = result && requestItemResize(id, finalSize, right, logUndo, undo, redo);
if (id == itemId) {
size = finalSize;
}
resizedCount++;
}
if (!result || resizedCount == 0) {
......@@ -3293,7 +3299,7 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
return res;
}
bool TimelineModel::requestItemResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo)
bool TimelineModel::requestItemResize(int itemId, int &size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo)
{
Q_UNUSED(blockUndo)
Fun local_undo = []() { return true; };
......@@ -6195,10 +6201,12 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align,
updatedDurationRight = qMin(updatedDurationRight, m_allClips.at(cid)->getPlaytime() + rightMax);
}
if (updatedDurationLeft != 0) {
requestItemResize(cid, m_allClips.at(cid)->getPlaytime() + updatedDurationLeft, false, true, undo, redo);
int updatedDurL = m_allClips.at(cid)->getPlaytime() + updatedDurationLeft;
requestItemResize(cid, updatedDurL, false, true, undo, redo);
}
if (updatedDurationRight != 0) {
requestItemResize(clipToResize, m_allClips.at(clipToResize)->getPlaytime() + updatedDurationRight, true, true, undo, redo);
int updatedDurR = m_allClips.at(clipToResize)->getPlaytime() + updatedDurationRight;
requestItemResize(clipToResize, updatedDurR, true, true, undo, redo);
}
int mixCutPos = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime() - cutPos;
int updatedDuration = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime() - m_allClips.at(cid)->getPosition();
......
......@@ -506,7 +506,7 @@ public:
Q_INVOKABLE int requestItemResize(int itemId, int size, bool right, bool logUndo = true, int snapDistance = -1, bool allowSingleResize = false);
/** @brief Same function, but accumulates undo and redo and doesn't deal with snapping*/
bool requestItemResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false);
bool requestItemResize(int itemId, int &size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false);
/** @brief @todo TODO */
Q_INVOKABLE int requestItemRippleResize(int itemId, int size, bool right, bool logUndo = true, int snapDistance = -1, bool allowSingleResize = false);
......
......@@ -654,7 +654,6 @@ Fun TrackModel::requestClipResize_lambda(int clipId, int in, int out, bool right
if (delta == 0) {
return []() { return true; };
}
// qDebug() << "RESIZING CLIP: " << clipId << " FROM: " << delta<<", ON PLAYLIST: "<<target_track;
if (delta > 0) { // we shrink clip
return [right, target_clip, target_track, clip_position, delta, in, out, clipId, update_snaps, this]() {
if (isLocked()) return false;
......@@ -686,10 +685,19 @@ Fun TrackModel::requestClipResize_lambda(int clipId, int in, int out, bool right
};
}
int blank = -1;
int other_blank_end = getBlankEnd(clip_position, 1 - target_track);
int startPos = clip_position;
if (hasMix) {
startPos += m_allClips[clipId]->getMixCutPosition();
}
int endPos = m_allClips[clipId]->getPosition() + out;
int other_blank_end = getBlankEnd(startPos, 1 - target_track);
if (right) {
if (target_clip == m_playlists[target_track].count() - 1 && (hasMix || other_blank_end >= out)) {
if (target_clip == m_playlists[target_track].count() - 1 && (hasMix || other_blank_end >= endPos)) {
// clip is last, it can always be extended
if (hasMix && other_blank_end < endPos && !hasEndMix(clipId)) {
// If clip has a start mix only, limit to next clip on other track
return []() { return false; };
}
return [this, target_clip, target_track, in, out, update_snaps, clipId]() {
if (isLocked()) return false;
// color, image and title clips can have unlimited resize
......
......@@ -158,6 +158,7 @@ protected:
@param in is the new starting on the clip
@param out is the new ending on the clip
@param right is true if we change the right side of the clip, false otherwise
@param hasMix is true if we change the right side of the clip, false otherwise
*/
Fun requestClipResize_lambda(int clipId, int in, int out, bool right, bool hasMix = false);
......
......@@ -410,6 +410,7 @@ Rectangle {
drag.axis: Drag.XAxis
drag.smoothed: false
drag.maximumX: clipRoot.width - 1
drag.minimumX: (clipRoot.mixDuration - clipRoot.mixCut) * clipRoot.timeScale
property bool sizeChanged: false
cursorShape: (containsMouse ? Qt.SizeHorCursor : Qt.ClosedHandCursor)
onPressed: {
......@@ -585,6 +586,9 @@ Rectangle {
var currentClipPos = clipRoot.modelStart
var delta = currentFrame - currentClipPos
if (delta !== 0) {
if (delta > 0 && (clipRoot.mixDuration - clipRoot.mixCut - delta < 0)) {
return
}
var newDuration = 0;
if (root.activeTool === ProjectTool.RippleTool) {
newDuration = clipRoot.originalDuration - delta
......
......@@ -3579,9 +3579,10 @@ void TimelineController::editItemDuration(int id)
result = m_model->requestCompositionMove(id, trackId, m_model->m_allCompositions[id]->getForcedTrack(), newPos, true, true, undo, redo);
}
if (result && newIn != in) {
m_model->requestItemResize(id, duration + (in - newIn), false, true, undo, redo);
int updatedDuration = duration + (in - newIn);
m_model->requestItemResize(id, updatedDuration, false, true, undo, redo);
if (result && partner > -1) {
result = m_model->requestItemResize(partner, duration + (in - newIn), false, true, undo, redo);
result = m_model->requestItemResize(partner, updatedDuration, false, true, undo, redo);
}
}
if (newDuration != duration + (in - newIn)) {
......@@ -3593,9 +3594,10 @@ void TimelineController::editItemDuration(int id)
} else {
// perform resize first
if (newIn != in) {
result = m_model->requestItemResize(id, duration + (in - newIn), false, true, undo, redo);
int updatedDuration = duration + (in - newIn);
result = m_model->requestItemResize(id, updatedDuration, false, true, undo, redo);
if (result && partner > -1) {
result = m_model->requestItemResize(partner, duration + (in - newIn), false, true, undo, redo);
result = m_model->requestItemResize(partner, updatedDuration, false, true, undo, redo);
}
}
if (newDuration != duration + (in - newIn)) {
......
......@@ -46,9 +46,9 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
int tid4 = TrackModel::construct(timeline);
// Create clip with audio
QString binId = createProducerWithSound(profile_mix, binModel, 50);
QString binId = createProducerWithSound(profile_mix, binModel, 100);
// Create clip with audio
// Create video clip
QString binId2 = createProducer(profile_mix, "red", binModel, 50, false);
// Setup insert stream data
QMap <int, QString>audioInfo;
......@@ -317,6 +317,21 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 0);
undoStack->undo();
state2();
// Resize right clip before left clip, should limit the resize to left clip position
REQUIRE(timeline->requestItemResize(cid4, 50, false, true) == 40);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
undoStack->undo();
state2();
// Resize left clip past right clip, should limit the resize to left clip position
REQUIRE(timeline->requestItemResize(cid3, 100, true, true) == 40);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid3]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid4]->getSubPlaylistIndex() == 1);
undoStack->undo();
state2();
undoStack->undo();
state0();
}
......@@ -327,7 +342,8 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
// CID 1 length=10, pos=100, CID2 length=10, pos=110
REQUIRE(timeline->m_allClips[cid1]->getPlaytime() == 10);
REQUIRE(timeline->m_allClips[cid2]->getPlaytime() == 10);
REQUIRE(timeline->requestItemResize(cid2, 50, true, true) == 50);
// Resize clip in to have some space for mix
REQUIRE(timeline->requestItemResize(cid2, 90, true, true) == 90);
REQUIRE(timeline->requestItemResize(cid2, 30, false, true) == 30);
REQUIRE(timeline->requestClipMove(cid2, tid2, 130));
REQUIRE(timeline->requestItemResize(cid1, 30, true, true) == 30);
......@@ -368,6 +384,23 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 0);
undoStack->undo();
state3();
// Resize right clip before left clip, should limit to left clip position
REQUIRE(timeline->requestItemResize(cid2, 80, false, true) == 60);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
undoStack->undo();
state3();
// Resize left clip after right clip, should limit to right clip duration
REQUIRE(timeline->requestItemResize(cid1, 80, true, true) == 60);
REQUIRE(timeline->getTrackById_const(tid2)->mixCount() == 1);
REQUIRE(timeline->getTrackById_const(tid3)->mixCount() == 1);
REQUIRE(timeline->m_allClips[cid1]->getSubPlaylistIndex() == 0);
REQUIRE(timeline->m_allClips[cid2]->getSubPlaylistIndex() == 1);
undoStack->undo();
state3();
undoStack->undo();
undoStack->undo();
undoStack->undo();
undoStack->undo();
......
......@@ -1653,7 +1653,8 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
REQUIRE(timeline->requestItemResize(cid6, l - 5, true, true, undo, redo, false));
int size = l - 5;
REQUIRE(timeline->requestItemResize(cid6, size, true, true, undo, redo, false));
pCore->pushUndo(undo, redo, QString());
}
auto state2 = [&]() {
......@@ -1682,7 +1683,8 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
REQUIRE(timeline->requestItemResize(cid6, l - 6, false, true, undo, redo, false));
int size = l - 6;
REQUIRE(timeline->requestItemResize(cid6, size, false, true, undo, redo, false));
pCore->pushUndo(undo, redo, QString());
}
auto state4 = [&]() {
......
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