Skip to content

Commit 436ddc6

Browse files
authored
Merge pull request #28470 from miiizen/27888-big-tie
Fix split, join and rewrite measure tie bugs
2 parents ae47941 + 79aeb3b commit 436ddc6

File tree

12 files changed

+853
-116
lines changed

12 files changed

+853
-116
lines changed

src/engraving/dom/range.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,8 @@ bool TrackList::write(Score* score, const Fraction& tick) const
656656
if (nn) {
657657
tie->setEndNote(nn);
658658
nn->setTieBack(tie);
659+
} else {
660+
score->doUndoRemoveElement(tie);
659661
}
660662
}
661663
if (s == segment) {
@@ -720,6 +722,23 @@ void ScoreRange::read(Segment* first, Segment* last, bool readSpanner)
720722
m_tracks.push_back(dl);
721723
}
722724
}
725+
726+
// Make sure incoming ties are restored
727+
Measure* m1 = first->measure();
728+
for (track_idx_t track = startTrack; track < endTrack; track++) {
729+
Chord* startChord = m1->findChord(first->tick(), track);
730+
if (!startChord) {
731+
continue;
732+
}
733+
for (Note* note : startChord->notes()) {
734+
Tie* tie = note->tieBack();
735+
if (!tie) {
736+
continue;
737+
}
738+
m_startTies.push_back(tie->clone());
739+
score->doUndoRemoveElement(tie);
740+
}
741+
}
723742
}
724743

725744
//---------------------------------------------------------
@@ -793,6 +812,18 @@ bool ScoreRange::write(Score* score, const Fraction& tick) const
793812
score->undoAddElement(a.e);
794813
}
795814
}
815+
816+
// Restore ties to the beginning of the first measure
817+
for (Tie* tie : m_startTies) {
818+
Note* endNote = searchTieNote(tie->startNote());
819+
if (!endNote) {
820+
delete tie;
821+
continue;
822+
}
823+
tie->setEndNote(endNote);
824+
score->doUndoAddElement(tie);
825+
}
826+
796827
return true;
797828
}
798829

src/engraving/dom/range.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Spanner;
4040
class ScoreRange;
4141
class ChordRest;
4242
class Score;
43+
class Tie;
4344

4445
//---------------------------------------------------------
4546
// TrackList
@@ -113,6 +114,7 @@ class ScoreRange
113114
friend class TrackList;
114115

115116
std::list<TrackList*> m_tracks;
117+
std::vector<Tie*> m_startTies;
116118
Segment* m_first = nullptr;
117119
Segment* m_last = nullptr;
118120
};

src/engraving/dom/score.cpp

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5909,69 +5909,71 @@ void Score::connectTies(bool silent)
59095909
return;
59105910
}
59115911

