diff --git a/src/engraving/dom/chordrest.cpp b/src/engraving/dom/chordrest.cpp index 41dfcbb04c690..df01d044e5465 100644 --- a/src/engraving/dom/chordrest.cpp +++ b/src/engraving/dom/chordrest.cpp @@ -868,29 +868,45 @@ void ChordRest::processSiblings(std::function func) EngravingItem* ChordRest::nextArticulationOrLyric(EngravingItem* e) { - if (isChord() && e->isArticulationFamily()) { - Chord* c = toChord(this); - auto i = std::find(c->articulations().begin(), c->articulations().end(), e); - if (i != c->articulations().end()) { - if (i != c->articulations().end() - 1) { - return *(i + 1); - } else { - if (!m_lyrics.empty()) { - return m_lyrics[0]; - } else { - return nullptr; - } - } + if (e->isLyrics()) { + // The next element after Lyrics is the LyricsLine (if it exists)... + if (LyricsLine* line = toLyrics(e)->separator()) { + return line; } - } else { + } + if (e->isLyricsLine()) { + LyricsLine* lyricsLine = toLyricsLine(e); + Lyrics* lyrics = lyricsLine->lyrics(); + IF_ASSERT_FAILED(lyrics) { + return nullptr; + } + // We were on a LyricsLine - now we'll try to move to the next Lyrics... + e = lyrics; + } + + if (!isChord() || !e->isArticulationFamily()) { + // Move to the next Lyrics... auto i = std::find(m_lyrics.begin(), m_lyrics.end(), e); - if (i != m_lyrics.end()) { - if (i != m_lyrics.end() - 1) { - return *(i + 1); - } + if (i == m_lyrics.end() || i == m_lyrics.end() - 1) { + return nullptr; } + return *(i + 1); } - return 0; + + // Cycle through articulations... + Chord* c = toChord(this); + auto i = std::find(c->articulations().begin(), c->articulations().end(), e); + if (i == c->articulations().end()) { + return nullptr; + } + if (i != c->articulations().end() - 1) { + return *(i + 1); + } + if (!m_lyrics.empty()) { + return m_lyrics[0]; + } + + return nullptr; } //--------------------------------------------------------- @@ -899,27 +915,39 @@ EngravingItem* ChordRest::nextArticulationOrLyric(EngravingItem* e) EngravingItem* ChordRest::prevArticulationOrLyric(EngravingItem* e) { + const std::vector artics = isChord() ? toChord(this)->articulations() : std::vector(); + + if (e->isLyricsLine()) { + // The previous element to a LyricsLine is the associated Lyrics... + return toLyricsLine(e)->lyrics(); + } + auto i = std::find(m_lyrics.begin(), m_lyrics.end(), e); - if (i != m_lyrics.end()) { - if (i != m_lyrics.begin()) { - return *(i - 1); - } else { - if (isChord() && !toChord(this)->articulations().empty()) { - return toChord(this)->articulations().back(); - } else { - return nullptr; - } + if (i == m_lyrics.end()) { + // Cycle through articulations... + if (artics.empty()) { + return nullptr; } - } else if (isChord() && e->isArticulationFamily()) { - Chord* c = toChord(this); - auto j = std::find(c->articulations().begin(), c->articulations().end(), e); - if (j != c->articulations().end()) { - if (j != c->articulations().begin()) { - return *(j - 1); - } + auto j = std::find(artics.begin(), artics.end(), e); + if (j == artics.end() || j == artics.begin()) { + return nullptr; } + return *(j - 1); } - return 0; + if (i == m_lyrics.begin()) { + return !artics.empty() ? artics.back() : nullptr; + } + + // Move to the previous Lyrics... + Lyrics* lyrics = *(i - 1); + IF_ASSERT_FAILED(lyrics) { + return nullptr; + } + if (lyrics->separator()) { + // Move to the LyricsLine of the previous Lyrics (if it exists)... + return lyrics->separator(); + } + return lyrics; } //--------------------------------------------------------- @@ -936,7 +964,8 @@ EngravingItem* ChordRest::nextElement() case ElementType::ARTICULATION: case ElementType::ORNAMENT: case ElementType::TAPPING: - case ElementType::LYRICS: { + case ElementType::LYRICS: + case ElementType::LYRICSLINE: { EngravingItem* next = nextArticulationOrLyric(e); if (next) { return next; @@ -972,7 +1001,8 @@ EngravingItem* ChordRest::prevElement() case ElementType::ARTICULATION: case ElementType::ORNAMENT: case ElementType::TAPPING: - case ElementType::LYRICS: { + case ElementType::LYRICS: + case ElementType::LYRICSLINE: { EngravingItem* prev = prevArticulationOrLyric(e); if (prev) { return prev; @@ -1010,11 +1040,17 @@ EngravingItem* ChordRest::prevElement() EngravingItem* ChordRest::lastElementBeforeSegment() { - if (!m_lyrics.empty()) { - return m_lyrics.back(); + if (m_lyrics.empty()) { + return nullptr; } - - return nullptr; + Lyrics* lyrics = m_lyrics.back(); + IF_ASSERT_FAILED(lyrics) { + return nullptr; + } + if (LyricsLine* lyricsLine = lyrics->separator()) { + return lyricsLine; + } + return lyrics; } //--------------------------------------------------------- diff --git a/src/engraving/rendering/score/lyricslayout.cpp b/src/engraving/rendering/score/lyricslayout.cpp index b423b7fc2bffa..7fda185805965 100644 --- a/src/engraving/rendering/score/lyricslayout.cpp +++ b/src/engraving/rendering/score/lyricslayout.cpp @@ -21,6 +21,7 @@ */ #include "lyricslayout.h" +#include "dom/factory.h" #include "dom/masterscore.h" #include "dom/repeatlist.h" #include "style/styledef.h" @@ -481,7 +482,7 @@ void LyricsLayout::createOrRemoveLyricsLine(Lyrics* item, LayoutContext& ctx) if (isEndMelisma() || item->syllabic() == LyricsSyllabic::BEGIN || item->syllabic() == LyricsSyllabic::MIDDLE) { if (!item->separator()) { - LyricsLine* separator = new LyricsLine(ctx.mutDom().dummyParent()); + LyricsLine* separator = Factory::createLyricsLine(ctx.mutDom().dummyParent()); separator->setTick(cr->tick()); item->setSeparator(separator); ctx.mutDom().addUnmanagedSpanner(item->separator());