Skip to content

Commit

Permalink
Merge pull request #26264 from miiizen/repeat-courtesies
Browse files Browse the repository at this point in the history
Implement repeat courtesies
  • Loading branch information
mike-spa authored Feb 7, 2025
2 parents 2e93b7f + cbd93b6 commit a494713
Show file tree
Hide file tree
Showing 101 changed files with 3,033 additions and 523 deletions.
110 changes: 6 additions & 104 deletions src/engraving/dom/clef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ PropertyValue Clef::getProperty(Pid propertyId) const
case Pid::SMALL: return isSmall();
case Pid::CLEF_TO_BARLINE_POS: return m_clefToBarlinePosition;
case Pid::IS_HEADER: return m_isHeader;
case Pid::IS_COURTESY: return m_isCourtesy;
default:
return EngravingItem::getProperty(propertyId);
}
Expand Down Expand Up @@ -326,6 +327,9 @@ bool Clef::setProperty(Pid propertyId, const PropertyValue& v)
case Pid::IS_HEADER:
m_isHeader = v.toBool();
break;
case Pid::IS_COURTESY:
m_isCourtesy = v.toBool();
break;
default:
return EngravingItem::setProperty(propertyId, v);
}
Expand All @@ -342,7 +346,6 @@ void Clef::changeClefToBarlinePos(ClefToBarlinePosition newPos)
}

Segment* seg = segment();
Measure* meas = seg->measure();

staff_idx_t nStaves = score()->nstaves();
for (staff_idx_t staffIndex = 0; staffIndex < nStaves; ++staffIndex) {
Expand All @@ -352,111 +355,9 @@ void Clef::changeClefToBarlinePos(ClefToBarlinePosition newPos)
}
}

Segment* endBarlineSeg = nullptr;
Segment* endRepeatSeg = nullptr;
Segment* startRepeatSeg = nullptr;

// Search first segment at this tick
Segment* firstSegAtThisTick = seg;
while (true) {
Segment* prev1 = firstSegAtThisTick->prev1();
if (prev1 && prev1->tick() == seg->tick()) {
firstSegAtThisTick = prev1;
} else {
break;
}
}
for (Segment* s = firstSegAtThisTick; s && s->tick() == seg->tick(); s = s->next1enabled()) {
// Scan all segments at this tick looking for the ones we need
if (s->isEndBarLineType() && s->measure()->repeatEnd()) {
endRepeatSeg = s;
} else if (s->isEndBarLineType()) {
endBarlineSeg = s;
} else if (s->isStartRepeatBarLineType()) {
startRepeatSeg = s;
}
}

if (newPos == ClefToBarlinePosition::AFTER) {
undoChangeProperty(Pid::SHOW_COURTESY, false, propertyFlags(Pid::SHOW_COURTESY));
}

if (newPos == ClefToBarlinePosition::AUTO) {
if (endBarlineSeg) {
// Clef before the end bar line
Measure* destMeas = endBarlineSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, endBarlineSeg);
seg->setRtick(endBarlineSeg->rtick());
seg->setParent(destMeas);
} else if (endRepeatSeg) {
// Clef after the end repeat
Measure* destMeas = endRepeatSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, endRepeatSeg->next());
seg->setRtick(endRepeatSeg->rtick());
seg->setParent(destMeas);
} else if (startRepeatSeg) {
// End of previous measure
Measure* destMeas = startRepeatSeg->measure()->prevMeasure();
if (destMeas) {
meas->segments().remove(seg);
destMeas->segments().push_back(seg);
seg->setRtick(destMeas->ticks());
seg->setParent(destMeas);
}
}
} else if (newPos == ClefToBarlinePosition::BEFORE) {
if (endBarlineSeg || endRepeatSeg) {
// Before the bar line
Segment* refSeg = endBarlineSeg ? endBarlineSeg : endRepeatSeg;
Measure* destMeas = refSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, refSeg);
seg->setRtick(refSeg->rtick());
seg->setParent(destMeas);
} else if (startRepeatSeg) {
// End of previous measure
Measure* destMeas = startRepeatSeg->measure()->prevMeasure();
if (destMeas) {
meas->segments().remove(seg);
destMeas->segments().push_back(seg);
seg->setRtick(destMeas->ticks());
seg->setParent(destMeas);
}
}
} else if (newPos == ClefToBarlinePosition::AFTER) {
bool isAtMeasureEnd = seg->rtick() == meas->ticks();
if (startRepeatSeg) {
// After the start repeat
Measure* destMeas = startRepeatSeg->measure();
meas->segments().remove(seg);
destMeas->segments().insert(seg, startRepeatSeg->next());
seg->setRtick(startRepeatSeg->rtick());
seg->setParent(destMeas);
} else if (isAtMeasureEnd) {
Measure* destMeas = meas->nextMeasure();
if (destMeas && !destMeas->header()) {
meas->segments().remove(seg);
destMeas->segments().push_front(seg);
seg->setRtick(Fraction(0, 1));
seg->setParent(destMeas);
} else if (destMeas) {
Segment* refSeg = destMeas->firstEnabled();
while (refSeg && refSeg->header()) {
refSeg = refSeg->nextEnabled();
}
if (refSeg) {
meas->segments().remove(seg);
destMeas->segments().insert(seg, refSeg);
seg->setRtick(refSeg->rtick());
seg->setParent(destMeas);
}
}
}
}

