@@ -250,14 +250,21 @@ bool StaveSharingLayout::isUnison(track_idx_t prevTrack, track_idx_t nextTrack,
250250 }
251251
252252 for (size_t i = 0 ; i < notes1.size (); ++i) {
253- if (!notes1[i]->isExactUnison (notes2[i])) {
253+ Note* n1 = notes1[i];
254+ Note* n2 = notes2[i];
255+
256+ if (!n1->isExactUnison (n2)) {
257+ return false ;
258+ }
259+
260+ if (!checkNoteSpannersForUnison (n1, n2)) {
254261 return false ;
255262 }
256263 }
257264 }
258265
259266 for (Segment* segment : ctx.allSegments ) {
260- if (!checkAnnotationsForSameVoice (segment, prevTrack, nextTrack, ctx )) {
267+ if (!checkAnnotationsForSameVoice (segment, prevTrack, nextTrack)) {
261268 return false ;
262269 }
263270 }
@@ -295,40 +302,52 @@ bool StaveSharingLayout::canGoToSameVoice(track_idx_t prevTrack, track_idx_t nex
295302
296303 Chord* c1 = toChord (cr1);
297304 Chord* c2 = toChord (cr2);
298- for (Note* n1 : c1->notes ()) {
299- for (Note* n2 : c2->notes ()) {
300- if (n2->pitch () > n1->pitch ()) {
305+
306+ const std::vector<Note*>& notes1 = c1->notes ();
307+ const std::vector<Note*>& notes2 = c2->notes ();
308+ if (notes1.size () != notes2.size ()) {
309+ return false ;
310+ }
311+
312+ for (size_t i = 0 ; i < notes1.size (); ++i) {
313+ Note* n1 = notes1[i];
314+ Note* n2 = notes2[i];
315+
316+ if (n2->pitch () > n1->pitch ()) {
317+ return false ;
318+ }
319+
320+ if (!n2->isExactUnison (n1)) {
321+ if (n2->pitch () == n1->pitch () || muse::contains (localUnisonNotes, n1)) {
301322 return false ;
302323 }
303324
304- if (!n2->isExactUnison (n1)) {
305- if (n2->pitch () == n1->pitch () || muse::contains (localUnisonNotes, n1)) {
306- return false ;
307- }
325+ continue ;
326+ }
308327
328+ if (!checkNoteSpannersForUnison (n1, n2)) {
329+ return false ;
330+ }
331+
332+ for (track_idx_t track : curTrackGroup) {
333+ if (track == prevTrack) {
309334 continue ;
310335 }
311-
312- for (track_idx_t track : curTrackGroup) {
313- if (track == prevTrack) {
314- continue ;
315- }
316- if (ChordRest* cr = toChordRest (segment->element (track)); cr && cr->isChord ()) {
317- for (Note* n : toChord (cr)->notes ()) {
318- if (!n2->isExactUnison (n)) {
319- return false ;
320- }
336+ if (ChordRest* cr = toChordRest (segment->element (track)); cr && cr->isChord ()) {
337+ for (Note* n : toChord (cr)->notes ()) {
338+ if (!n2->isExactUnison (n)) {
339+ return false ;
321340 }
322341 }
323342 }
324-
325- potentialUnisonNotes.push_back (n2);
326343 }
344+
345+ potentialUnisonNotes.push_back (n2);
327346 }
328347 }
329348
330349 for (Segment* segment : ctx.allSegments ) {
331- if (!checkAnnotationsForSameVoice (segment, prevTrack, nextTrack, ctx )) {
350+ if (!checkAnnotationsForSameVoice (segment, prevTrack, nextTrack)) {
332351 return false ;
333352 }
334353 }
@@ -340,8 +359,7 @@ bool StaveSharingLayout::canGoToSameVoice(track_idx_t prevTrack, track_idx_t nex
340359 return true ;
341360}
342361
343- bool StaveSharingLayout::checkAnnotationsForSameVoice (Segment* segment, track_idx_t prevTrack, track_idx_t nextTrack,
344- StaveSharingContext& ctx)
362+ bool StaveSharingLayout::checkAnnotationsForSameVoice (Segment* segment, track_idx_t prevTrack, track_idx_t nextTrack)
345363{
346364 std::multimap<ElementType, EngravingItem*> annotationsOnPrevTrack;
347365 std::multimap<ElementType, EngravingItem*> annotationsOnNextTrack;
@@ -379,6 +397,65 @@ bool StaveSharingLayout::checkAnnotationsForSameVoice(Segment* segment, track_id
379397 return true ;
380398}
381399
400+ bool StaveSharingLayout::checkNoteSpannersForUnison (const Note* note1, const Note* note2)
401+ {
402+ const Tie* tieBack1 = note1->tieBack ();
403+ const Tie* tieBack2 = note2->tieBack ();
404+ if (bool (tieBack1) != bool (tieBack2)) {
405+ return false ;
406+ }
407+ if (tieBack1 && bool (tieBack1->startElement ()) != bool (tieBack2->startElement ())) {
408+ return false ;
409+ }
410+
411+ const Tie* tieFor1 = note1->tieFor ();
412+ const Tie* tieFor2 = note2->tieFor ();
413+ if (bool (tieFor1) != bool (tieFor2)) {
414+ return false ;
415+ }
416+ if (tieFor1 && bool (tieFor1->startElement ()) != bool (tieFor2->startElement ())) {
417+ return false ;
418+ }
419+
420+ const std::vector<Spanner*>& spannerBack1 = note1->spannerBack ();
421+ const std::vector<Spanner*>& spannerBack2 = note2->spannerBack ();
422+ if (spannerBack1.size () != spannerBack2.size ()) {
423+ return false ;
424+ }
425+
426+ for (Spanner* sp1 : spannerBack1) {
427+ auto i = std::find_if (spannerBack2.begin (), spannerBack2.end (), [sp1](Spanner* sp2) { return sp2->type () == sp1->type (); });
428+ if (i == spannerBack2.end ()) {
429+ return false ;
430+ }
431+
432+ Spanner* sp2 = *i;
433+ if (bool (sp1->startElement ()) != bool (sp2->startElement ())) {
434+ return false ;
435+ }
436+ }
437+
438+ const std::vector<Spanner*>& spannerFor1 = note1->spannerFor ();
439+ const std::vector<Spanner*>& spannerFor2 = note2->spannerFor ();
440+ if (spannerFor1.size () != spannerFor2.size ()) {
441+ return false ;
442+ }
443+
444+ for (Spanner* sp1 : spannerFor1) {
445+ auto i = std::find_if (spannerFor2.begin (), spannerFor2.end (), [sp1](Spanner* sp2) { return sp2->type () == sp1->type (); });
446+ if (i == spannerFor2.end ()) {
447+ return false ;
448+ }
449+
450+ Spanner* sp2 = *i;
451+ if (bool (sp1->endElement ()) != bool (sp2->endElement ())) {
452+ return false ;
453+ }
454+ }
455+
456+ return true ;
457+ }
458+
382459bool StaveSharingLayout::canGoToSameStave (track_idx_t prevTrack, track_idx_t nextTrack,
383460 StaveSharingContext& ctx)
384461{
@@ -474,6 +551,24 @@ void StaveSharingLayout::disconnectAll(SharedPart* p, StaveSharingContext& ctx)
474551 if (cr->isChord ()) {
475552 for (Note* note : toChord (cr)->notes ()) {
476553 EngravingItem::disconnectAllOriginItems (note);
554+
555+ if (Tie* tieFor = note->tieFor (); tieFor && !tieFor->endNote ()) { // if it does have endNote it will be disconnected when we process that note
556+ EngravingItem::disconnectAllOriginItems (tieFor);
557+ }
558+
559+ for (Spanner* spannerFor : note->spannerFor ()) {
560+ if (!spannerFor->endElement ()) {
561+ EngravingItem::disconnectAllOriginItems (spannerFor); // if it does have endElement it will be disconnected when we process that note
562+ }
563+ }
564+
565+ if (Tie* tieBack = note->tieBack ()) {
566+ EngravingItem::disconnectAllOriginItems (tieBack);
567+ }
568+
569+ for (Spanner* spannerBack : note->spannerBack ()) {
570+ EngravingItem::disconnectAllOriginItems (spannerBack);
571+ }
477572 }
478573 }
479574 }
@@ -567,7 +662,7 @@ void StaveSharingLayout::makeSharedChordRests(SharedPart* p, StaveSharingContext
567662 Chord* sharedChord = toChord (sharedCR);
568663 Note* sharedNote = nullptr ;
569664 for (Note* n : sharedChord->notes ()) {
570- if (n->pitch () == originNote-> pitch ( )) {
665+ if (n->isExactUnison ( originNote)) {
571666 sharedNote = n;
572667 break ;
573668 }
@@ -581,7 +676,88 @@ void StaveSharingLayout::makeSharedChordRests(SharedPart* p, StaveSharingContext
581676 }
582677
583678 EngravingItem::connectSharedItem (sharedNote, originNote);
679+
680+ makeSharedTiesAndNoteSpanners (originNote, sharedNote);
681+ }
682+ }
683+ }
684+
685+ void StaveSharingLayout::makeSharedTiesAndNoteSpanners (Note* originNote, Note* sharedNote)
686+ {
687+ Score* score = originNote->score ();
688+
689+ Tie* tieBack = originNote->tieBack ();
690+ if (tieBack) {
691+ Tie* sharedTieBack = sharedNote->tieBack ();
692+ if (!sharedTieBack) {
693+ sharedTieBack = toTie (tieBack->clone ());
694+ Note* sharedStartNote = tieBack->startNote () ? toNote (tieBack->startNote ()->sharedItem ()) : nullptr ;
695+ sharedTieBack->setNoteSpan (sharedStartNote, sharedNote);
696+
697+ score->undoAddElement (sharedTieBack);
698+ }
699+
700+ EngravingItem::connectSharedItem (sharedTieBack, tieBack);
701+ }
702+
703+ Tie* tieFor = originNote->tieFor ();
704+ if (tieFor && !tieFor->endNote ()) { // If it does have an end note we add it when we process the end note
705+ Tie* sharedTieFor = sharedNote->tieFor ();
706+ if (!sharedTieFor) {
707+ sharedTieFor = toTie (sharedTieFor->clone ());
708+ sharedTieFor->setNoteSpan (sharedNote, nullptr );
709+
710+ score->undoAddElement (sharedTieFor);
711+ }
712+
713+ EngravingItem::connectSharedItem (sharedTieFor, tieFor);
714+ }
715+
716+ const std::vector<Spanner*>& originSpannerBack = originNote->spannerBack ();
717+ const std::vector<Spanner*>& sharedSpannerBack = sharedNote->spannerBack ();
718+
719+ for (Spanner* spanner : originSpannerBack) {
720+ Spanner* sharedSpanner = nullptr ;
721+ for (Spanner* sp : sharedSpannerBack) {
722+ if (sp && sp->type () == spanner->type ()) {
723+ sharedSpanner = sp;
724+ break ;
725+ }
584726 }
727+
728+ if (!sharedSpanner) {
729+ sharedSpanner = toSpanner (spanner->clone ());
730+ Note* startNote = spanner->startElement () ? toNote (spanner->startElement ()->sharedItem ()) : nullptr ;
731+ sharedSpanner->setNoteSpan (startNote, sharedNote);
732+
733+ score->undoAddElement (sharedSpanner);
734+ }
735+
736+ EngravingItem::connectSharedItem (sharedSpanner, spanner);
737+ }
738+
739+ for (Spanner* spanner : originNote->spannerFor ()) {
740+ if (spanner->endElement ()) { // If it does have an end note we add it when we process the end note
741+ continue ;
742+ }
743+
744+ Spanner* sharedSpanner = nullptr ;
745+ for (Spanner* sp : sharedNote->spannerFor ()) {
746+ if (sp->type () == spanner->type ()) {
747+ sharedSpanner = sp;
748+ break ;
749+ }
750+ }
751+
752+ if (!sharedSpanner) {
753+ sharedSpanner = toSpanner (spanner->clone ());
754+ sharedSpanner->setTrack (sharedNote->track ());
755+ sharedSpanner->setStartElement (sharedNote);
756+
757+ score->undoAddElement (sharedSpanner);
758+ }
759+
760+ EngravingItem::connectSharedItem (sharedSpanner, spanner);
585761 }
586762}
587763
@@ -663,10 +839,6 @@ void StaveSharingLayout::makeSharedAnnotations(SharedPart* p, StaveSharingContex
663839 }
664840}
665841
666- bool StaveSharingLayout::annotationRefersToBothVoices (EngravingItem* sharedAnnotation, StaveSharingContext& ctx)
667- {
668- }
669-
670842void StaveSharingLayout::cleanup (SharedPart* p, StaveSharingContext& ctx)
671843{
672844 Score* score = ctx.score ;
@@ -714,6 +886,26 @@ void StaveSharingLayout::cleanup(SharedPart* p, StaveSharingContext& ctx)
714886 Chord* c = toChord (cr);
715887 std::vector<Note*> notes = c->notes (); // copy because may be removed
716888 for (Note* note : notes) {
889+ if (Tie* tieBack = note->tieBack (); tieBack && tieBack->originItems ().empty ()) {
890+ score->undoRemoveElement (tieBack);
891+ }
892+
893+ for (Spanner* sp : note->spannerBack ()) {
894+ if (sp->originItems ().empty ()) {
895+ score->undoRemoveElement (sp);
896+ }
897+ }
898+
899+ if (Tie* tieFor = note->tieFor (); tieFor && !tieFor->endElement () && tieFor->originItems ().empty ()) {
900+ score->undoRemoveElement (tieFor);
901+ }
902+
903+ for (Spanner* sp : note->spannerFor ()) {
904+ if (!sp->endElement () && sp->originItems ().empty ()) {
905+ score->undoRemoveElement (sp);
906+ }
907+ }
908+
717909 if (note->originItems ().empty ()) {
718910 score->undoRemoveElement (note);
719911 }
0 commit comments