Skip to content

Commit 423355a

Browse files
authored
Merge pull request #33837 from miiizen/mmrests2
Fix MMRest bugs
2 parents d1cb2ad + ff85662 commit 423355a

38 files changed

Lines changed: 1706 additions & 1090 deletions

src/engraving/dom/excerpt.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,35 @@ static MeasureBase* cloneMeasure(MeasureBase* mb, Score* score, const Score* osc
11341134
return nmb;
11351135
}
11361136

1137+
void Excerpt::cloneMMRests(Score* sourceScore, Score* dstScore, const std::vector<staff_idx_t>& sourceStavesIndexes,
1138+
const TracksMap& trackList, TieMap& tieMap)
1139+
{
1140+
// When MMRests are enabled in the main score and we are creating a new part or revealing a hidden stave within one, we must copy MMRests
1141+
// Elements are moved from underlying measures to MMRest measures. If we do not copy these MMRests, the elements attached to them will be lost
1142+
// It doesn't matter if the MMRest range is different in the part to the score. As long as the MMRest measure is present in the DOM, MMRestLayout will
1143+
// correct this, setting the appropriate length and moving the elements to the correct locations
1144+
1145+
for (Measure* srcM = sourceScore->firstMeasure(); srcM; srcM = srcM->nextMeasure()) {
1146+
if (!srcM->hasMMRest()) {
1147+
continue;
1148+
}
1149+
1150+
Measure* dstM = dstScore->tick2measure(srcM->tick());
1151+
if (!dstM) {
1152+
continue;
1153+
}
1154+
1155+
Measure* srcMMRest = srcM->mmRest();
1156+
1157+
Measure* dstMMRest = toMeasure(cloneMeasure(srcMMRest, dstScore, sourceScore, sourceStavesIndexes, trackList, tieMap));
1158+
dstMMRest->setMMRestCount(srcMMRest->mmRestCount());
1159+
dstMMRest->setPrev(dstM->prev());
1160+
dstMMRest->setNext(dstScore->tick2measure(srcMMRest->tick() + srcMMRest->ticks()));
1161+
1162+
dstM->setMMRest(dstMMRest);
1163+
}
1164+
}
1165+
11371166
void Excerpt::cloneStaves(Score* sourceScore, Score* dstScore, const std::vector<staff_idx_t>& sourceStavesIndexes,
11381167
const TracksMap& trackList)
11391168
{
@@ -1157,6 +1186,8 @@ void Excerpt::cloneStaves(Score* sourceScore, Score* dstScore, const std::vector
11571186
measures->append(newMeasure);
11581187
}
11591188

1189+
cloneMMRests(sourceScore, dstScore, sourceStavesIndexes, trackList, tieMap);
1190+
11601191
size_t n = sourceStavesIndexes.size();
11611192
for (staff_idx_t dstStaffIdx = 0; dstStaffIdx < n; ++dstStaffIdx) {
11621193
Staff* srcStaff = sourceScore->staff(sourceStavesIndexes[dstStaffIdx]);
@@ -1222,6 +1253,8 @@ void Excerpt::cloneMeasures(Score* oscore, Score* score)
12221253
measures->append(newMeasure);
12231254
}
12241255

1256+
cloneMMRests(oscore, score, {}, {}, tieMap);
1257+
12251258
collectTieEndPoints(tieMap);
12261259
}
12271260

src/engraving/dom/excerpt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Part;
3636
class Score;
3737
class Staff;
3838
class Spanner;
39+
class TieMap;
3940

4041
class Excerpt
4142
{
@@ -100,6 +101,8 @@ class Excerpt
100101
friend class MasterScore;
101102

102103
static void promoteGapRestsToRealRests(const Measure* measure, staff_idx_t staffIdx);
104+
static void cloneMMRests(Score* sourceScore, Score* dstScore, const std::vector<staff_idx_t>& sourceStavesIndexes,
105+
const TracksMap& trackList, TieMap& tieMap);
103106

104107
void setInited(bool inited);
105108
void writeNameToMetaTags();

src/engraving/dom/measure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3028,7 +3028,7 @@ Measure* Measure::coveringMMRestOrThis()
30283028
m = m->prevMeasure();
30293029
}
30303030

