Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial lyric lines #25980

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/engraving/api/v1/apitypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ enum class ElementType {
VOLTA_SEGMENT = int(mu::engraving::ElementType::VOLTA_SEGMENT),
PEDAL_SEGMENT = int(mu::engraving::ElementType::PEDAL_SEGMENT),
LYRICSLINE_SEGMENT = int(mu::engraving::ElementType::LYRICSLINE_SEGMENT),
PARTIAL_LYRICSLINE_SEGMENT = int(mu::engraving::ElementType::PARTIAL_LYRICSLINE_SEGMENT),
GLISSANDO_SEGMENT = int(mu::engraving::ElementType::GLISSANDO_SEGMENT),
NOTELINE_SEGMENT = int(mu::engraving::ElementType::NOTELINE_SEGMENT),
LAYOUT_BREAK = int(mu::engraving::ElementType::LAYOUT_BREAK),
Expand Down Expand Up @@ -319,6 +320,7 @@ enum class ElementType {
TEXTLINE_BASE = int(mu::engraving::ElementType::TEXTLINE_BASE),
NOTELINE = int(mu::engraving::ElementType::NOTELINE),
LYRICSLINE = int(mu::engraving::ElementType::LYRICSLINE),
PARTIAL_LYRICSLINE = int(mu::engraving::ElementType::PARTIAL_LYRICSLINE),
GLISSANDO = int(mu::engraving::ElementType::GLISSANDO),
BRACKET = int(mu::engraving::ElementType::BRACKET),
SEGMENT = int(mu::engraving::ElementType::SEGMENT),
Expand Down
5 changes: 5 additions & 0 deletions src/engraving/dom/chordrest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,11 @@ void ChordRest::remove(EngravingItem* e)
}
}
break;
// case ElementType::PARTIAL_LYRICSLINE: {
// e->resetExplicitParent();
// score()->undoRemoveElement()
// }
// break;
default:
ASSERT_X(u"ChordRest::remove: unknown element " + String::fromAscii(e->typeName()));
}
Expand Down
34 changes: 32 additions & 2 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,17 @@ TextBase* Score::addText(TextStyleType type, EngravingItem* destinationElement)
}

int no = static_cast<int>(chordRest->lyrics().size());
const auto& spanners = spannerMap().findOverlapping(chordRest->tick().ticks(), chordRest->endTick().ticks());
for (auto& spanner : spanners) {
if (!spanner.value->isPartialLyricsLine() || spanner.start != chordRest->tick().ticks()) {
continue;
}
const PartialLyricsLine* line = toPartialLyricsLine(spanner.value);

no = std::max(no, line->no() + 1);
}

