Skip to content

Commit

Permalink
Add partial lyrics lines
Browse files Browse the repository at this point in the history
  • Loading branch information
miiizen committed Jan 3, 2025
1 parent e363f24 commit cb02050
Show file tree
Hide file tree
Showing 31 changed files with 704 additions and 189 deletions.
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 @@ -2905,6 +2916,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 @@ -6080,6 +6092,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 @@ -6145,6 +6158,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 @@ -6178,6 +6192,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 @@ -6347,7 +6362,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 @@ -7203,9 +7219,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
9 changes: 2 additions & 7 deletions src/engraving/dom/lyrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,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 @@ -559,9 +554,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
82 changes: 73 additions & 9 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 @@ -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,59 @@ 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;

Lyrics* findLyricsInPreviousRepeatSeg();

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;
};
} // namespace mu::engraving
#endif
Loading

0 comments on commit cb02050

Please sign in to comment.