diff --git a/src/engraving/dom/noteentry.cpp b/src/engraving/dom/noteentry.cpp index e3f14f763e167..20b5e34017563 100644 --- a/src/engraving/dom/noteentry.cpp +++ b/src/engraving/dom/noteentry.cpp @@ -450,6 +450,34 @@ Ret Score::putNote(const Position& p, bool replace) ChordRest* cr = m_is.cr(); + // If there's an overlapping ChordRest at the current input position, shorten it... + if (!cr) { + MasterScore* ms = masterScore(); + ChordRest* prevCr = m_is.segment()->nextChordRest(m_is.track(), /*backwards*/ true, /*stopAtMeasureBoundary*/ true); + if (prevCr && prevCr->endTick() > m_is.tick()) { + const Fraction overlapDuration = prevCr->endTick() - m_is.tick(); + const Fraction desiredDuration = prevCr->ticks() - overlapDuration; + + const InputState inputStateToRestore = m_is; // because changeCRlen will alter the input state + ms->changeCRlen(prevCr, desiredDuration, /*fillWithRest*/ false); + + // Fill the difference with tied notes if necessary... + const Fraction difference = desiredDuration - prevCr->ticks(); + if (prevCr->isChord() && difference.isNotZero()) { + Fraction startTick = prevCr->endTick(); + Chord* prevChord = nullptr; + const std::vector durationList = toDurationList(difference, true); + for (const TDuration& dur : durationList) { + Chord* tieFrom = prevChord ? prevChord : toChord(prevCr); + prevChord = ms->addChord(startTick, dur, tieFrom, /*genTie*/ bool(tieFrom), tieFrom->tuplet()); + startTick += dur.fraction(); + } + } + + m_is = inputStateToRestore; + } + } + auto checkTied = [&](){ if (!cr || !cr->isChord()) { return false; diff --git a/src/engraving/dom/segment.cpp b/src/engraving/dom/segment.cpp index 45b150802ceff..723f45630d5c4 100644 --- a/src/engraving/dom/segment.cpp +++ b/src/engraving/dom/segment.cpp @@ -585,15 +585,23 @@ Segment* Segment::nextCR(track_idx_t track, bool sameStaff) const // get the next ChordRest, start at this segment //--------------------------------------------------------- -ChordRest* Segment::nextChordRest(track_idx_t track, bool backwards) const +ChordRest* Segment::nextChordRest(track_idx_t track, bool backwards, bool stopAtMeasureBoundary) const { - for (const Segment* seg = this; seg; seg = backwards ? seg->prev1() : seg->next1()) { + const Segment* seg = this; + while (seg) { EngravingItem* el = seg->element(track); if (el && el->isChordRest()) { return toChordRest(el); } + + if (backwards) { + seg = stopAtMeasureBoundary ? seg->prev() : seg->prev1(); + continue; + } + + seg = stopAtMeasureBoundary ? seg->next() : seg->next1(); } - return 0; + return nullptr; } EngravingItem* Segment::element(track_idx_t track) const diff --git a/src/engraving/dom/segment.h b/src/engraving/dom/segment.h index ceb15329a5558..0d679055d7c87 100644 --- a/src/engraving/dom/segment.h +++ b/src/engraving/dom/segment.h @@ -138,7 +138,7 @@ class Segment final : public EngravingItem Segment* nextCR(track_idx_t track = muse::nidx, bool sameStaff = false) const; - ChordRest* nextChordRest(track_idx_t track, bool backwards = false) const; + ChordRest* nextChordRest(track_idx_t track, bool backwards = false, bool stopAtMeasureBoundary = false) const; EngravingItem* element(track_idx_t track) const;