Skip to content

Commit 2192080

Browse files
committed
Handle cross-system hopos correctly
1 parent 8fc5144 commit 2192080

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

src/engraving/dom/hammeronpulloff.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ void HammerOnPullOffSegment::updateHopoText()
101101
EngravingItem* endEl = hammerOnPullOff()->endElement();
102102
endChord = endEl && endEl->isChord() ? toChord(endEl) : nullptr;
103103
} else {
104+
// If the segment doesn't end in this system, the endChord is the first chord of next system
104105
ChordRest* lastCR = system()->lastChordRest(track());
106+
if (lastCR) {
107+
lastCR = toChordRest(lastCR->segment()->next1WithElemsOnTrack(track())->element(track()));
108+
}
105109
endChord = lastCR && lastCR->isChord() ? toChord(lastCR) : nullptr;
106110
}
107111

src/engraving/dom/segment.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,17 @@ Segment* Segment::next1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segTyp
359359
return next;
360360
}
361361

362+
Segment* Segment::next1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType) const
363+
{
364+
Segment* next = next1(segType);
365+
366+
while (next && !next->hasElements(trackIdx, trackIdx)) {
367+
next = next->next1(segType);
368+
}
369+
370+
return next;
371+
}
372+
362373
Segment* Segment::next1MM(SegmentType types) const
363374
{
364375
for (Segment* s = next1MM(); s; s = s->next1MM()) {

src/engraving/dom/segment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class Segment final : public EngravingItem
101101
Segment* next1(SegmentType) const;
102102
Segment* next1ChordRestOrTimeTick() const;
103103
Segment* next1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType = SegmentType::ChordRest) const;
104+
Segment* next1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
104105
Segment* next1MM(SegmentType) const;
105106

106107
Segment* prev1() const;

src/engraving/rendering/score/tlayout.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3259,7 +3259,9 @@ void TLayout::layoutHammerOnPullOffSegment(HammerOnPullOffSegment* item, LayoutC
32593259
// The layout of the slur has already been done. Here we layout the H/P letters.
32603260
item->updateHopoText();
32613261

3262-
Skyline& sk = item->system()->staff(item->staffIdx())->skyline();
3262+
System* system = item->system();
3263+
Fraction systemEndTick = system->endTick();
3264+
Skyline& sk = system->staff(item->staffIdx())->skyline();
32633265

32643266
for (HammerOnPullOffText* hopoText : item->hopoText()) {
32653267
bool above = hopoText->placeAbove();
@@ -3270,8 +3272,22 @@ void TLayout::layoutHammerOnPullOffSegment(HammerOnPullOffSegment* item, LayoutC
32703272
hopoText->setAlign(align);
32713273
layoutItem(hopoText, ctx);
32723274

3273-
double startX = hopoText->startChord()->systemPos().x() + hopoText->startChord()->upNote()->headWidth();
3274-
double endX = hopoText->endChord()->systemPos().x();
3275+
const Chord* startChord = hopoText->startChord();
3276+
const Chord* endChord = hopoText->endChord();
3277+
double startX = startChord->systemPos().x() + startChord->upNote()->headWidth();
3278+
double endX = startX;
3279+
if (endChord->tick() < systemEndTick) {
3280+
endX = endChord->systemPos().x();
3281+
} else {
3282+
// The last endChord of this segment is in next system. Use end barline instead.
3283+
Measure* lastMeas = system->lastMeasure();
3284+
for (Segment* seg = lastMeas->last(); seg; seg = seg->prev()) {
3285+
if (seg->isType(SegmentType::BarLineType)) {
3286+
endX = seg->systemPos().x();
3287+
break;
3288+
}
3289+
}
3290+
}
32753291
double centerX = 0.5 * (startX + endX);
32763292

32773293
double vertPadding = 0.5 * item->spatium();
@@ -3281,8 +3297,8 @@ void TLayout::layoutHammerOnPullOffSegment(HammerOnPullOffSegment* item, LayoutC
32813297
y += above ? -vertPadding : vertPadding;
32823298
y = above ? std::min(y, -vertPadding) : std::max(y, item->staff()->staffHeight(item->tick()) + vertPadding);
32833299

3284-
Note* startNote = above ? hopoText->startChord()->upNote() : hopoText->startChord()->downNote();
3285-
Note* endNote = above ? hopoText->endChord()->upNote() : hopoText->endChord()->downNote();
3300+
Note* startNote = above ? startChord->upNote() : startChord->downNote();
3301+
Note* endNote = above ? endChord->upNote() : endChord->downNote();
32863302
double yNoteLimit = above ? std::min(startNote->y(), endNote->y()) - 2 * vertPadding
32873303
: std::max(startNote->y(), endNote->y()) + 2 * vertPadding;
32883304
y = above ? std::min(y, yNoteLimit) : std::max(y, yNoteLimit);

0 commit comments

Comments
 (0)