5912-
SegmentType st = SegmentType::ChordRest;
5913-
for (Segment* s = m->first(st); s; s = s->next1(st)) {
5914-
for (track_idx_t i = 0; i < tracks; ++i) {
5915-
EngravingItem* e = s->element(i);
5916-
if (e == 0 || !e->isChord()) {
5912+
auto connectTiesForChord = [silent](Chord* c, Segment* s, track_idx_t track) -> void {
5913+
for (Note* n : c->notes()) {
5914+
if (n->laissezVib()) {
59175915
continue;
59185916
}
5919-
Chord* c = toChord(e);
5920-
for (Note* n : c->notes()) {
5921-
if (n->laissezVib()) {
5922-
continue;
5923-
}
5924-
// connect a tie without end note
5925-
Tie* tie = n->tieFor();
5926-
if (tie) {
5927-
tie->updatePossibleJumpPoints();
5928-
}
5929-
if (tie && !tie->isPartialTie() && !tie->endNote()) {
5930-
Note* nnote;
5931-
if (m_mscVersion <= 114) {
5932-
nnote = searchTieNote114(n);
5933-
} else {
5934-
nnote = searchTieNote(n);
5935-
}
5936-
if (nnote == 0) {
5937-
if (!silent) {
5938-
LOGD("next note at %d track %zu for tie not found (version %d)", s->tick().ticks(), i, m_mscVersion);
5939-
delete tie;
5940-
n->setTieFor(0);
5941-
}
5942-
} else {
5943-
tie->setEndNote(nnote);
5944-
nnote->setTieBack(tie);
5945-
}
5946-
}
5947-
// connect a glissando without initial note (old glissando format)
5948-
for (Spanner* spanner : n->spannerBack()) {
5949-
if (spanner->isGlissando() && !spanner->startElement()) {
5950-
Note* initialNote = Glissando::guessInitialNote(n->chord());
5951-
n->removeSpannerBack(spanner);
5952-
if (initialNote) {
5953-
spanner->setStartElement(initialNote);
5954-
spanner->setEndElement(n);
5955-
spanner->setTick(initialNote->chord()->tick());
5956-
spanner->setTick2(n->chord()->tick());
5957-
spanner->setTrack(n->track());
5958-
spanner->setTrack2(n->track());
5959-
spanner->setParent(initialNote);
5960-
initialNote->add(spanner);
5961-
} else {
5962-
delete spanner;
5963-
}
5917+
// connect a tie without end note
5918+
Tie* tie = n->tieFor();
5919+
if (tie) {
5920+
tie->updatePossibleJumpPoints();
5921+
}
5922+
if (tie && !tie->isPartialTie() && !tie->endNote()) {
5923+
Note* nnote;
5924+
nnote = searchTieNote(n);
5925+
if (nnote == 0) {
5926+
if (!silent) {
5927+
LOGD("next note at %d track %zu for tie not found", s->tick().ticks(), track);
5928+
delete tie;
5929+
n->setTieFor(0);
59645930
}
5931+
} else {
5932+
tie->setEndNote(nnote);
5933+
nnote->setTieBack(tie);
59655934
}
5966-
// spanner with no end element can happen during copy/paste
5967-
for (Spanner* spanner : n->spannerFor()) {
5968-
if (spanner->endElement() == nullptr) {
5969-
n->removeSpannerFor(spanner);
5935+
}
5936+
// connect a glissando without initial note (old glissando format)
5937+
for (Spanner* spanner : n->spannerBack()) {
5938+
if (spanner->isGlissando() && !spanner->startElement()) {
5939+
Note* initialNote = Glissando::guessInitialNote(n->chord());
5940+
n->removeSpannerBack(spanner);
5941+
if (initialNote) {
5942+
spanner->setStartElement(initialNote);
5943+
spanner->setEndElement(n);
5944+
spanner->setTick(initialNote->chord()->tick());
5945+
spanner->setTick2(n->chord()->tick());
5946+
spanner->setTrack(n->track());
5947+
spanner->setTrack2(n->track());
5948+
spanner->setParent(initialNote);
5949+
initialNote->add(spanner);
5950+
} else {
59705951
delete spanner;
59715952
}
59725953
}
59735954
}
5955+
// spanner with no end element can happen during copy/paste
5956+
for (Spanner* spanner : n->spannerFor()) {
5957+
if (spanner->endElement() == nullptr) {
5958+
n->removeSpannerFor(spanner);
5959+
delete spanner;
5960+
}
5961+
}
5962+
}
5963+
};
5964+
5965+
SegmentType st = SegmentType::ChordRest;
5966+
for (Segment* s = m->first(st); s; s = s->next1(st)) {
5967+
for (track_idx_t track = 0; track < tracks; ++track) {
5968+
EngravingItem* e = s->element(track);
5969+
if (e == 0 || !e->isChord()) {
5970+
continue;
5971+
}
5972+
Chord* c = toChord(e);
5973+
connectTiesForChord(c, s, track);
59745974
for (Chord* gc : c->graceNotes()) {
5975+
connectTiesForChord(gc, s, track);
5976+
59755977
for (Note* n : gc->notes()) {
59765978
// spanner with no end element apparently happens when reading some 206 files
59775979
// (and possibly in other situations too)

src/engraving/dom/splitMeasure.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,6 @@ void MasterScore::splitMeasure(const Fraction& tick)
9696
}
9797
}
9898

99-
// Make sure ties to the beginning of the split measure are restored.
100-
std::vector<Tie*> ties;
101-
for (size_t track = 0; track < ntracks(); track++) {
102-
Chord* chord = measure->findChord(stick, static_cast<int>(track));
103-
if (chord) {
104-
for (Note* note : chord->notes()) {
105-
Tie* tie = note->tieBack();
106-
if (tie) {
107-
ties.push_back(tie->clone());
108-
}
109-
}
110-
}
111-
}
112-
11399
MeasureBase* nm = measure->next();
114100

115101
// create empty measures:
@@ -181,12 +167,6 @@ void MasterScore::splitMeasure(const Fraction& tick)
181167

182168
range.write(this, m1->tick());
183169

184-
// Restore ties to the beginning of the split measure.
185-
for (auto tie : ties) {
186-
tie->setEndNote(searchTieNote(tie->startNote()));
187-
undoAddElement(tie);
188-
}
189-
190170
for (auto i : sl) {
191171
Spanner* s = std::get<0>(i);
192172
Fraction t = std::get<1>(i);

src/engraving/dom/utils.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -872,47 +872,6 @@ Note* searchTieNote(const Note* note, const Segment* nextSegment, const bool dis
872872
return note2;
873873
}
874874

875-
//---------------------------------------------------------
876-
// searchTieNote114
877-
// search Note to tie to "note", tie to next note in
878-
// same voice
879-
//---------------------------------------------------------
880-
881-
Note* searchTieNote114(Note* note)
882-
{
883-
Note* note2 = 0;
884-
Chord* chord = note->chord();
885-
Segment* seg = chord->segment();
886-
Part* part = chord->part();
887-
track_idx_t strack = part->staves().front()->idx() * VOICES;
888-
track_idx_t etrack = strack + part->staves().size() * VOICES;
889-
890-
while ((seg = seg->next1(SegmentType::ChordRest))) {
891-
for (track_idx_t track = strack; track < etrack; ++track) {
892-
EngravingItem* e = seg->element(track);
893-
if (e == 0 || (!e->isChord()) || (e->track() != chord->track())) {
894-
continue;
895-
}
896-
Chord* c = toChord(e);
897-
staff_idx_t staffIdx = c->staffIdx() + c->staffMove();
898-
if (staffIdx != chord->staffIdx() + chord->staffMove()) { // cannot happen?
899-
continue;
900-
}
901-
for (Note* n : c->notes()) {
902-
if (n->pitch() == note->pitch()) {
903-
if (note2 == 0 || c->track() == chord->track()) {
904-
note2 = n;
905-
}
906-
}
907-
}
908-
}
909-
if (note2) {
910-
break;
911-
}
912-
}
913-
return note2;
914-
}
915-
916875
//---------------------------------------------------------
917876
// absStep
918877
/// Compute absolute step.

src/engraving/dom/utils.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ extern Segment* nextSeg1(Segment* s);
7575
extern Segment* prevSeg1(Segment* seg);
7676

7777
extern Note* searchTieNote(const Note* note, const Segment* nextSegment = nullptr, const bool disableOverRepeats = true);
78-
extern Note* searchTieNote114(Note* note);
7978

8079
extern int absStep(int pitch);
8180
extern int absStep(int tpc, int pitch);

0 commit comments

Comments
 (0)