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

Add a position widget to mix parameters to allow sliding the mix

Related to #796
parent 84a25d66
......@@ -1136,9 +1136,9 @@ void Core::testProxies()
dialog->exec();
}
void Core::resizeMix(int cid, int duration, MixAlignment align)
void Core::resizeMix(int cid, int duration, MixAlignment align, int leftFrames)
{
m_mainWindow->getCurrentTimeline()->controller()->resizeMix(cid, duration, align);
m_mainWindow->getCurrentTimeline()->controller()->resizeMix(cid, duration, align, leftFrames);
}
MixAlignment Core::getMixAlign(int cid) const
......@@ -1146,6 +1146,11 @@ MixAlignment Core::getMixAlign(int cid) const
return m_mainWindow->getCurrentTimeline()->controller()->getMixAlign(cid);
}
int Core::getMixCutPos(int cid) const
{
return m_mainWindow->getCurrentTimeline()->controller()->getMixCutPos(cid);
}
void Core::cleanup()
{
audioThumbCache.clear();
......
......@@ -255,7 +255,9 @@ public:
/** @brief The number of clip load jobs changed */
void loadingClips(int);
/** @brief Resize current mix item */
void resizeMix(int cid, int duration, MixAlignment align);
void resizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
/** @brief Get Mix cut pos (the duration of the mix on the right clip) */
int getMixCutPos(int cid) const;
/** @brief Get alignment info for a mix item */
MixAlignment getMixAlign(int cid) const;
/** @brief Closing current document, do some cleanup */
......
......@@ -5575,6 +5575,12 @@ std::pair<int, int> TimelineModel::getMixInOut(int cid) const
return {-1,-1};
}
int TimelineModel::getMixCutPos(int cid) const
{
Q_ASSERT(isClip(cid));
return m_allClips.at(cid)->getMixCutPosition();
}
MixAlignment TimelineModel::getMixAlign(int cid) const
{
Q_ASSERT(isClip(cid));
......@@ -5593,7 +5599,7 @@ MixAlignment TimelineModel::getMixAlign(int cid) const
return MixAlignment::AlignNone;
}
void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align, int leftFrames)
{
Q_ASSERT(isClip(cid));
int tid = m_allClips.at(cid)->getCurrentTrackId();
......@@ -5734,19 +5740,28 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else {
int updatedDurationRight = m_allClips.at(cid)->getMixCutPosition();
int updatedDurationLeft = m_allClips.at(cid)->getMixDuration() - updatedDurationRight;
int currentDuration = m_allClips.at(cid)->getMixDuration();
double ratio = double (duration) / currentDuration;
updatedDurationRight *= ratio;
updatedDurationLeft = duration - updatedDurationRight;
// No alignment specified
int updatedDurationRight;
int updatedDurationLeft;
if (leftFrames > -1) {
// A left frame offset was specified
updatedDurationLeft = qBound(0, leftFrames, duration);
updatedDurationRight = duration - updatedDurationLeft;
} else {
updatedDurationRight = m_allClips.at(cid)->getMixCutPosition();
updatedDurationLeft = m_allClips.at(cid)->getMixDuration() - updatedDurationRight;
int currentDuration = m_allClips.at(cid)->getMixDuration();
double ratio = double (duration) / currentDuration;
updatedDurationRight *= ratio;
updatedDurationLeft = duration - updatedDurationRight;
}
if (updatedDurationLeft + updatedDurationRight < 1) {
//
pCore->displayMessage(i18n("Cannot resize mix to less than 1 frame"), ErrorMessage, 500);
emit selectedMixChanged(cid, getTrackById_const(tid)->mixModel(cid), true);
return;
}
updatedDurationLeft -= (m_allClips.at(cid)->getMixDuration() - updatedDurationRight);
updatedDurationLeft -= (m_allClips.at(cid)->getMixDuration() - m_allClips.at(cid)->getMixCutPosition());
updatedDurationRight -= m_allClips.at(cid)->getMixCutPosition();
if (updatedDurationLeft != 0) {
requestItemResize(cid, m_allClips.at(cid)->getPlaytime() + updatedDurationLeft, false, true, undo, redo);
......
......@@ -749,7 +749,9 @@ public:
/** @brief Create a mix selection with currently selected clip. If delta = -1, mix with previous clip, +1 with next clip and 0 will check cursor position*/
bool mixClip(int idToMove = -1, int delta = 0);
Q_INVOKABLE bool resizeStartMix(int cid, int duration, bool singleResize);
void requestResizeMix(int cid, int duration, MixAlignment align);
void requestResizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
/** @brief Get Mix cut pos (the duration of the mix on the right clip) */
int getMixCutPos(int cid) const;
MixAlignment getMixAlign(int cid) const;
std::shared_ptr<SubtitleModel> getSubtitleModel();
/** @brief Get the frame size of the clip above a composition */
......
......@@ -4677,13 +4677,18 @@ int TimelineController::clipMaxDuration(int cid)
return m_model->m_allClips[cid]->getMaxDuration();
}
void TimelineController::resizeMix(int cid, int duration, MixAlignment align)
void TimelineController::resizeMix(int cid, int duration, MixAlignment align, int leftFrames)
{
if (cid > -1) {
m_model->requestResizeMix(cid, duration, align);
m_model->requestResizeMix(cid, duration, align, leftFrames);
}
}
int TimelineController::getMixCutPos(int cid) const
{
return m_model->getMixCutPos(cid);
}
MixAlignment TimelineController::getMixAlign(int cid) const
{
return m_model->getMixAlign(cid);
......
......@@ -638,6 +638,8 @@ public:
void updateMasterZones(QVariantList zones);
/** @brief get Maximum duration of a clip */
int clipMaxDuration(int cid);
/** @brief Get Mix cut pos (the duration of the mix on the right clip) */
int getMixCutPos(int cid) const;
/** @brief Get align info for a mix. */
MixAlignment getMixAlign(int cid) const;
/** @brief Process a lift operation for multitrack operation. */
......@@ -665,7 +667,7 @@ public slots:
/** @brief Restore timeline scroll pos on open. */
void setScrollPos(int pos);
/** @brief Request resizing currently selected mix. */
void resizeMix(int cid, int duration, MixAlignment align);
void resizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
/** @brief change zone info with undo. */
Q_INVOKABLE void updateZone(const QPoint oldZone, const QPoint newZone, bool withUndo = true);
Q_INVOKABLE void updateEffectZone(const QPoint oldZone, const QPoint newZone, bool withUndo = true);
......
......@@ -21,6 +21,14 @@
MixStackView::MixStackView(QWidget *parent)
: AssetParameterView(parent)
{
// Position widget
m_positionLayout = new QHBoxLayout;
m_position = new TimecodeDisplay(pCore->timecode(), this);
m_position->setRange(0, -1);
m_positionLayout->addWidget(new QLabel(i18n("Position (left):")));
m_positionLayout->addWidget(m_position);
m_positionLayout->addStretch();
// Duration widget
m_durationLayout = new QHBoxLayout;
m_duration = new TimecodeDisplay(pCore->timecode(), this);
m_duration->setRange(1, -1);
......@@ -49,6 +57,7 @@ MixStackView::MixStackView(QWidget *parent)
m_durationLayout->addWidget(m_alignCenter);
m_durationLayout->addWidget(m_alignLeft);
connect(m_duration, &TimecodeDisplay::timeCodeUpdated, this, &MixStackView::updateDuration);
connect(m_position, &TimecodeDisplay::timeCodeUpdated, this, &MixStackView::updatePosition);
connect(this, &AssetParameterView::seekToPos, [this](int pos) {
// at this point, the effects returns a pos relative to the clip. We need to convert it to a global time
int clipIn = pCore->getItemPosition(m_model->getOwnerId());
......@@ -68,21 +77,24 @@ void MixStackView::setModel(const std::shared_ptr<AssetParameterModel> &model, Q
pCore->getMonitor(m_model->monitorId)->slotShowEffectScene(needsMonitorEffectScene());
if (m_model->rowCount() > 0) {
QSignalBlocker bk0(m_duration);
m_duration->setValue(m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt() + 1);
const QSignalBlocker bk0(m_duration);
const QSignalBlocker bk1(m_position);
int duration = m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt();
m_duration->setValue(duration);
m_position->setValue(duration - pCore->getMixCutPos(stackOwner().second));
connect(m_model.get(), &AssetParameterModel::dataChanged, this, &MixStackView::durationChanged);
}
checkAlignment();
m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt();
// The layout is handled by AssetParameterView, so we can only add our custom stuff later here
m_lay->addLayout(m_durationLayout);
m_lay->addLayout(m_positionLayout);
m_lay->addStretch(10);
checkAlignment();
slotRefresh();
}
void MixStackView::checkAlignment()
{
int mainClipId = stackOwner().second;
MixAlignment align = pCore->getMixAlign(mainClipId);
MixAlignment align = pCore->getMixAlign(stackOwner().second);
QSignalBlocker bk1(m_alignLeft);
QSignalBlocker bk2(m_alignRight);
QSignalBlocker bk3(m_alignCenter);
......@@ -110,7 +122,11 @@ void MixStackView::durationChanged(const QModelIndex &, const QModelIndex &, con
{
if (roles.contains(AssetParameterModel::ParentDurationRole)) {
QSignalBlocker bk1(m_duration);
m_duration->setValue(m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt() + 1);
QSignalBlocker bk2(m_position);
int duration = m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt();
m_duration->setValue(duration);
m_position->setRange(0, duration);
m_position->setValue(duration - pCore->getMixCutPos(stackOwner().second));
checkAlignment();
}
}
......@@ -131,7 +147,12 @@ MixAlignment MixStackView::alignment() const
void MixStackView::updateDuration()
{
pCore->resizeMix(stackOwner().second, m_duration->getValue() - 1, alignment());
pCore->resizeMix(stackOwner().second, m_duration->getValue(), alignment());
}
void MixStackView::updatePosition()
{
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignNone, m_position->getValue());
}
void MixStackView::slotAlignLeft()
......@@ -141,7 +162,7 @@ void MixStackView::slotAlignLeft()
}
m_alignRight->setChecked(false);
m_alignCenter->setChecked(false);
pCore->resizeMix(stackOwner().second, m_duration->getValue() - 1, MixAlignment::AlignLeft);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignLeft);
}
void MixStackView::slotAlignRight()
......@@ -151,7 +172,7 @@ void MixStackView::slotAlignRight()
}
m_alignLeft->setChecked(false);
m_alignCenter->setChecked(false);
pCore->resizeMix(stackOwner().second, m_duration->getValue() - 1, MixAlignment::AlignRight);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignRight);
}
void MixStackView::slotAlignCenter()
......@@ -161,7 +182,7 @@ void MixStackView::slotAlignCenter()
}
m_alignLeft->setChecked(false);
m_alignRight->setChecked(false);
pCore->resizeMix(stackOwner().second, m_duration->getValue() - 1, MixAlignment::AlignCenter);
pCore->resizeMix(stackOwner().second, m_duration->getValue(), MixAlignment::AlignCenter);
}
void MixStackView::unsetModel()
......@@ -169,6 +190,7 @@ void MixStackView::unsetModel()
if (m_model) {
m_model->setActive(false);
m_lay->removeItem(m_durationLayout);
m_lay->removeItem(m_positionLayout);
auto kfr = m_model->getKeyframeModel();
if (kfr) {
disconnect(kfr.get(), &KeyframeModelList::modelChanged, this, &AssetParameterView::slotRefresh);
......
......@@ -30,11 +30,14 @@ signals:
private slots:
void durationChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &roles);
void updateDuration();
void updatePosition();
void slotAlignLeft();
void slotAlignRight();
void slotAlignCenter();
private:
QHBoxLayout *m_positionLayout;
TimecodeDisplay *m_position;
QHBoxLayout *m_durationLayout;
TimecodeDisplay *m_duration;
QToolButton *m_alignLeft;
......
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