if ((newPos == ClefToBarlinePosition::AUTO || newPos == ClefToBarlinePosition::BEFORE)) {
} else {
undoChangeProperty(Pid::SHOW_COURTESY, true, PropertyFlags::STYLED);
}
}
Expand Down Expand Up @@ -511,6 +412,7 @@ PropertyValue Clef::propertyDefault(Pid id) const
case Pid::SMALL: return false;
case Pid::CLEF_TO_BARLINE_POS: return ClefToBarlinePosition::AUTO;
case Pid::IS_HEADER: return false;
case Pid::IS_COURTESY: return false;
default: return EngravingItem::propertyDefault(id);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/engraving/dom/clef.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class Clef final : public EngravingItem
ClefType clefType() const;
void setClefType(ClefType i);

bool isCourtesy() const { return m_isCourtesy; }
void setIsCourtesy(const bool v) { m_isCourtesy = v; }

int subtype() const override { return int(clefType()); }
TranslatableString subtypeUserName() const override;

Expand Down Expand Up @@ -165,6 +168,7 @@ class Clef final : public EngravingItem
bool m_isSmall = false;
bool m_forInstrumentChange = false;
bool m_isHeader = false;
bool m_isCourtesy = false;
ClefToBarlinePosition m_clefToBarlinePosition = ClefToBarlinePosition::AUTO;
ClefTypeList m_clefTypes = ClefType::INVALID;
};
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/dom/dom.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ set(DOM_SRC
${CMAKE_CURRENT_LIST_DIR}/ottava.h
${CMAKE_CURRENT_LIST_DIR}/page.cpp
${CMAKE_CURRENT_LIST_DIR}/page.h
${CMAKE_CURRENT_LIST_DIR}/parenthesis.cpp
${CMAKE_CURRENT_LIST_DIR}/parenthesis.h
${CMAKE_CURRENT_LIST_DIR}/partialtie.cpp
${CMAKE_CURRENT_LIST_DIR}/partialtie.h
${CMAKE_CURRENT_LIST_DIR}/palmmute.cpp
Expand Down
11 changes: 7 additions & 4 deletions src/engraving/dom/engravingitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,15 @@ enum class ElementFlag {
NO_BREAK = 0x00100000,
HEADER = 0x00200000,
TRAILER = 0x00400000, // also used in segment
KEYSIG = 0x00800000,
COURTESY_KEYSIG = 0x00800000,
COURTESY_TIMESIG = 0x01000000,
COURTESY_CLEF = 0x02000000,

// segment flags
ENABLED = 0x01000000, // used for segments
EMPTY = 0x02000000,
WRITTEN = 0x04000000,
ENABLED = 0x04000000, // used for segments
EMPTY = 0x08000000,
WRITTEN = 0x10000000,
END_OF_MEASURE_CHANGE = 0x20000000
};

typedef muse::Flags<ElementFlag> ElementFlags;
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/engravingobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class OttavaSegment;
class Page;
class PalmMute;
class PalmMuteSegment;
class Parenthesis;
class Part;
class PartialLyricsLine;
class PartialLyricsLineSegment;
Expand Down Expand Up @@ -454,6 +455,7 @@ class EngravingObject
CONVERT(FretCircle, FRET_CIRCLE)
CONVERT(StringTunings, STRING_TUNINGS)
CONVERT(TimeTickAnchor, TIME_TICK_ANCHOR)
CONVERT(Parenthesis, PARENTHESIS)
#undef CONVERT

virtual bool isEngravingItem() const { return false; } // overridden in element.h
Expand Down Expand Up @@ -868,5 +870,6 @@ CONVERT(LaissezVib)
CONVERT(PartialTie)
CONVERT(PartialLyricsLine)
CONVERT(PartialLyricsLineSegment)
CONVERT(Parenthesis)
#undef CONVERT
}
5 changes: 5 additions & 0 deletions src/engraving/dom/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
#include "ottava.h"
#include "page.h"
#include "palmmute.h"
#include "parenthesis.h"
#include "partialtie.h"
#include "pedal.h"
#include "pickscrape.h"
Expand Down Expand Up @@ -239,6 +240,7 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
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::PARENTHESIS: return new Parenthesis(parent->isSegment() ? toSegment(parent) : dummy->segment());

