Skip to content
Permalink
Browse files

fix #196771 : Regroup Rhythms deletes various elements

  • Loading branch information...
AntonioBL authored and shoogle committed Mar 8, 2018
1 parent 3d20279 commit aeaa2ee1932892c1742a995df66a88ae46eebea8
@@ -3178,19 +3178,17 @@ void Chord::sortNotes()

Chord* Chord::nextTiedChord(bool backwards, bool sameSize)
{
Segment* nextSeg = segment();
ChordRest* nextCR = 0;
do {
nextSeg = backwards ? nextSeg->prev1(Segment::Type::ChordRest) : nextSeg->next1(Segment::Type::ChordRest);
if (!nextSeg)
return 0; // nothing to tie to
nextCR = nextSeg->cr(track());
} while (nextCR == 0); // nextCR = 0 when CR in another voice overlaps
if (!nextCR->isChord())
return 0; // can't tie to a rest
Segment* nextSeg = backwards ? segment()->prev1(Segment::Type::ChordRest) : segment()->next1(Segment::Type::ChordRest);
if (!nextSeg)
return 0;
ChordRest* nextCR = nextSeg->nextChordRest(track(), backwards);
if (!nextCR || !nextCR->isChord())
return 0;
Chord* next = static_cast<Chord*>(nextCR);
if (sameSize && notes().size() != next->notes().size())
return 0; // sizes don't match so some notes can't be tied
if (tuplet() != next->tuplet())
return 0; // next chord belongs to a different tuplet
for (Note* n : _notes) {
Tie* tie = backwards ? n->tieBack() : n->tieFor();
if (!tie)
@@ -1528,7 +1528,8 @@ void Score::regroupNotesAndRests(int startTick, int endTick, int track)
lastRest = cr;
}
int restTicks = lastRest->tick() + lastRest->duration().ticks() - curr->tick();
seg = setNoteRest(seg, curr->track(), NoteVal(), Fraction::fromTicks(restTicks), MScore::Direction::AUTO, true);
if (restTicks > curr->duration().ticks())
seg = setNoteRest(seg, curr->track(), NoteVal(), Fraction::fromTicks(restTicks), MScore::Direction::AUTO, true);
}
else {
// combine tied chords
@@ -1539,51 +1540,127 @@ void Score::regroupNotesAndRests(int startTick, int endTick, int track)
}
if (!lastTiedChord)
lastTiedChord = chord;
int numNotes = chord->notes().size();
int pitches[numNotes];
Tie* tieBack[numNotes];
Tie* tieFor[numNotes];
for (int i = 0; i < numNotes; i++) {
Note* n = chord->notes()[i];
Note* nn = lastTiedChord->notes()[i];
pitches[i] = n->pitch();
tieBack[i] = n->tieBack();
tieFor[i] = nn->tieFor();
n->setTieBack(0);
nn->setTieFor(0);
}
int noteTicks = lastTiedChord->tick() + lastTiedChord->duration().ticks() - chord->tick();
Segment* newSeg = setNoteRest(seg, curr->track(), NoteVal(pitches[0]), Fraction::fromTicks(noteTicks), MScore::Direction::AUTO, true);
for (seg = seg->prev1()->next1(Segment::Type::ChordRest);;seg = seg->next1(Segment::Type::ChordRest)) {
ChordRest* cr = seg->cr(track);
if (!cr)
continue; // voice is empty here
Chord* newChord = static_cast<Chord*>(cr);
Note* n = newChord->notes().front();
undoRemoveElement(n);
if (noteTicks > chord->duration().ticks()) {
// store start/end note for backward/forward ties ending/starting on the group of notes being rewritten
int numNotes = chord->notes().size();
Note* tieBack[numNotes];
Note* tieFor[numNotes];
for (int i = 0; i < numNotes; i++) {
NoteVal nval = NoteVal(pitches[i]);
n = addNote(newChord, nval);
if (tieBack[i]) {
n->setTieBack(tieBack[i]);
tieBack[i]->setEndNote(n);
Note* n = chord->notes()[i];
Note* nn = lastTiedChord->notes()[i];
if (n->tieBack())
tieBack[i] = n->tieBack()->startNote();
else
tieBack[i] = 0;
if (nn->tieFor())
tieFor[i] = nn->tieFor()->endNote();
else
tieFor[i] = 0;
}
int tick = seg->tick();
int track = chord->track();
Fraction sd = Fraction::fromTicks(noteTicks);
Tie* tie = 0;
Segment* segment = seg;
ChordRest* cr = static_cast<ChordRest*>(segment->element(track));
Chord* nchord = static_cast<Chord*>(chord->clone());
for (int i = 0; i < numNotes; i++) { // strip ties from cloned chord
Note* n = nchord->notes()[i];
n->setTieFor(0);
n->setTieBack(0);
}
Chord* startChord = nchord;
Measure* measure = 0;
bool firstpart = true;
for (;;) {
if (track % VOICES)
expandVoice(segment, track);
// the returned gap ends at the measure boundary or at tuplet end
Fraction dd = makeGap(segment, track, sd, cr->tuplet());
if (dd.isZero())
break;
measure = segment->measure();
QList<TDuration> dl = toRhythmicDurationList(dd, false, segment->rtick(), sigmap()->timesig(tick).nominal(), measure, 1);
int n = dl.size();
for (int i = 0; i < n; ++i) {
const TDuration& d = dl[i];
Chord* nchord2 = static_cast<Chord*>(nchord->clone());
if (!firstpart)
nchord2->removeMarkings(true);
nchord2->setDurationType(d);
nchord2->setDuration(d.fraction());
QList<Note*> nl1 = nchord->notes();
QList<Note*> nl2 = nchord2->notes();
if (!firstpart)
for (unsigned j = 0; j < nl1.size(); ++j) {
tie = new Tie(this);
tie->setStartNote(nl1[j]);
tie->setEndNote(nl2[j]);
tie->setTrack(track);
nl1[j]->setTieFor(tie);
nl2[j]->setTieBack(tie);
}
undoAddCR(nchord2, measure, tick);
segment = nchord2->segment();
tick += nchord2->actualTicks();
nchord = nchord2;
firstpart = false;
}
if (seg != newSeg) {
Tie* tie = new Tie(this);
n->setTieFor(tie);
tie->setStartNote(n);
sd -= dd;
if (sd.isZero())
break;
Segment* nseg = tick2segment(tick, false, Segment::Type::ChordRest);
if (nseg == 0)
break;
segment = nseg;
cr = static_cast<ChordRest*>(segment->element(track));
if (cr == 0) {
if (track % VOICES)
cr = addRest(segment, track, TDuration(TDuration::DurationType::V_MEASURE), 0);
else
break;
}
}
if (_is.slur()) {
// extend slur
_is.slur()->undoChangeProperty(P_ID::SPANNER_TICKS, nchord->tick() - _is.slur()->tick());
for (ScoreElement* e : _is.slur()->linkList()) {
Slur* slur = static_cast<Slur*>(e);
for (ScoreElement* ee : nchord->linkList()) {
Element* e = static_cast<Element*>(ee);
if (e->score() == slur->score() && e->track() == slur->track2()) {
slur->score()->undo(new ChangeSpannerElements(slur, slur->startElement(), e));
break;
}
}
}
}
// recreate previously stored pending ties
for (int i = 0; i < numNotes; i++) {
Note* n = startChord->notes()[i];
Note* nn = nchord->notes()[i];
if (tieBack[i]) {
tie = new Tie(this);
tie->setStartNote(tieBack[i]);
tie->setEndNote(n);
tie->setTrack(n->track());
tieBack[i] = tie;
tie->setTrack(track);
n->setTieBack(tie);
tieBack[i]->setTieFor(tie);
undoAddElement(tie);
}
else if (tieFor[i]) {
n->setTieFor(tieFor[i]);
tieFor[i]->setStartNote(n);
if (tieFor[i]) {
tie = new Tie(this);
tie->setStartNote(nn);
tie->setEndNote(tieFor[i]);
tie->setTrack(track);
n->setTieFor(tie);
tieFor[i]->setTieBack(tie);
undoAddElement(tie);
}
}
if (seg == newSeg)
break;
if (tie) // at least one tie was created
connectTies();
}
}
}

0 comments on commit aeaa2ee

Please sign in to comment.
You can’t perform that action at this time.