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

Fix various mix resize/align issues

parent 783204cc
......@@ -172,16 +172,23 @@ void AssetPanel::showTransition(int tid, const std::shared_ptr<AssetParameterMod
m_transitionWidget->setModel(transitionModel, s, true);
}
void AssetPanel::showMix(int cid, const std::shared_ptr<AssetParameterModel> &transitionModel)
void AssetPanel::showMix(int cid, const std::shared_ptr<AssetParameterModel> &transitionModel, bool refreshOnly)
{
if (cid == -1) {
clear();
return;
}
ObjectId id = {ObjectType::TimelineMix, cid};
if (m_mixWidget->stackOwner() == id) {
// already on this effect stack, do nothing
return;
if (refreshOnly) {
if (m_mixWidget->stackOwner() != id) {
// item not currently displayed, ignore
return;
}
} else {
if (m_mixWidget->stackOwner() == id) {
// already on this effect stack, do nothing
return;
}
}
clear();
// There is only 1 audio composition, so hide switch combobox
......
......@@ -60,7 +60,7 @@ public:
/** @brief Shows the parameters of the given transition model */
void showTransition(int tid, const std::shared_ptr<AssetParameterModel> &transition_model);
/** @brief Shows the parameters of the given mix model */
void showMix(int cid, const std::shared_ptr<AssetParameterModel> &transitionModel);
void showMix(int cid, const std::shared_ptr<AssetParameterModel> &transitionModel, bool refreshOnly);
/** @brief Shows the parameters of the given effect stack model */
void showEffectStack(const QString &itemName, const std::shared_ptr<EffectStackModel> &effectsModel, QSize frameSize, bool showKeyframes);
......
......@@ -151,9 +151,7 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
continue;
}
QString id(t.get("kdenlive_id"));
QString internal(t.get("internal_added"));
QString isMix(t.get("kdenlive:mixcut"));
if (internal.isEmpty() && isMix.isEmpty()) {
if (t.property_exists("internal_added") == false && t.property_exists("kdenlive:mixcut") == false) {
compositions << new Mlt::Transition(t);
if (id.isEmpty()) {
qWarning() << "transition without id" << t.get("id") << t.get("mlt_service") << "on track" << t.get_b_track();
......
......@@ -5452,20 +5452,53 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
if (clipToResize > -1) {
Fun undo = []() { return true; };
Fun redo = []() { return true; };
int cutPos = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getMixDuration() - m_allClips.at(cid)->getMixCutPosition();
// The mix cut position shoud never change through a resize operation
int cutPos = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime() - m_allClips.at(cid)->getMixCutPosition();
int maxLengthLeft = m_allClips.at(clipToResize)->getMaxDuration();
int leftMax = maxLengthLeft > -1 ? (maxLengthLeft - 1 - m_allClips.at(clipToResize)->getOut()) : -1;
int maxLengthRight = m_allClips.at(cid)->getMaxDuration();
int rightMax = maxLengthRight > -1 ? (m_allClips.at(cid)->getIn()) : -1;
Fun adjust_mix_undo = [this, tid, cid, prevCut = m_allClips.at(cid)->getMixCutPosition(), prevDuration = m_allClips.at(cid)->getMixDuration()]() {
getTrackById_const(tid)->setMixDuration(cid, prevDuration, prevCut);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
getTrackById_const(tid)->setMixDuration(cid, prevDuration, prevCut);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
if (align == MixAlignment::AlignLeft) {
int updatedDuration = cutPos + duration - m_allClips.at(clipToResize)->getPosition();
int result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos;
result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, duration);
// Adjust left clip
int updatedDurationLeft = cutPos + duration - m_allClips.at(clipToResize)->getPosition();
if (leftMax > -1) {
updatedDurationLeft = qMin(updatedDurationLeft, m_allClips.at(clipToResize)->getPlaytime() + leftMax);
}
// Adjust right clip
int updatedDurationRight = m_allClips.at(cid)->getPlaytime();
if (cutPos != m_allClips.at(cid)->getPosition()) {
updatedDurationRight = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos;
if (rightMax > -1) {
updatedDurationRight = qMin(updatedDurationRight, m_allClips.at(cid)->getPlaytime() + rightMax);
}
}
int updatedDuration = m_allClips.at(clipToResize)->getPosition() + updatedDurationLeft - (m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - updatedDurationRight);
if (updatedDuration < 2) {
//
pCore->displayMessage(i18n("Cannot resize mix to less than 2 frames"), ErrorMessage, 500);
// update mix widget
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
requestItemResize(clipToResize, updatedDurationLeft, true, true, undo, redo);
if (m_allClips.at(cid)->getPlaytime() != updatedDurationRight) {
requestItemResize(cid, updatedDurationRight, false, true, undo, redo);
}
int updatedCutPosition = m_allClips.at(cid)->getPosition();
if (updatedCutPosition != cutPos) {
pCore->displayMessage(i18n("Cannot resize mix"), ErrorMessage, 500);
undo();
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
Fun adjust_mix = [this, tid, cid, updatedDuration, duration]() {
getTrackById_const(tid)->setMixDuration(cid, updatedDuration, updatedDuration);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
......@@ -5473,12 +5506,32 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else if (align == MixAlignment::AlignRight) {
int updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration;
int result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
updatedDuration = cutPos - m_allClips.at(clipToResize)->getPosition();
result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, 0);
int updatedDurationRight = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration;
if (rightMax > -1) {
updatedDurationRight = qMin(updatedDurationRight, m_allClips.at(cid)->getPlaytime() + rightMax);
}
int updatedDurationLeft = cutPos - m_allClips.at(clipToResize)->getPosition();
if (leftMax > -1) {
updatedDurationLeft = qMin(updatedDurationLeft, m_allClips.at(clipToResize)->getPlaytime() + leftMax);
}
int updatedDuration = m_allClips.at(clipToResize)->getPosition() + updatedDurationLeft - (m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - updatedDurationRight);
if (updatedDuration < 2) {
//
pCore->displayMessage(i18n("Cannot resize mix to less than 2 frames"), ErrorMessage, 500);
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
requestItemResize(cid, updatedDurationRight, false, true, undo, redo);
requestItemResize(clipToResize, updatedDurationLeft, true, true, undo, redo);
int updatedCutPosition = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime();
if (updatedCutPosition != cutPos) {
pCore->displayMessage(i18n("Cannot resize mix"), ErrorMessage, 500);
undo();
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
Fun adjust_mix = [this, tid, cid, updatedDuration]() {
getTrackById_const(tid)->setMixDuration(cid, updatedDuration, 0);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
......@@ -5486,12 +5539,43 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else if (align == MixAlignment::AlignCenter) {
int updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration / 2;
int result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
updatedDuration = cutPos + (duration - duration / 2) - m_allClips.at(clipToResize)->getPosition();
result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, (duration - duration / 2));
int updatedDurationRight = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration / 2;
if (rightMax > -1) {
updatedDurationRight = qMin(updatedDurationRight, m_allClips.at(cid)->getPlaytime() + rightMax);
}
int updatedDurationLeft = cutPos + (duration - duration / 2) - m_allClips.at(clipToResize)->getPosition();
if (leftMax > -1) {
updatedDurationLeft = qMin(updatedDurationLeft, m_allClips.at(clipToResize)->getPlaytime() + leftMax);
}
int updatedDuration = m_allClips.at(clipToResize)->getPosition() + updatedDurationLeft - (m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - updatedDurationRight);
if (updatedDuration < 2) {
pCore->displayMessage(i18n("Cannot resize mix to less than 2 frames"), ErrorMessage, 500);
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
int deltaLeft = m_allClips.at(clipToResize)->getPosition() + updatedDurationLeft - cutPos;
int deltaRight = cutPos - (m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - updatedDurationRight);
if (deltaLeft < 2 || deltaRight < 2) {
pCore->displayMessage(i18n("Cannot align mix"), ErrorMessage, 500);
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
requestItemResize(cid, updatedDurationRight, false, true, undo, redo);
requestItemResize(clipToResize, updatedDurationLeft, true, true, undo, redo);
int mixCutPos = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime() - cutPos;
if (mixCutPos > updatedDuration) {
pCore->displayMessage(i18n("Cannot resize mix"), ErrorMessage, 500);
undo();
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
if (qAbs(deltaLeft - deltaRight > 2)) {
// Mix not exactly centered
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
Fun adjust_mix = [this, tid, cid, updatedDuration, mixCutPos]() {
getTrackById_const(tid)->setMixDuration(cid, updatedDuration, mixCutPos);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
......@@ -5499,14 +5583,31 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else {
Fun adjust_mix = [this, tid, cid, duration, updatedCut = m_allClips.at(cid)->getPosition() + duration - cutPos]() {
getTrackById_const(tid)->setMixDuration(cid, duration, updatedCut);
int updatedDurationLeft = m_allClips.at(cid)->getPosition() + duration - m_allClips[clipToResize]->getPosition();
if (leftMax > -1) {
updatedDurationLeft = qMin(updatedDurationLeft, m_allClips.at(clipToResize)->getPlaytime() + leftMax);
}
int updatedDuration = m_allClips.at(clipToResize)->getPosition() + updatedDurationLeft - m_allClips.at(cid)->getPosition();
if (updatedDuration < 2) {
//
pCore->displayMessage(i18n("Cannot resize mix to less than 2 frames"), ErrorMessage, 500);
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
requestItemResize(clipToResize, updatedDurationLeft, true, true, undo, redo);
int mixCutPos = m_allClips.at(clipToResize)->getPosition() + m_allClips.at(clipToResize)->getPlaytime() - cutPos;
if (mixCutPos > updatedDuration) {
pCore->displayMessage(i18n("Cannot resize mix"), ErrorMessage, 500);
undo();
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
Fun adjust_mix = [this, tid, cid, updatedDuration, mixCutPos]() {
getTrackById_const(tid)->setMixDuration(cid, updatedDuration, mixCutPos);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
int updatedDuration = m_allClips.at(cid)->getPosition() + duration - m_allClips[clipToResize]->getPosition();
int result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
}
......
......@@ -855,7 +855,7 @@ signals:
/** @brief Signal sent whenever the selection changes */
void selectionChanged();
/** @brief Signal sent whenever the selected mix changes */
void selectedMixChanged(int cid, const std::shared_ptr<AssetParameterModel> &asset);
void selectedMixChanged(int cid, const std::shared_ptr<AssetParameterModel> &asset, bool refreshOnly = false);
/** @brief Signal when a track is deleted so we make sure we don't store its id */
void checkTrackDeletion(int tid);
/** @brief Emitted when a clip is deleted to check if it was not used in timeline qml */
......
......@@ -2305,6 +2305,14 @@ bool TrackModel::loadMix(Mlt::Transition *t)
return false;
}
}
// Ensure in/out points are in sync with the clips
int clipIn = m_allClips[cid2]->getPosition();
int clipOut = m_allClips[cid1]->getPosition() + m_allClips[cid1]->getPlaytime();
if (in != clipIn || out != clipOut) {
t->set_in_and_out(clipIn, clipOut);
in = clipIn;
out = clipOut;
}
QString assetId(t->get("kdenlive_id"));
if (assetId.isEmpty()) {
assetId = QString(t->get("mlt_service"));
......@@ -2330,7 +2338,9 @@ bool TrackModel::loadMix(Mlt::Transition *t)
std::shared_ptr<AssetParameterModel> asset(new AssetParameterModel(std::move(tr), xml, assetId, {ObjectType::TimelineMix, cid2}, QString()));
m_sameCompositions[cid2] = asset;
m_mixList.insert(cid1, cid2);
setMixDuration(cid2, t->get_length() - 1, t->get_int("kdenlive:mixcut"));
int mixDuration = t->get_length() - 1;
int mixCutPos = qMin(t->get_int("kdenlive:mixcut"), mixDuration);
setMixDuration(cid2, mixDuration, mixCutPos);
return true;
}
......
......@@ -751,7 +751,7 @@ signals:
/** @brief Requests that a given parameter model is displayed in the asset panel */
void showTransitionModel(int tid, std::shared_ptr<AssetParameterModel>);
/** @brief Requests that a given mix is displayed in the asset panel */
void showMixModel(int cid, const std::shared_ptr<AssetParameterModel> &asset);
void showMixModel(int cid, const std::shared_ptr<AssetParameterModel> &asset, bool refreshOnly);
void showItemEffectStack(const QString &clipName, std::shared_ptr<EffectStackModel>, QSize frameSize, bool showKeyframes);
void showSubtitle(int id);
/** @brief notify of chunks change
......
......@@ -85,7 +85,7 @@ signals:
/** @brief Requests that a given parameter model is displayed in the asset panel */
void showTransitionModel(int tid, std::shared_ptr<AssetParameterModel>);
/** @brief Requests that a given mix is displayed in the asset panel */
void showMixModel(int cid, std::shared_ptr<AssetParameterModel>);
void showMixModel(int cid, std::shared_ptr<AssetParameterModel>, bool refreshOnly);
/** @brief Requests that a given effectstack model is displayed in the asset panel */
void showItemEffectStack(const QString &clipName, std::shared_ptr<EffectStackModel>, QSize, bool);
void showSubtitle(int itemId);
......
......@@ -149,8 +149,7 @@ void MixStackView::slotAlignLeft()
}
m_alignRight->setChecked(false);
m_alignCenter->setChecked(false);
int newDuration = m_duration->getValue();
pCore->resizeMix(stackOwner().second, newDuration, MixAlignment::AlignLeft);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignLeft);
}
void MixStackView::slotAlignRight()
......@@ -160,8 +159,7 @@ void MixStackView::slotAlignRight()
}
m_alignLeft->setChecked(false);
m_alignCenter->setChecked(false);
int newDuration = m_duration->getValue();
pCore->resizeMix(stackOwner().second, newDuration, MixAlignment::AlignRight);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignRight);
}
void MixStackView::slotAlignCenter()
......@@ -171,8 +169,7 @@ void MixStackView::slotAlignCenter()
}
m_alignLeft->setChecked(false);
m_alignRight->setChecked(false);
int newDuration = m_duration->getValue();
pCore->resizeMix(stackOwner().second, newDuration, MixAlignment::AlignCenter);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignCenter);
}
void MixStackView::unsetModel()
......
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