case ElementType::LYRICSLINE:
case ElementType::TEXTLINE_BASE:
Expand Down Expand Up @@ -785,3 +787,6 @@ SystemLockIndicator* Factory::createSystemLockIndicator(System * parent, const S
}

COPY_ITEM_IMPL(SystemLockIndicator)

CREATE_ITEM_IMPL(Parenthesis, ElementType::PARENTHESIS, Segment, isAccessibleEnabled);
COPY_ITEM_IMPL(Parenthesis)
3 changes: 3 additions & 0 deletions src/engraving/dom/factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ class Factory

static Page* createPage(RootItem* parent, bool isAccessibleEnabled = true);

static Parenthesis* createParenthesis(Segment* parent, bool isAccessibleEnabled = true);
static Parenthesis* copyParenthesis(const Parenthesis& src);

static PartialTie* createPartialTie(Note* parent, bool isAccessibleEnabled = true);
static PartialTie* copyPartialTie(const PartialTie& src);

Expand Down
7 changes: 7 additions & 0 deletions src/engraving/dom/keysig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ PropertyValue KeySig::getProperty(Pid propertyId) const
return int(showCourtesy());
case Pid::KEYSIG_MODE:
return int(mode());
case Pid::IS_COURTESY:
return _isCourtesy;
default:
return EngravingItem::getProperty(propertyId);
}
Expand Down Expand Up @@ -249,6 +251,9 @@ bool KeySig::setProperty(Pid propertyId, const PropertyValue& v)
setMode(KeyMode(v.toInt()));
staff()->setKey(tick(), keySigEvent());
break;
case Pid::IS_COURTESY:
_isCourtesy = v.toBool();
break;
default:
if (!EngravingItem::setProperty(propertyId, v)) {
return false;
Expand All @@ -275,6 +280,8 @@ PropertyValue KeySig::propertyDefault(Pid id) const
return true;
case Pid::KEYSIG_MODE:
return int(KeyMode::UNKNOWN);
case Pid::IS_COURTESY:
return false;
default:
return EngravingItem::propertyDefault(id);
}
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/dom/keysig.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class KeySig final : public EngravingItem
OBJECT_ALLOCATOR(engraving, KeySig)
DECLARE_CLASSOF(ElementType::KEYSIG)

M_PROPERTY2(bool, isCourtesy, setIsCourtesy, false)

public:

KeySig* clone() const override { return new KeySig(*this); }
Expand Down
8 changes: 4 additions & 4 deletions src/engraving/dom/masterscore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,15 +620,15 @@ MeasureBase* MasterScore::insertMeasure(MeasureBase* beforeMeasure, const Insert
moveClef = initClef;
} else {
ClefToBarlinePosition clefPos = toClef(e)->clefToBarlinePosition();
if (clefPos == ClefToBarlinePosition::AFTER) {
// non header clef at the begining of the measure
moveClef = true;
} else if (isBeginning) {
if (isBeginning) {
// special case:
// there is a non-header clef at global tick 0, and we are inserting at the beginning of the score.
// this clef will be moved with the measure it accompanies, but it will be moved before the barline.
specialCase = true;
moveClef = true;
} else if (clefPos == ClefToBarlinePosition::AFTER) {
// non header clef at the begining of the measure
moveClef = true;
}
}
} else {
Expand Down
27 changes: 22 additions & 5 deletions src/engraving/dom/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,10 +839,11 @@ void Measure::add(EngravingItem* e)
}
break;
case ElementType::JUMP:
setRepeatJump(true);
// fall through

