diff --git a/src/engraving/dom/gradualtempochange.cpp b/src/engraving/dom/gradualtempochange.cpp index 0d8c7c15652ed..68669036254da 100644 --- a/src/engraving/dom/gradualtempochange.cpp +++ b/src/engraving/dom/gradualtempochange.cpp @@ -359,6 +359,7 @@ TempoText* GradualTempoChangeSegment::findElementToSnapAfter() const // It is the next tempoChange which looks for a tempoChange before. Fraction refTick = tempoChange()->tick2(); Measure* measure = score()->tick2measure(refTick); + measure = style().styleB(Sid::createMultiMeasureRests) && measure->hasMMRest() ? measure->mmRest() : measure; if (!measure) { return nullptr; } diff --git a/src/engraving/rendering/dev/beamlayout.cpp b/src/engraving/rendering/dev/beamlayout.cpp index 31efb23dccad8..90c68cf85b56b 100644 --- a/src/engraving/rendering/dev/beamlayout.cpp +++ b/src/engraving/rendering/dev/beamlayout.cpp @@ -644,8 +644,6 @@ void BeamLayout::beamGraceNotes(LayoutContext& ctx, Chord* mainNote, bool after) void BeamLayout::createBeams(LayoutContext& ctx, Measure* measure) { - bool crossMeasure = ctx.conf().styleB(Sid::crossMeasureValues); - for (track_idx_t track = 0; track < ctx.dom().ntracks(); ++track) { const Staff* stf = ctx.dom().staff(track2staff(track)); @@ -738,17 +736,12 @@ void BeamLayout::createBeams(LayoutContext& ctx, Measure* measure) cr->removeDeleteBeam(false); } - // handle grace notes and cross-measure beaming + // handle grace notes // (tied chords?) if (cr->isChord()) { Chord* chord = toChord(cr); beamGraceNotes(ctx, chord, false); // grace before beamGraceNotes(ctx, chord, true); // grace after - // set up for cross-measure values as soon as possible - // to have all computations (stems, hooks, ...) consistent with it - if (!chord->isGrace()) { - ChordLayout::crossMeasureSetup(chord, crossMeasure, ctx); - } } if (cr->isRest() && cr->beamMode() == BeamMode::AUTO) { diff --git a/src/engraving/rendering/dev/lyricslayout.cpp b/src/engraving/rendering/dev/lyricslayout.cpp index 63627ab667e28..91518d0ec3988 100644 --- a/src/engraving/rendering/dev/lyricslayout.cpp +++ b/src/engraving/rendering/dev/lyricslayout.cpp @@ -451,8 +451,18 @@ void LyricsLayout::createOrRemoveLyricsLine(Lyrics* item, LayoutContext& ctx) EngravingItem* endSegmentElement = endSegment->element(track); if (endSegment->tick() == endTick && endSegmentElement && endSegmentElement->type() == ElementType::CHORD) { // everything is OK if we have reached a chord at right tick on right track - // advance to next CR, or last segment if no next CR - endSegment = endSegment->nextCR(track, false); + // advance to next CR after duration of note, or last segment if no next CR + const Segment* endChordSeg = endSegment; + const Chord* endChord = toChord(endSegmentElement); + + endSegment = endChordSeg->nextCR(track, false); + + if (!endSegment) { + endSegment = endChordSeg; + while (endSegment && endSegment->tick() < endChord->tick() + endChord->ticks()) { + endSegment = endSegment->nextCR(muse::nidx, true); + } + } } else { // FIXUP - lyrics tick count not valid // this happens if edits to score have removed the original end segment @@ -609,18 +619,17 @@ void LyricsLayout::setDefaultPositions(staff_idx_t staffIdx, const LyricsVersesM double staffHeight = ctx.dom().staff(staffIdx)->staffHeight(); double lyricsLineHeightFactor = ctx.conf().styleD(Sid::lyricsLineHeight); - int totVersesAbove = int(lyricsVersesAbove.size()) - 1; - + int maxVerseAbove = !lyricsVersesAbove.empty() ? lyricsVersesAbove.crbegin()->first : 0; for (auto& pair : lyricsVersesAbove) { int verse = pair.first; const LyricsVerse& lyricsVerse = pair.second; for (Lyrics* lyrics : lyricsVerse.lyrics()) { - double y = -(totVersesAbove - verse) * lyrics->lineSpacing() * lyricsLineHeightFactor; + double y = -(maxVerseAbove - verse) * lyrics->lineSpacing() * lyricsLineHeightFactor; lyrics->setYRelativeToStaff(y); } for (LyricsLineSegment* lyricsLineSegment : lyricsVerse.lines()) { Lyrics* lyrics = lyricsLineSegment->lyricsLine()->lyrics(); - double y = -(totVersesAbove - verse) * lyrics->lineSpacing() * lyricsLineHeightFactor; + double y = -(maxVerseAbove - verse) * lyrics->lineSpacing() * lyricsLineHeightFactor; lyricsLineSegment->move(PointF(0.0, y + lyricsLineSegment->baseLineShift())); } } @@ -651,10 +660,13 @@ void LyricsLayout::checkCollisionsWithStaffElements(System* system, staff_idx_t SkylineLine& staffSkylineNorth = systemStaff->skyline().north(); SkylineLine& staffSkylineSouth = systemStaff->skyline().south(); - int maxVerseAbove = int(lyricsVersesAbove.size()); - int maxVerseBelow = int(lyricsVersesBelow.size()); + int maxVerseAbove = !lyricsVersesAbove.empty() ? lyricsVersesAbove.crbegin()->first : 0; + int maxVerseBelow = !lyricsVersesBelow.empty() ? lyricsVersesBelow.crbegin()->first : 0; - for (int verse = maxVerseAbove - 1; verse >= 0; --verse) { + for (int verse = maxVerseAbove; verse >= 0; --verse) { + if (lyricsVersesAbove.count(verse) == 0) { + continue; + } SkylineLine verseSkyline = createSkylineForVerse(verse, false, lyricsVersesAbove, system); double minDistance = -verseSkyline.minDistance(staffSkylineNorth); if (minDistance < lyricsMinDist) { @@ -663,7 +675,10 @@ void LyricsLayout::checkCollisionsWithStaffElements(System* system, staff_idx_t } } - for (int verse = 0; verse < maxVerseBelow; ++verse) { + for (int verse = 0; verse <= maxVerseBelow; ++verse) { + if (lyricsVersesBelow.count(verse) == 0) { + continue; + } SkylineLine verseSkyline = createSkylineForVerse(verse, true, lyricsVersesBelow, system); double minDistance = -staffSkylineSouth.minDistance(verseSkyline); if (minDistance < lyricsMinDist) { diff --git a/src/engraving/rendering/dev/measurelayout.cpp b/src/engraving/rendering/dev/measurelayout.cpp index 504bd326aab24..27837d71dca00 100644 --- a/src/engraving/rendering/dev/measurelayout.cpp +++ b/src/engraving/rendering/dev/measurelayout.cpp @@ -869,6 +869,7 @@ void MeasureLayout::layoutMeasure(MeasureBase* currentMB, LayoutContext& ctx) checkStaffMoveValidity(measure, ctx); // ---- Modify DOM ---- + ModifyDom::setCrossMeasure(measure, ctx); ModifyDom::connectTremolo(measure); ModifyDom::cmdUpdateNotes(measure, ctx.dom()); ModifyDom::createStems(measure, ctx); diff --git a/src/engraving/rendering/dev/modifydom.cpp b/src/engraving/rendering/dev/modifydom.cpp index b0578c3d020b1..495a2ee6016d1 100644 --- a/src/engraving/rendering/dev/modifydom.cpp +++ b/src/engraving/rendering/dev/modifydom.cpp @@ -32,9 +32,44 @@ #include "dom/keysig.h" #include "dom/hook.h" #include "dom/part.h" +#include "rendering/dev/chordlayout.h" using namespace mu::engraving::rendering::dev; +void ModifyDom::setCrossMeasure(const Measure* measure, LayoutContext& ctx) +{ + bool crossMeasure = ctx.conf().styleB(Sid::crossMeasureValues); + const DomAccessor& dom = ctx.dom(); + for (staff_idx_t staffIdx = 0; staffIdx < dom.nstaves(); ++staffIdx) { + const Staff* staff = dom.staff(staffIdx); + if (!staff->show()) { + continue; + } + + track_idx_t startTrack = staffIdx * VOICES; + track_idx_t endTrack = startTrack + VOICES; + + for (const Segment& segment : measure->segments()) { + if (!segment.isJustType(SegmentType::ChordRest)) { + continue; + } + + for (track_idx_t t = startTrack; t < endTrack; ++t) { + ChordRest* cr = segment.cr(t); + if (!cr) { + continue; + } + if (cr->isChord()) { + Chord* chord = toChord(cr); + if (!chord->isGrace()) { + ChordLayout::crossMeasureSetup(chord, crossMeasure, ctx); + } + } + } + } + } +} + void ModifyDom::connectTremolo(Measure* m) { m->connectTremolo(); diff --git a/src/engraving/rendering/dev/modifydom.h b/src/engraving/rendering/dev/modifydom.h index 3ebc20a67393c..3086f1b1582d9 100644 --- a/src/engraving/rendering/dev/modifydom.h +++ b/src/engraving/rendering/dev/modifydom.h @@ -36,6 +36,7 @@ class ModifyDom { public: + static void setCrossMeasure(const Measure* measure, LayoutContext& ctx); static void connectTremolo(Measure* m); static void cmdUpdateNotes(const Measure* measure, const DomAccessor& dom); static void createStems(const Measure* measure, LayoutContext& ctx); diff --git a/src/engraving/rendering/dev/systemlayout.cpp b/src/engraving/rendering/dev/systemlayout.cpp index a26c3cc41c335..db154b2b93611 100644 --- a/src/engraving/rendering/dev/systemlayout.cpp +++ b/src/engraving/rendering/dev/systemlayout.cpp @@ -1134,6 +1134,9 @@ void SystemLayout::layoutSystemElements(System* system, LayoutContext& ctx) if (!sp->systemFlag() && sp->staff() && !sp->staff()->show()) { continue; } + if (sp->systemFlag() && sp->staffIdxOrNextVisible() == muse::nidx) { + continue; + } if (sp->tick2() == stick && sp->isPedal() && toPedal(sp)->connect45HookToNext()) { pedal.push_back(sp); diff --git a/src/framework/global/serialization/xmlstreamreader.cpp b/src/framework/global/serialization/xmlstreamreader.cpp index dafb02b2a9029..092d630a67ef5 100644 --- a/src/framework/global/serialization/xmlstreamreader.cpp +++ b/src/framework/global/serialization/xmlstreamreader.cpp @@ -157,7 +157,7 @@ static std::pair resolveNode(XMLNode* curr } XMLNode* sibling = currentNode->NextSibling(); - if (!sibling || sibling->ToElement() || sibling->ToText()) { + if (!sibling || sibling->ToElement() || sibling->ToText() || sibling->ToComment()) { return { currentNode, XmlStreamReader::TokenType::EndElement }; } } diff --git a/src/notation/view/widgets/editstafftype.cpp b/src/notation/view/widgets/editstafftype.cpp index c7a7b3a307c17..3ee298b221924 100644 --- a/src/notation/view/widgets/editstafftype.cpp +++ b/src/notation/view/widgets/editstafftype.cpp @@ -442,30 +442,30 @@ void EditStaffType::setFromDlg() staffType.setShowLedgerLines(showLedgerLinesPercussion->isChecked()); staffType.setStemless(stemlessPercussion->isChecked()); } - staffType.setDurationFontName(durFontName->currentText()); - staffType.setDurationFontSize(durFontSize->value()); - staffType.setDurationFontUserY(durY->value()); - staffType.setFretFontName(fretFontName->currentText()); - staffType.setFretFontSize(fretFontSize->value()); - staffType.setFretFontUserY(fretY->value()); - staffType.setLinesThrough(linesThroughRadio->isChecked()); - staffType.setMinimStyle(minimNoneRadio->isChecked() ? mu::engraving::TablatureMinimStyle::NONE - : (minimShortRadio->isChecked() ? mu::engraving::TablatureMinimStyle::SHORTER : mu::engraving:: - TablatureMinimStyle:: - SLASHED)); - staffType.setSymbolRepeat(valuesRepeatNever->isChecked() ? mu::engraving::TablatureSymbolRepeat::NEVER - : (valuesRepeatSystem->isChecked() ? mu::engraving::TablatureSymbolRepeat::SYSTEM - : valuesRepeatMeasure->isChecked() ? mu::engraving::TablatureSymbolRepeat::MEASURE - : mu::engraving::TablatureSymbolRepeat::ALWAYS)); - staffType.setOnLines(onLinesRadio->isChecked()); - staffType.setShowRests(showRests->isChecked()); - staffType.setUpsideDown(upsideDown->isChecked()); - staffType.setShowTabFingering(showTabFingering->isChecked()); - staffType.setUseNumbers(numbersRadio->isChecked()); - //note values - staffType.setStemsDown(stemBelowRadio->isChecked()); - staffType.setStemsThrough(stemThroughRadio->isChecked()); if (staffType.group() == mu::engraving::StaffGroup::TAB) { + staffType.setDurationFontName(durFontName->currentText()); + staffType.setDurationFontSize(durFontSize->value()); + staffType.setDurationFontUserY(durY->value()); + staffType.setFretFontName(fretFontName->currentText()); + staffType.setFretFontSize(fretFontSize->value()); + staffType.setFretFontUserY(fretY->value()); + staffType.setLinesThrough(linesThroughRadio->isChecked()); + staffType.setMinimStyle(minimNoneRadio->isChecked() ? mu::engraving::TablatureMinimStyle::NONE + : (minimShortRadio->isChecked() ? mu::engraving::TablatureMinimStyle::SHORTER : mu::engraving:: + TablatureMinimStyle:: + SLASHED)); + staffType.setSymbolRepeat(valuesRepeatNever->isChecked() ? mu::engraving::TablatureSymbolRepeat::NEVER + : (valuesRepeatSystem->isChecked() ? mu::engraving::TablatureSymbolRepeat::SYSTEM + : valuesRepeatMeasure->isChecked() ? mu::engraving::TablatureSymbolRepeat::MEASURE + : mu::engraving::TablatureSymbolRepeat::ALWAYS)); + staffType.setOnLines(onLinesRadio->isChecked()); + staffType.setShowRests(showRests->isChecked()); + staffType.setUpsideDown(upsideDown->isChecked()); + staffType.setShowTabFingering(showTabFingering->isChecked()); + staffType.setUseNumbers(numbersRadio->isChecked()); + //note values + staffType.setStemsDown(stemBelowRadio->isChecked()); + staffType.setStemsThrough(stemThroughRadio->isChecked()); staffType.setGenKeysig(false); staffType.setStemless(true); // assume no note values staffType.setGenDurations(false); // " " diff --git a/vtest/scores/cross-measure-1.mscz b/vtest/scores/cross-measure-1.mscz new file mode 100644 index 0000000000000..daf2aab37e5d6 Binary files /dev/null and b/vtest/scores/cross-measure-1.mscz differ diff --git a/vtest/scores/lyrics-22.mscz b/vtest/scores/lyrics-22.mscz new file mode 100644 index 0000000000000..04b6d0007f7d0 Binary files /dev/null and b/vtest/scores/lyrics-22.mscz differ diff --git a/vtest/scores/lyrics-23.mscz b/vtest/scores/lyrics-23.mscz new file mode 100644 index 0000000000000..e88aed6db4253 Binary files /dev/null and b/vtest/scores/lyrics-23.mscz differ diff --git a/vtest/scores/mmrest-20.mscz b/vtest/scores/mmrest-20.mscz new file mode 100644 index 0000000000000..93ce1df05f5a7 Binary files /dev/null and b/vtest/scores/mmrest-20.mscz differ