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

Fix incorrect collision detection with clip having mixes

parent 9d8ec7e7
......@@ -375,6 +375,7 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
int cid = -1;
if (pCore->bin()->getBinClip(binId)) {
PlaylistState::ClipState st = inferState(clip, audioTrack);
bool enforceTopPlaylist = false;
if (playlist > 0) {
// Clips on playlist > 0 must have a mix or something is wrong
bool hasStartMix = !timeline->trackIsBlankAt(tid, position, 0);
......@@ -451,9 +452,19 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
m_notesLog << i18n("%1 Clip (%2) with missing mix found and removed", tcInfo, clip->parent().get("id"));
continue;
}
} else {
// Check if playlist 0 is available
enforceTopPlaylist = timeline->trackIsAvailable(tid, position, duration, 0);
if (enforceTopPlaylist) {
m_errorMessage << i18n("Clip %1 on incorrect subtrack found and fixed on track %2 at %3.", clip->parent().get("id"), timeline->getTrackTagById(tid), position);
} else {
m_errorMessage << i18n("Clip %1 on incorrect subtrack found on track %2 at %3.", clip->parent().get("id"), timeline->getTrackTagById(tid), position);
QString tcInfo = QString("<a href=\"%1?%2\">%3 %4</a>").arg(QString::number(position), QString::number(timeline->getTrackPosition(tid)+1), timeline->getTrackTagById(tid), pCore->timecode().getTimecodeFromFrames(position));
m_notesLog << i18n("%1 Clip (%2) with incorrect subplaylist found", tcInfo, clip->parent().get("id"));
}
}
}
cid = ClipModel::construct(timeline, binId, clip, st, tid, originalDecimalPoint, playlist);
cid = ClipModel::construct(timeline, binId, clip, st, tid, originalDecimalPoint, enforceTopPlaylist ? 0 : playlist);
ok = timeline->requestClipMove(cid, tid, position, true, true, false, true, undo, redo);
} else {
qWarning() << "can't find bin clip" << binId << clip->get("id");
......
......@@ -679,6 +679,20 @@ bool TimelineModel::requestClipMove(int clipId, int trackId, int position, bool
}
}
bool hadMix = mixData.first.firstClipId > -1 || mixData.second.secondClipId > -1;
if (!finalMove) {
QVector <int>exceptions = {clipId};
if (mixData.first.firstClipId > -1) {
exceptions << mixData.first.firstClipId;
}
if (mixData.second.secondClipId > -1) {
exceptions << mixData.second.secondClipId;
}
if (!getTrackById_const(trackId)->isAvailableWithExceptions(position, getClipPlaytime(clipId), exceptions)) {
// No space for clip insert operation, abort
qWarning() << "No free space for clip move";
return false;
}
}
if (old_trackId == -1 && isTrack(previous_track) && hadMix && previous_track != trackId) {
// Clip is moved to another track
bool mixGroupMove = false;
......@@ -766,7 +780,7 @@ bool TimelineModel::requestClipMove(int clipId, int trackId, int position, bool
}
}
} else if (finalMove && groupMove && isTrack(old_trackId) && hadMix && old_trackId == trackId) {
// Group move on same track with mix
if (mixData.first.firstClipId > -1) {
// Mix on clip start, check if mix is still in range
if (!moving_clips.contains(mixData.first.firstClipId)) {
......@@ -2938,6 +2952,11 @@ bool TimelineModel::trackIsBlankAt(int tid, int pos, int playlist) const
return getTrackById_const(tid)->isBlankAt(pos, playlist);
}
bool TimelineModel::trackIsAvailable(int tid, int pos, int duration, int playlist) const
{
return getTrackById_const(tid)->isAvailable(pos, duration, playlist);
}
int TimelineModel::getClipStartAt(int tid, int pos, int playlist) const
{
return getTrackById_const(tid)->getClipStart(pos, playlist);
......
......@@ -757,6 +757,8 @@ public:
const QString getTrackTagById(int trackId) const;
/** @brief returns true if track is empty at position on playlist */
bool trackIsBlankAt(int tid, int pos, int playlist) const;
/** @brief returns true if track is empty at position on playlist */
bool trackIsAvailable(int tid, int pos, int duration, int playlist) const;
/** @brief returns the position of the clip start on a playlist */
int getClipStartAt(int tid, int pos, int playlist) const;
int getClipEndAt(int tid, int pos, int playlist) const;
......
......@@ -1573,6 +1573,28 @@ bool TrackModel::isAvailable(int position, int duration, int playlist)
return m_playlists[playlist].is_blank(start_clip);
}
bool TrackModel::isAvailableWithExceptions(int position, int duration, QVector<int>exceptions)
{
// Check on both playlists
QSharedPointer<Mlt::Producer> prod = nullptr;
for (auto &playlist : m_playlists) {
int start_clip = playlist.get_clip_index_at(position);
int end_clip = playlist.get_clip_index_at(position + duration - 1);
for (int ix = start_clip; ix <= end_clip; ix++) {
if (playlist.is_blank(ix)) {
continue;
}
prod.reset(playlist.get_clip(ix));
if (prod) {
if (!exceptions.contains(prod->get_int("_kdenlive_cid"))) {
return false;
}
}
}
}
return true;
}
bool TrackModel::requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &redo)
{
int mixDuration;
......
......@@ -309,6 +309,8 @@ protected:
bool copyEffect(const std::shared_ptr<EffectStackModel> &stackModel, int rowId);
/** @brief Returns true if we have a blank at position for duration */
bool isAvailable(int position, int duration, int playlist);
/** @brief Returns true if we have a blank at position for duration, with the exception of clip ids exception */
bool isAvailableWithExceptions(int position, int duration, QVector<int>exceptions);
/** @brief Returns the number of same track transitions (mix) in this track */
int mixCount() const;
/** @brief Returns true if the track has a same track transition for this clip (cid) */
......
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