case ElementType::MARKER:
if (e && (e->isJump() || muse::contains(Marker::RIGHT_MARKERS, toMarker(e)->markerType()))) {
// "To coda" markings act like jumps
setRepeatJump(true);
}
el().push_back(e);
break;

Expand Down Expand Up @@ -1798,7 +1799,7 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
if (nl > ol) {
// move EndBarLine, TimeSigAnnounce, KeySigAnnounce
for (Segment* seg = m->first(); seg; seg = seg->next()) {
if (seg->segmentType() & (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce | SegmentType::KeySigAnnounce)) {
if (seg->segmentType() & (SegmentType::EndBarLine | SegmentType::CourtesyTimeSigType | SegmentType::CourtesyKeySigType)) {
seg->setRtick(nl);
}
}
Expand Down Expand Up @@ -1976,7 +1977,7 @@ bool Measure::isFinalMeasureOfSection() const
return false;
}

LayoutBreak* Measure::sectionBreakElement(bool includeNextFrames)
LayoutBreak* Measure::sectionBreakElement(bool includeNextFrames) const
{
const MeasureBase* mb = static_cast<const MeasureBase*>(this);

Expand Down Expand Up @@ -3461,6 +3462,22 @@ void Measure::checkTrailer()
}
}

void Measure::checkEndOfMeasureChange()
{
bool found = false;
for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
if (seg->enabled() && seg->endOfMeasureChange()) {
setEndOfMeasureChange(seg->endOfMeasureChange());
found = true;
break;
}
}

if (!found) {
setEndOfMeasureChange(false);
}
}

bool Measure::canAddStringTunings(staff_idx_t staffIdx) const
{
Staff* staff = score()->staff(staffIdx);
Expand Down
3 changes: 2 additions & 1 deletion src/engraving/dom/measure.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class Measure final : public MeasureBase
bool visible(staff_idx_t staffIdx) const;
bool stemless(staff_idx_t staffIdx) const;
bool isFinalMeasureOfSection() const;
LayoutBreak* sectionBreakElement(bool includeNextFrames = true);
LayoutBreak* sectionBreakElement(bool includeNextFrames = true) const;
bool isAnacrusis() const;
bool isFirstInSystem() const;
bool isLastInSystem() const;
Expand Down Expand Up @@ -352,6 +352,7 @@ class Measure final : public MeasureBase

void checkHeader();
void checkTrailer();
void checkEndOfMeasureChange();

void respaceSegments();

Expand Down
13 changes: 11 additions & 2 deletions src/engraving/dom/measurebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,17 @@ class MeasureBase : public EngravingItem
bool noBreak() const { return flag(ElementFlag::NO_BREAK); }
void setNoBreak(bool v) { setFlag(ElementFlag::NO_BREAK, v); }

bool hasCourtesyKeySig() const { return flag(ElementFlag::KEYSIG); }
void setHasCourtesyKeySig(bool v) { setFlag(ElementFlag::KEYSIG, v); }
bool hasCourtesyKeySig() const { return flag(ElementFlag::COURTESY_KEYSIG); }
void setHasCourtesyKeySig(bool v) { setFlag(ElementFlag::COURTESY_KEYSIG, v); }

bool hasCourtesyTimeSig() const { return flag(ElementFlag::COURTESY_TIMESIG); }
void setHasCourtesyTimeSig(bool v) const { setFlag(ElementFlag::COURTESY_TIMESIG, v); }

bool hasCourtesyClef() const { return flag(ElementFlag::COURTESY_CLEF); }
void setHasCourtesyClef(bool v) const { setFlag(ElementFlag::COURTESY_CLEF, v); }

bool endOfMeasureChange() const { return flag(ElementFlag::END_OF_MEASURE_CHANGE); }
void setEndOfMeasureChange(bool val) const { setFlag(ElementFlag::END_OF_MEASURE_CHANGE, val); }

virtual void computeMinWidth() { }

Expand Down
Loading

0 comments on commit a494713

Please sign in to comment.