3031-
if (m) {
3031+
if (m && !m->m_mmRest->mmRestLast()->isBefore(this)) {
30323032
return m->m_mmRest;
30333033
}
30343034

src/engraving/dom/mmrest.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ MMRest::MMRest(Segment* s)
4747
MMRest::MMRest(const MMRest& r, bool link)
4848
: Rest(r, link)
4949
{
50-
if (link) {
51-
score()->undo(new Link(this, const_cast<MMRest*>(&r)));
52-
setAutoplace(true);
53-
}
5450
m_numberVisible = r.m_numberVisible;
5551
}
5652

src/engraving/editing/edit.cpp

Lines changed: 9 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,16 +2839,6 @@ void Score::deleteItem(EngravingItem* el)
28392839
case ElementType::KEYSIG:
28402840
{
28412841
KeySig* k = toKeySig(el);
2842-
Measure* m = k->measure();
2843-
if (m->isMMRest()) {
2844-
m = m->mmRestFirst();
2845-
if (Segment* s = m->findSegment(SegmentType::KeySig, k->tick())) {
2846-
k = toKeySig(s->element(k->track()));
2847-
}
2848-
if (!k || k->generated()) {
2849-
return;
2850-
}
2851-
}
28522842
Segment* nextCrSeg = k->segment()->next1(SegmentType::ChordRest);
28532843
bool ic = nextCrSeg && nextCrSeg->findAnnotation(ElementType::INSTRUMENT_CHANGE,
28542844
el->part()->startTrack(), el->part()->endTrack() - 1);
@@ -3132,52 +3122,22 @@ void Score::deleteItem(EngravingItem* el)
31323122
case ElementType::BRACKET:
31333123
undoRemoveBracket(toBracket(el));
31343124
break;
3135-
3136-
case ElementType::LAYOUT_BREAK:
3137-
{
3138-
undoRemoveElement(el);
3139-
LayoutBreak* lb = toLayoutBreak(el);
3140-
MeasureBase* mb = lb->measure();
3141-
Measure* m = mb && mb->isMeasure() ? toMeasure(mb) : nullptr;
3142-
if (m && m->isMMRest()) {
3143-
// propagate to original measure
3144-
m = m->mmRestLast();
3145-
for (EngravingItem* e : m->el()) {
3146-
if (e->isLayoutBreak() && toLayoutBreak(e)->layoutBreakType() == toLayoutBreak(el)->layoutBreakType()) {
3147-
undoRemoveElement(e);
3148-
break;
3149-
}
3150-
}
3151-
}
3152-
}
3153-
break;
3154-
31553125
case ElementType::CLEF:
31563126
{
31573127
Clef* clef = toClef(el);
31583128
Measure* m = clef->measure();
3159-
if (m->isMMRest()) {
3160-
// propagate to original measure
3161-
m = m->mmRestLast();
3162-
Segment* s = m->findSegment(SegmentType::Clef, clef->segment()->tick());
3163-
if (s && s->element(clef->track())) {
3164-
Clef* c = toClef(s->element(clef->track()));
3165-
undoRemoveElement(c);
3166-
}
3167-
} else {
3168-
if (clef->generated()) {
3169-
// find the real clef if this is a cautionary one
3170-
if (m && m->prevMeasure()) {
3171-
Fraction tick = m->tick();
3172-
m = m->prevMeasure();
3173-
Segment* s = m->findSegment(SegmentType::Clef, tick);
3174-
if (s && s->element(clef->track())) {
3175-
clef = toClef(s->element(clef->track()));
3176-
}
3129+
if (clef->generated()) {
3130+
// find the real clef if this is a cautionary one
3131+
if (m && m->prevMeasure()) {
3132+
Fraction tick = m->tick();
3133+
m = m->prevMeasure();
3134+
Segment* s = m->findSegment(SegmentType::Clef, tick);
3135+
if (s && s->element(clef->track())) {
3136+
clef = toClef(s->element(clef->track()));
31773137
}
31783138
}
3179-
undoRemoveElement(clef);
31803139
}
3140+
undoRemoveElement(clef);
31813141
}
31823142
break;
31833143

@@ -3207,29 +3167,6 @@ void Score::deleteItem(EngravingItem* el)
32073167
}
32083168
}
32093169
break;
3210-
case ElementType::REHEARSAL_MARK:
3211-
case ElementType::TEMPO_TEXT:
3212-
{
3213-
Segment* s = toSegment(el->explicitParent());
3214-
Measure* m = s->measure();
3215-
if (m->isMMRest()) {
3216-
// propagate to original measure/element
3217-
m = m->mmRestFirst();
3218-
Segment* ns = m->findSegment(SegmentType::ChordRest, s->tick());
3219-
const auto annotations = ns->annotations(); // make a copy since we alter the list
3220-
for (EngravingItem* e : annotations) {
3221-
if (e->type() == el->type() && e->track() == el->track()) {
3222-
el = e;
3223-
undoRemoveElement(el);
3224-
break;
3225-
}
3226-
}
3227-
} else {
3228-
undoRemoveElement(el);
3229-
}
3230-
}
3231-
break;
3232-
32333170
case ElementType::LYRICSLINE_SEGMENT:
32343171
{
32353172
el = toLyricsLineSegment(el)->lyricsLine();
@@ -3341,53 +3278,6 @@ void Score::deleteItem(EngravingItem* el)
33413278
}
33423279
}
33433280
break;
3344-
3345-
case ElementType::MARKER:
3346-
{
3347-
Measure* m = toMeasure(el->explicitParent());
3348-
if (m->isMMRest()) {
3349-
// find corresponding marker in underlying measure
3350-
bool found = false;
3351-
// the marker may be in the first measure...
3352-
for (EngravingItem* e : m->mmRestFirst()->el()) {
3353-
if (e->isMarker() && e->subtype() == el->subtype()) {
3354-
undoRemoveElement(e);
3355-
found = true;
3356-
break;
3357-
}
3358-
}
3359-
if (!found) {
3360-
// ...or it may be in the last measure
3361-
for (EngravingItem* e : m->mmRestLast()->el()) {
3362-
if (e->isMarker() && e->subtype() == el->subtype()) {
3363-
undoRemoveElement(e);
3364-
break;
3365-
}
3366-
}
3367-
}
3368-
}
3369-
// whether m is an mmrest or not, we still need to remove el
3370-
undoRemoveElement(el);
3371-
}
3372-
break;
3373-
3374-
case ElementType::JUMP:
3375-
{
3376-
Measure* m = toMeasure(el->explicitParent());
3377-
if (m->isMMRest()) {
3378-
// find corresponding jump in underlying measure
3379-
for (EngravingItem* e : m->mmRestLast()->el()) {
3380-
if (e->isJump() && e->subtype() == el->subtype()) {
3381-
undoRemoveElement(e);
3382-
break;
3383-
}
3384-
}
3385-
}
3386-
// whether m is an mmrest or not, we still need to remove el
3387-
undoRemoveElement(el);
3388-
}
3389-
break;
3390-
33913281
case ElementType::SYSTEM_LOCK_INDICATOR:
33923282
{
33933283
const SystemLock* systemLock = toSystemLockIndicator(el)->systemLock();

src/engraving/editing/editmeasures.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,21 @@ void ChangeMeasureRepeatCount::flip(EditData*)
408408
m->setMeasureRepeatCount(count, staffIdx);
409409
count = oldCount;
410410
}
411+
412+
void ChangeMMRestNext::flip(EditData*)
413+
{
414+
assert(m_mmrest->isMMRest());
415+
MeasureBase* oldNext = m_mmrest->next();
416+
417+
m_mmrest->setNext(m_next);
418+
m_next = oldNext;
419+
}
420+
421+
void ChangeMMRestPrev::flip(EditData*)
422+
{
423+
assert(m_mmrest->isMMRest());
424+
MeasureBase* oldPrev = m_mmrest->prev();
425+
426+
m_mmrest->setPrev(m_prev);
427+
m_prev = oldPrev;
428+
}

src/engraving/editing/editmeasures.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,41 @@ class ChangeMMRest : public UndoableCommand
110110
UNDO_CHANGED_OBJECTS({ m, mmrest })
111111
};
112112

113+
// ChangeMMRestNext & ChangeMMRestPrev SHOULD ONLY BE USED FOR MMRests
114+
// Setting m_next & m_prev involves the score's MeasureList for regular measures
115+
// This is handled through undo commands above
116+
class ChangeMMRestNext : public UndoableCommand
117+
{
118+
OBJECT_ALLOCATOR(engraving, ChangeMMRestNext)
119+
120+
Measure* m_mmrest = nullptr;
121+
MeasureBase* m_next = nullptr;
122+
123+
void flip(EditData*) override;
124+
public:
125+
ChangeMMRestNext(Measure* mmrest, MeasureBase* next)
126+
: m_mmrest(mmrest), m_next(next) {}
127+
128+
UNDO_NAME("ChangeMMRestNext")
129+
UNDO_CHANGED_OBJECTS({ m_mmrest })
130+
};
131+
132+
class ChangeMMRestPrev : public UndoableCommand
133+
{
134+
OBJECT_ALLOCATOR(engraving, ChangeMMRestPrev)
135+
136+
Measure* m_mmrest = nullptr;
137+
MeasureBase* m_prev = nullptr;
138+
139+
void flip(EditData*) override;
140+
public:
141+
ChangeMMRestPrev(Measure* mmrest, MeasureBase* prev)
142+
: m_mmrest(mmrest), m_prev(prev) {}
143+
144+
UNDO_NAME("ChangeMMRestPrev")
145+
UNDO_CHANGED_OBJECTS({ m_mmrest })
146+
};
147+
113148
class ChangeMeasureRepeatCount : public UndoableCommand
114149
{
115150
OBJECT_ALLOCATOR(engraving, ChangeMeasureRepeatCount)

0 commit comments

Comments
 (0)