Skip to content

Commit

Permalink
Fix #15726 (Glissando & Bends): Some elements are lost when changing …
Browse files Browse the repository at this point in the history
…time signature
  • Loading branch information
pacebes committed Jan 8, 2025
1 parent 31c4159 commit 82aa1be
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/engraving/dom/note.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,24 @@ Note::Note(const Note& n, bool link)
}
}

//
// Add For and Back spanners
//
for (Spanner* sp : n.spannerFor()) {
if ((sp->isGuitarBend()) || (sp->isGlissando())) {
Spanner* csp = toSpanner(sp->clone());
csp->setNoteSpan(this, toNote(csp->endElement()));
addSpannerFor(csp);
}
}
for (Spanner* sp : n.spannerBack()) {
if ((sp->isGuitarBend()) || (sp->isGlissando())) {
Spanner* csp = toSpanner(sp->clone());
csp->setNoteSpan(toNote(csp->startElement()), this);
addSpannerBack(csp);
}
}

m_playEvents = n.m_playEvents;

if (n.laissezVib()) {
Expand Down
94 changes: 93 additions & 1 deletion src/engraving/dom/range.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
Expand Down Expand Up @@ -194,6 +195,10 @@ void TrackList::append(EngravingItem* e)
}
if (e->isChord()) {
Chord* chord = toChord(e);

// Map between Chords and clonned chords
m_clonedChord.insert(std::make_pair(chord, toChord(element)));

bool akkumulateChord = true;
for (Note* n : chord->notes()) {
if (!n->tieBack() || !n->tieBack()->generated()) {
Expand Down Expand Up @@ -288,6 +293,7 @@ bool TrackList::truncate(const Fraction& f)
void TrackList::read(const Segment* fs, const Segment* es)
{
Fraction tick = fs->tick();
m_clonedChord.clear();

const Segment* s;
for (s = fs; s && (s != es); s = s->next1()) {
Expand Down Expand Up @@ -353,6 +359,10 @@ void TrackList::read(const Segment* fs, const Segment* es)
continue;
}
Chord* chord = toChord(e);

// Rebuild Spanner's start and end Notes
rebuildSpannerStartEndNotes(chord);

for (Note* n1 : chord->notes()) {
Tie* tie = n1->tieFor();
if (!tie) {
Expand Down Expand Up @@ -380,6 +390,7 @@ void TrackList::read(const Segment* fs, const Segment* es)
}
}
}
m_clonedChord.clear();
}

//---------------------------------------------------------
Expand Down Expand Up @@ -504,11 +515,12 @@ Tuplet* TrackList::writeTuplet(Tuplet* parent, Tuplet* tuplet, Measure*& measure
// rewrite notes into measure list measure
//---------------------------------------------------------

bool TrackList::write(Score* score, const Fraction& tick) const
bool TrackList::write(Score* score, const Fraction& tick)
{
if ((m_track % VOICES) && size() == 1 && at(0)->isRest()) { // don’t write rests in voice > 0
return true;
}
m_clonedChord.clear();
Measure* measure = score->tick2measure(tick);
Measure* m = measure;
Fraction remains = m->endTick() - tick;
Expand Down Expand Up @@ -573,6 +585,9 @@ bool TrackList::write(Score* score, const Fraction& tick) const
remains -= gd;

if (cr->isChord()) {
// Map between Chords and clonned chords
m_clonedChord.insert(std::make_pair(toChord(e), toChord(cr)));

TremoloTwoChord* tremolo = toChord(cr)->tremoloTwoChord();
if (!firstpart && tremolo) { // remove partial two-note tremolo
if (toChord(e)->tremoloTwoChord()->chord1() == toChord(e)) {
Expand Down Expand Up @@ -633,6 +648,18 @@ bool TrackList::write(Score* score, const Fraction& tick) const
seg->add(ne);
}
}

//
// Rebuild Spanner's Start and End Notes
//
for (Segment* s = measure->first(); s; s = s->next1()) {
EngravingItem* e = s->element(m_track);
if (e && e->isChord()) {
rebuildSpannerStartEndNotes(toChord(e));
}
}
m_clonedChord.clear();

//
// connect ties from measure->first() to segment
//
Expand Down Expand Up @@ -844,3 +871,68 @@ void TrackList::dump() const
}
}
}

//---------------------------------------------------------
// clonedNote
//---------------------------------------------------------
Note* TrackList::clonedNote(Note* srcNote)
{
Note* cNote = nullptr;
Chord* srcChord = srcNote->chord();
Chord* cChord = m_clonedChord[srcChord];

if ((srcChord) && (cChord)) {
int noteSrcPosition = 0;
int noteClonedPosition = 0;
bool noteFound = false;
// We presume notes where created in the same order in the srcChord and clonedChord
// Note position in sourceChord
for (Note* n : srcChord->notes()) {
++noteSrcPosition;
if (srcNote == n) {
noteFound = true;
break;
}
}
if (noteFound) {
// Note in clonedChord
for (Note* n : cChord->notes()) {
++noteClonedPosition;
if (noteClonedPosition == noteSrcPosition) {
cNote = n;
break;
}
}
}
}
return cNote;
}

//---------------------------------------------------------
// rebuildSpannerStartEndNotes
//---------------------------------------------------------
void TrackList::rebuildSpannerStartEndNotes(Chord* srcChord)
{
// Rebuild Spanner's start and end Notes
for (Note* n1 : srcChord->notes()) {
for (Spanner* sp : n1->spannerFor()) {
if ((sp->isGuitarBend()) || (sp->isGlissando())) {
Note* endClonedNote = clonedNote(toNote(sp->endElement()));

if (endClonedNote) {
sp->setNoteSpan(n1, endClonedNote);
}
}
}

for (Spanner* sp : n1->spannerBack()) {
if ((sp->isGuitarBend()) || (sp->isGlissando())) {
Note* startClonedNote = clonedNote(toNote(sp->startElement()));

if (startClonedNote) {
sp->setNoteSpan(startClonedNote, n1);
}
}
}
}
}
7 changes: 6 additions & 1 deletion src/engraving/dom/range.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Segment;
class Spanner;
class ScoreRange;
class ChordRest;
class Chord;
class Note;
class Score;

//---------------------------------------------------------
Expand All @@ -60,7 +62,7 @@ class TrackList : public std::vector<EngravingItem*>
void setTrack(track_idx_t val) { m_track = val; }

void read(const Segment* fs, const Segment* ls);
bool write(Score*, const Fraction&) const;
bool write(Score*, const Fraction&);

void appendGap(const Fraction&, Score* score);
bool truncate(const Fraction&);
Expand All @@ -72,10 +74,13 @@ class TrackList : public std::vector<EngravingItem*>
void append(EngravingItem*);
void appendTuplet(Tuplet* srcTuplet, Tuplet* dstTuplet);
void combineTuplet(Tuplet* dst, Tuplet* src);
Note* clonedNote(Note* srcNote);
void rebuildSpannerStartEndNotes(Chord* srcChord);

Fraction m_duration;
ScoreRange* m_range = nullptr;
track_idx_t m_track = 0;
std::map<Chord*, Chord*> m_clonedChord;
};

//---------------------------------------------------------
Expand Down

0 comments on commit 82aa1be

Please sign in to comment.