// Also check how many partial lines there are
Lyrics* lyrics = Factory::createLyrics(chordRest);
lyrics->setTrack(chordRest->track());
lyrics->setParent(chordRest);
Expand Down Expand Up @@ -2894,6 +2905,7 @@ void Score::deleteItem(EngravingItem* el)
case ElementType::LAISSEZ_VIB_SEGMENT:
case ElementType::PARTIAL_TIE_SEGMENT:
case ElementType::LYRICSLINE_SEGMENT:
case ElementType::PARTIAL_LYRICSLINE_SEGMENT:
case ElementType::PEDAL_SEGMENT:
case ElementType::GLISSANDO_SEGMENT:
case ElementType::NOTELINE_SEGMENT:
Expand Down Expand Up @@ -6069,6 +6081,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
&& et != ElementType::VIBRATO
&& et != ElementType::TEXTLINE
&& et != ElementType::PEDAL
&& et != ElementType::PARTIAL_LYRICSLINE
&& et != ElementType::BREATH
&& et != ElementType::DYNAMIC
&& et != ElementType::EXPRESSION
Expand Down Expand Up @@ -6134,6 +6147,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
ElementType::TEXTLINE,
ElementType::PEDAL,
ElementType::LYRICS,
ElementType::PARTIAL_LYRICSLINE,
ElementType::CLEF,
ElementType::AMBITUS
};
Expand Down Expand Up @@ -6167,6 +6181,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
case ElementType::DYNAMIC:
case ElementType::EXPRESSION:
case ElementType::LYRICS: // not normally segment-attached
case ElementType::PARTIAL_LYRICSLINE:
continue;
default:
break;
Expand Down Expand Up @@ -6336,7 +6351,8 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
|| element->isTrill()
|| element->isVibrato()
|| element->isTextLine()
|| element->isPedal()) {
|| element->isPedal()
|| element->isPartialLyricsLine()) {
Spanner* sp = toSpanner(element);
Spanner* nsp = toSpanner(ne);
track_idx_t tr2 = sp->effectiveTrack2();
Expand Down Expand Up @@ -7192,9 +7208,23 @@ void Score::undoRemoveStaleTieJumpPoints()
for (Segment* s = m->first(st); s; s = s->next1(st)) {
for (track_idx_t i = 0; i < tracks; ++i) {
EngravingItem* e = s->element(i);
if (e == 0 || !e->isChord()) {
if (e == 0 || !e->isChordRest()) {
continue;
}

// Remove invalid lyrics dashes
for (Lyrics* lyrics : toChordRest(e)->lyrics()) {
LyricsLine* separator = lyrics->separator();
if ((lyrics->syllabic() == LyricsSyllabic::BEGIN || lyrics->syllabic() == LyricsSyllabic::MIDDLE) && separator
&& !separator->nextLyrics() && !separator->isEndMelisma()) {
lyrics->setNeedRemoveInvalidSegments();
}
}

if (!e->isChord()) {
continue;
}

Chord* c = toChord(e);
for (Note* n : c->notes()) {
if (!n->tieFor()) {
Expand Down
15 changes: 13 additions & 2 deletions src/engraving/dom/engravingobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class Page;
class PalmMute;
class PalmMuteSegment;
class Part;
class PartialLyricsLine;
class PartialLyricsLineSegment;
class PartialTie;
class PartialTieSegment;
class Pedal;
Expand Down Expand Up @@ -422,8 +424,8 @@ class EngravingObject
CONVERT(FSymbol, FSYMBOL)
CONVERT(Fingering, FINGERING)
CONVERT(NoteHead, NOTEHEAD)
CONVERT(LyricsLine, LYRICSLINE)
CONVERT(LyricsLineSegment, LYRICSLINE_SEGMENT)
CONVERT(PartialLyricsLine, PARTIAL_LYRICSLINE)
CONVERT(PartialLyricsLineSegment, PARTIAL_LYRICSLINE_SEGMENT)
CONVERT(FiguredBass, FIGURED_BASS)
CONVERT(FiguredBassItem, FIGURED_BASS_ITEM)
CONVERT(StaffState, STAFF_STATE)
Expand Down Expand Up @@ -528,6 +530,13 @@ class EngravingObject
;
}

bool isLyricsLine() const { return type() == ElementType::LYRICSLINE || type() == ElementType::PARTIAL_LYRICSLINE; }

bool isLyricsLineSegment() const
{
return type() == ElementType::LYRICSLINE_SEGMENT || type() == ElementType::PARTIAL_LYRICSLINE_SEGMENT;
}

bool isSLine() const
{
return isTextLineBase() || isTrill() || isGlissando() || isVibrato() || isGuitarBend() || isGuitarBendHold();
Expand Down Expand Up @@ -857,5 +866,7 @@ CONVERT(SoundFlag)
CONVERT(TimeTickAnchor)
CONVERT(LaissezVib)
CONVERT(PartialTie)
CONVERT(PartialLyricsLine)
CONVERT(PartialLyricsLineSegment)
#undef CONVERT
}
9 changes: 7 additions & 2 deletions src/engraving/dom/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
case ElementType::TIME_TICK_ANCHOR: return new TimeTickAnchor(parent->isSegment() ? toSegment(parent) : dummy->segment());
case ElementType::LAISSEZ_VIB: return new LaissezVib(parent->isNote() ? toNote(parent) : dummy->note());
case ElementType::PARTIAL_TIE: return new PartialTie(parent->isNote() ? toNote(parent) : dummy->note());
case ElementType::PARTIAL_LYRICSLINE: return new PartialLyricsLine(parent);

case ElementType::LYRICSLINE:
case ElementType::TEXTLINE_BASE:
Expand Down Expand Up @@ -271,6 +272,7 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
case ElementType::VOLTA_SEGMENT:
case ElementType::PEDAL_SEGMENT:
case ElementType::LYRICSLINE_SEGMENT:
case ElementType::PARTIAL_LYRICSLINE_SEGMENT:
case ElementType::LEDGER_LINE:
case ElementType::STAFF_LINES:
case ElementType::SELECTION:
Expand Down Expand Up @@ -475,9 +477,12 @@ Page* Factory::createPage(RootItem* parent, bool isAccessibleEnabled)
}

CREATE_ITEM_IMPL(PartialTie, ElementType::PARTIAL_TIE, Note, isAccessibleEnabled)
COPY_ITEM_IMPL(PartialTie);
COPY_ITEM_IMPL(PartialTie)

Rest* Factory::createRest(Segment* parent, bool isAccessibleEnabled)
CREATE_ITEM_IMPL(PartialLyricsLine, ElementType::PARTIAL_LYRICSLINE, EngravingItem, isAccessibleEnabled)
COPY_ITEM_IMPL(PartialLyricsLine)

Rest* Factory::createRest(Segment * parent, bool isAccessibleEnabled)
{
Rest* r = new Rest(parent);
r->setAccessibleEnabled(isAccessibleEnabled);
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ class Factory
static PartialTie* createPartialTie(Note* parent, bool isAccessibleEnabled = true);
static PartialTie* copyPartialTie(const PartialTie& src);

static PartialLyricsLine* createPartialLyricsLine(EngravingItem* parent, bool isAccessibleEnabled = true);
static PartialLyricsLine* copyPartialLyricsLine(const PartialLyricsLine& src);

static Rest* createRest(Segment* parent, bool isAccessibleEnabled = true);
static Rest* createRest(Segment* parent, const TDuration& t, bool isAccessibleEnabled = true);
static Rest* copyRest(const Rest& src, bool link = false);
Expand Down
19 changes: 12 additions & 7 deletions src/engraving/dom/lyrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "system.h"
#include "textedit.h"
#include "undo.h"
#include "utils.h"

#include "log.h"

Expand Down Expand Up @@ -88,11 +89,6 @@ TranslatableString Lyrics::subtypeUserName() const

void Lyrics::add(EngravingItem* el)
{
// el->setParent(this);
// if (el->type() == ElementType::LINE)
// _separator.append((Line*)el); // ignore! Internally managed
// ;
// else
LOGD("Lyrics::add: unknown element %s", el->typeName());
}

Expand Down Expand Up @@ -330,6 +326,15 @@ void Lyrics::adjustPrevious()
}
}

void Lyrics::setNeedRemoveInvalidSegments()
{
// Allow "invalid" segments when there is a partial lyric line in a following repeat segment
if (chordRest()->hasFollowingJumpItem() && repeatHasPartialLyricLine(measure())) {
return;
}
m_needRemoveInvalidSegments = true;
}

//---------------------------------------------------------
// endEdit
//---------------------------------------------------------
Expand Down Expand Up @@ -559,9 +564,9 @@ void Lyrics::removeInvalidSegments()
m_separator = nullptr;
setAlign(propertyDefault(Pid::ALIGN).value<Align>());
if (m_syllabic == LyricsSyllabic::BEGIN || m_syllabic == LyricsSyllabic::SINGLE) {
m_syllabic = LyricsSyllabic::SINGLE;
undoChangeProperty(Pid::SYLLABIC, int(LyricsSyllabic::SINGLE));
} else {
m_syllabic = LyricsSyllabic::END;
undoChangeProperty(Pid::SYLLABIC, int(LyricsSyllabic::END));
}
}
}
Expand Down
88 changes: 78 additions & 10 deletions src/engraving/dom/lyrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef MU_ENGRAVING_LYRICS_H
#define MU_ENGRAVING_LYRICS_H
#pragma once

#include "../types/types.h"
#include "line.h"
Expand Down Expand Up @@ -81,7 +80,7 @@ class Lyrics final : public TextBase
void adjustPrevious();

bool needRemoveInvalidSegments() const { return m_needRemoveInvalidSegments; }
void setNeedRemoveInvalidSegments() { m_needRemoveInvalidSegments = true; }
void setNeedRemoveInvalidSegments();
void removeInvalidSegments();

LyricsLine* separator() const { return m_separator; }
Expand Down Expand Up @@ -124,7 +123,7 @@ class Lyrics final : public TextBase
/// \cond PLUGIN_API \private \endcond
//---------------------------------------------------------

class LyricsLine final : public SLine
class LyricsLine : public SLine
{
OBJECT_ALLOCATOR(engraving, LyricsLine)
DECLARE_CLASSOF(ElementType::LYRICSLINE)
Expand All @@ -139,14 +138,16 @@ class LyricsLine final : public SLine
void removeUnmanaged() override;
void styleChanged() override;

Lyrics* lyrics() const { return toLyrics(explicitParent()); }
virtual Lyrics* lyrics() const { return toLyrics(explicitParent()); }
Lyrics* nextLyrics() const { return m_nextLyrics; }
void setNextLyrics(Lyrics* l) { m_nextLyrics = l; }
bool isEndMelisma() const { return lyrics() && lyrics()->ticks().isNotZero(); }
virtual bool isEndMelisma() const { return lyrics() && lyrics()->ticks().isNotZero(); }
bool isDash() const { return !isEndMelisma(); }
bool setProperty(Pid propertyId, const PropertyValue& v) override;

protected:
LyricsLine(const ElementType& type, EngravingItem* parent, ElementFlags = ElementFlag::NOTHING);

Lyrics* m_nextLyrics = nullptr;

void doComputeEndElement() override;
Expand All @@ -157,7 +158,7 @@ class LyricsLine final : public SLine
/// \cond PLUGIN_API \private \endcond
//---------------------------------------------------------

class LyricsLineSegment final : public LineSegment
class LyricsLineSegment : public LineSegment
{
OBJECT_ALLOCATOR(engraving, LyricsLineSegment)
DECLARE_CLASSOF(ElementType::LYRICSLINE_SEGMENT)
Expand All @@ -168,9 +169,19 @@ class LyricsLineSegment final : public LineSegment
LyricsLineSegment* clone() const override { return new LyricsLineSegment(*this); }

LyricsLine* lyricsLine() const { return toLyricsLine(spanner()); }
Lyrics* lyrics() const { return lyricsLine()->lyrics(); }
virtual Lyrics* lyrics() const { return lyricsLine()->lyrics(); }

virtual double baseLineShift() const;

double baseLineShift() const;
virtual int no() const { return lyrics()->no(); }
virtual bool lyricsPlaceAbove() const { return lyrics()->placeAbove(); }
virtual bool lyricsAddToSkyline() const { return lyrics()->addToSkyline(); }
virtual double lineSpacing() const { return lyrics()->lineSpacing(); }
Color color() const override { return lyrics()->color(); }
int gripsCount() const override { return 0; }
Grip initialEditModeGrip() const override { return Grip::NO_GRIP; }
Grip defaultGrip() const override { return Grip::NO_GRIP; }
bool needStartEditingAfterSelecting() const override { return false; }

struct LayoutData : public LineSegment::LayoutData {
public:
Expand All @@ -181,6 +192,63 @@ class LyricsLineSegment final : public LineSegment
std::vector<LineF> m_dashes;
};
DECLARE_LAYOUTDATA_METHODS(LyricsLineSegment)

protected:
LyricsLineSegment(const ElementType& type, LyricsLine* sp, System* parent, ElementFlags f = ElementFlag::NOTHING);
};

class PartialLyricsLine final : public LyricsLine
{
OBJECT_ALLOCATOR(engraving, PartialLyricsLine)
DECLARE_CLASSOF(ElementType::PARTIAL_LYRICSLINE)

M_PROPERTY2(int, no, setNo, 0)
public:
PartialLyricsLine(EngravingItem* parent);
PartialLyricsLine(const PartialLyricsLine&);
PartialLyricsLine* clone() const override { return new PartialLyricsLine(*this); }
LineSegment* createLineSegment(System* parent) override;

Lyrics* lyrics() const override { return nullptr; }

void setIsEndMelisma(bool val) { m_isEndMelisma = val; }
bool isEndMelisma() const override { return m_isEndMelisma; }

PropertyValue getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const PropertyValue&) override;
PropertyValue propertyDefault(Pid propertyId) const override;
Sid getPropertyStyle(Pid propertyId) const override;

Lyrics* findLyricsInPreviousRepeatSeg() const;
Lyrics* findAdjacentLyricsOrDefault() const;

protected:
void doComputeEndElement() override;

private:
bool m_isEndMelisma = false;
};

class PartialLyricsLineSegment final : public LyricsLineSegment
{
OBJECT_ALLOCATOR(engraving, PartialLyricsLineSegment)
DECLARE_CLASSOF(ElementType::PARTIAL_LYRICSLINE_SEGMENT)

public:
PartialLyricsLineSegment(PartialLyricsLine*, System* parent);

LyricsLineSegment* clone() const override { return new PartialLyricsLineSegment(*this); }

PartialLyricsLine* lyricsLine() const { return toPartialLyricsLine(spanner()); }
Lyrics* lyrics() const override { return nullptr; }

int no() const override { return lyricsLine()->no(); }
double lineSpacing() const override;
bool lyricsPlaceAbove() const override { return lyricsLine()->placeAbove(); }// Delegate?
bool lyricsAddToSkyline() const override { return lyricsLine()->addToSkyline(); }
Color color() const override { return lyricsLine()->color(); }
double baseLineShift() const override;

EngravingItem* propertyDelegate(Pid) override;
};
} // namespace mu::engraving
#endif
Loading
Loading