-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Implement repeat courtesies #26264
Implement repeat courtesies #26264
Conversation
2bacb0c
to
e656d9e
Compare
4fd33e2
to
beaed54
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely heroic work
src/engraving/dom/clef.cpp
Outdated
@@ -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 _isCourtesy; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_isCourtesy
, for consistency
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_isCourtesy
src/engraving/dom/clef.h
Outdated
@@ -89,6 +89,8 @@ class Clef final : public EngravingItem | |||
OBJECT_ALLOCATOR(engraving, Clef) | |||
DECLARE_CLASSOF(ElementType::CLEF) | |||
|
|||
M_PROPERTY2(bool, isCourtesy, setIsCourtesy, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I've used this too in the past, but lately I've always avoided this macro, and taken the boredome to write member/getter/setter. It's boilerplate, but you'll thank yourself for the boilerplate the first time you'll need to place a breakpoint to see who's getting/setting this variable.
src/engraving/dom/measurebase.h
Outdated
void setHasCourtesyTimeSig(bool v) const { setFlag(ElementFlag::TIMESIG, v); } | ||
|
||
bool hasCourtesyClef() const { return flag(ElementFlag::CLEF); } | ||
void setHasCourtesyClef(bool v) const { setFlag(ElementFlag::CLEF, v); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps the flags could be better named as COURTESY_TIMESIG, COURTESY_CLEF?
src/engraving/dom/measure.cpp
Outdated
if (seg->segmentType() | ||
& (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce | SegmentType::KeySigAnnounce | ||
| SegmentType::TimeSigRepeatAnnounce | SegmentType::KeySigRepeatAnnounce | SegmentType::TimeSigStartRepeatAnnounce | ||
| SegmentType::KeySigStartRepeatAnnounce)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure you can use some of the aliases you've created among SegmentType to make this statement a bit shorter/more readable?
if (m_segmentType == SegmentType::KeySigAnnounce | ||
|| m_segmentType == SegmentType::KeySigRepeatAnnounce || m_segmentType == SegmentType::KeySigStartRepeatAnnounce) { | ||
toKeySig(el)->setIsCourtesy(true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and all of the ones above I think you can use the aliases (and also take advantage of the bitwise |
operations which are faster)
src/engraving/dom/segment.cpp
Outdated
|| segmentType() == SegmentType::KeySigRepeatAnnounce | ||
|| segmentType() == SegmentType::ClefStartRepeatAnnounce | ||
|| segmentType() == SegmentType::TimeSigStartRepeatAnnounce | ||
|| segmentType() == SegmentType::KeySigStartRepeatAnnounce) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait... why doesn't this function simply return segmentType() != SegmentType::ChordRest
? 😅
src/engraving/dom/segment.cpp
Outdated
@@ -2532,11 +2564,15 @@ void Segment::createShape(staff_idx_t staffIdx) | |||
} | |||
} | |||
|
|||
rendering::score::SegmentLayout::placeParentheses(this, staffIdx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a tempting thing to do, but it's a mistake that I've made myself before and rolling it back later was ugly. We should never call layout functions from here. This function should have the one and only task of adding the (already laid out) elements to the segment shape, because that's what we expect it to do when we call it. If we let this function actively modify things by doing layout calls we open ouselves to side effects and properly shoot ourselves in the foot (ask me how I know...).
You're calling it here because obvs you need to know the shape of things in order to place the parenthesis correctly. But you can know that shape right after you've laid out the courtesy elements. So perhaps a good place to call this may be instead MeasureLayout::addRepeatContinuationCourtesies
?
// if time sig not at beginning of measure => courtesy time sig | ||
|
||
// PRE 4.5: if time sig not at beginning of measure => courtesy time sig | ||
// 4.5+ just tag it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YES. This insane thing of inferring that something is a courtesy because it's not at the start of the measure gave me nightmares. Let's purge it wherever we can
@@ -231,3 +233,84 @@ void SegmentLayout::layoutChordsStem(const Segment& segment, track_idx_t startTr | |||
} | |||
} | |||
} | |||
|
|||
void SegmentLayout::placeParentheses(const Segment* segment, staff_idx_t staffIdx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, just for organization, it's a bit weird to have this in SegmentLayout, given that this is stricly related to all the rest of the courtesy layout code. So I'd rather put this in MeasureLayout together with all the rest. Or, if you want or think it could make sense, even create a new layout class like CourtesyLayout and put everything in there that relates to courtesies
Small refactor of MeasureLayout::addSystemTrailer
Fix creating parens on single segment
beaed54
to
cbd93b6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of cleanup comments, but you can do that in the next PR :)
@@ -52,6 +52,8 @@ class TimeSig final : public EngravingItem | |||
OBJECT_ALLOCATOR(engraving, TimeSig) | |||
DECLARE_CLASSOF(ElementType::TIMESIG) | |||
|
|||
M_PROPERTY2(bool, isCourtesy, setIsCourtesy, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as before about avoiding this macro. And m_isCourtesy
|
||
#include "tlayout.h" | ||
#include "chordlayout.h" | ||
#include "horizontalspacing.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These can be now removed
This PR implements a selection of style options to create courtesy time signatures, key signatures and clefs before and after repeats and jumps.
Screen.Recording.2025-01-29.at.15.50.30.mov