diff --git a/libmscore/barline.cpp b/libmscore/barline.cpp index fc661697bb62d..ba770c917e33a 100644 --- a/libmscore/barline.cpp +++ b/libmscore/barline.cpp @@ -388,9 +388,13 @@ int nextVisibleSpannedStaff(const BarLine* bl) int nstaves = score->nstaves(); int staffIdx = bl->staffIdx(); Segment* segment = bl->segment(); - for (int i = staffIdx + 1; i < nstaves; ++i) { + Measure* nm = bl->measure()->nextMeasure(); + for (int i = staffIdx + 1; i < nstaves; ++i) { Staff* s = score->staff(i); - if (s->part()->show() && bl->measure()->visible(i)) + if (s->part()->show() && (bl->measure()->visible(i) || // span bar line if measure is visible + (segment && segment->isEndBarLineType() && // or if this is a measure's End Bar Line and... + ((nm ? nm->visible(i) : false) && (nm ? nm->system() == bl->measure()->system() : false) // ...next measure is visible in system + || bl->measure()->isCutawayClef(i))))) // ...or measure has Courtesy Clef return i; BarLine* nbl = toBarLine(segment->element(i * VOICES)); if (!nbl || !nbl->spanStaff()) @@ -1192,7 +1196,7 @@ void BarLine::endEditDrag(EditData& ed) newSpanTo = 0; } - bool localDrag = ed.control() || segment()->isBarLine(); + bool localDrag = ed.control() || segment()->isBarLineType(); if (localDrag) { Segment* s = segment(); for (int staffIdx = staffIdx1; staffIdx < staffIdx2; ++staffIdx) { diff --git a/libmscore/measure.cpp b/libmscore/measure.cpp index e80d460045708..8cf0ab4317b26 100644 --- a/libmscore/measure.cpp +++ b/libmscore/measure.cpp @@ -261,8 +261,16 @@ Measure::Measure(const Measure& m) void Measure::layoutStaffLines() { - for (MStaff* ms : _mstaves) - ms->lines()->layout(); + int staffIdx = 0; + for (MStaff* ms : _mstaves) { + if (isCutawayClef(staffIdx) && (score()->staff(staffIdx)->cutaway() || !visible(staffIdx))) + // draw short staff lines for a courtesy clef on a hidden measure + ms->lines()->layoutPartialWidth(width(), 4.0, true); + else + // normal staff lines + ms->lines()->layout(); + staffIdx += 1; + } } //--------------------------------------------------------- @@ -2586,10 +2594,10 @@ void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all) int nstaves = score()->nstaves(); for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { - if (!all && !(visible(staffIdx) && score()->staff(staffIdx)->show())) + if (!all && !score()->staff(staffIdx)->show()) continue; MStaff* ms = _mstaves[staffIdx]; - func(data, ms->lines()); + // show spacers and measure number even on invisible measures (TO DO: also include Staff Type Changes) if (ms->vspacerUp()) func(data, ms->vspacerUp()); if (ms->vspacerDown()) @@ -2598,6 +2606,9 @@ void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all) func(data, ms->noText()); if (ms->mmRangeText()) func(data, ms->mmRangeText()); + // show staff lines only if measure is visible OR if it only has a courtesy clef for cutaway/ossias (short staff lines will be drawn if needed) + if (visible(staffIdx) || isCutawayClef(staffIdx)) + func(data, ms->lines()); } for (Segment* s = first(); s; s = s->next()) { @@ -2826,6 +2837,7 @@ bool Measure::isEmpty(int staffIdx) const { int strack; int etrack; + bool hasStaves = score()->staff(staffIdx)->part()->staves()->size() > 1; if (staffIdx < 0) { strack = 0; etrack = score()->nstaves() * VOICES; @@ -2839,6 +2851,19 @@ bool Measure::isEmpty(int staffIdx) const Element* e = s->element(track); if (e && !e->isRest()) return false; + // Check for cross-staff chords + if (hasStaves) { + if (strack >= VOICES) { + e = s->element(track - VOICES); + if (e && !e->isRest() && e->vStaffIdx() == staffIdx) + return false; + } + if (etrack < score()->nstaves() * VOICES) { + e = s->element(track + VOICES); + if (e && !e->isRest() && e->vStaffIdx() == staffIdx) + return false; + } + } } for (Element* a : s->annotations()) { if (!a || a->systemFlag() || !a->visible() || a->isFermata()) @@ -2851,6 +2876,37 @@ bool Measure::isEmpty(int staffIdx) const return true; } +//--------------------------------------------------------- +// isCourtesyClef +// Check for empty measure with only +// a Courtesy Clef before the End Bar Line +//--------------------------------------------------------- + +bool Measure::isCutawayClef(int staffIdx) const + { + if (!isEmpty(staffIdx)) + return false; + int strack; + int etrack; + if (staffIdx < 0) { + strack = 0; + etrack = score()->nstaves() * VOICES; + } + else { + strack = staffIdx * VOICES; + etrack = strack + VOICES; + } + Segment* s = last()->prev(); + if (!s) + return false; + for (int track = strack; track < etrack; ++track) { + Element* e = s->element(track); + if (e && e->isClef() && (nextMeasure()->system() == system() || toClef(e)->showCourtesy())) + return true; + } + return false; + } + //--------------------------------------------------------- // isFullMeasureRest // Check for an empty measure, filled with full measure diff --git a/libmscore/measure.h b/libmscore/measure.h index 58bd553177229..ffe4634dc729e 100644 --- a/libmscore/measure.h +++ b/libmscore/measure.h @@ -224,6 +224,7 @@ class Measure final : public MeasureBase { void checkMultiVoices(int staffIdx); bool hasVoice(int track) const; bool isEmpty(int staffIdx) const; + bool isCutawayClef(int staffIdx) const; bool isFullMeasureRest() const; bool isRepeatMeasure(const Staff* staff) const; bool visible(int staffIdx) const; diff --git a/libmscore/segment.cpp b/libmscore/segment.cpp index 9e4055e3325d5..a0c1acb2d0989 100644 --- a/libmscore/segment.cpp +++ b/libmscore/segment.cpp @@ -1165,13 +1165,29 @@ void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all) { for (int track = 0; track < score()->nstaves() * VOICES; ++track) { int staffIdx = track/VOICES; - if (!all && !(measure()->visible(staffIdx) && score()->staff(staffIdx)->show())) { + if (!all && !(score()->staff(staffIdx)->show())) { track += VOICES - 1; continue; } Element* e = element(track); if (e == 0) continue; + // if measure is not visible, handle visible End Bar Lines and Courtesy Clefs in certain conditions (for ossias and cutaway): + if (!measure()->visible(staffIdx)) { + if (isEndBarLineType()) { + if (!measure()->nextMeasure()) + continue; // skip EndBarLines if next measure == NULL + else if (!measure()->isCutawayClef(staffIdx) && + !(measure()->nextMeasure()->visible(staffIdx) && measure()->nextMeasure()->system() == measure()->system())) + continue; // skip if not on courtesy clef measures and if next measure in system is not visible + } + else if (isClefType()) { + if (!measure()->isCutawayClef(staffIdx)) + continue; // skip clefs except for courtesy clefs at the end of invisible measures + } + else + continue; + } e->scanElements(data, func, all); } for (Element* e : annotations()) { diff --git a/libmscore/stafflines.cpp b/libmscore/stafflines.cpp index 44e344844a14a..9a11b98dae715 100644 --- a/libmscore/stafflines.cpp +++ b/libmscore/stafflines.cpp @@ -127,6 +127,51 @@ void StaffLines::layoutForWidth(qreal w) } } +//--------------------------------------------------------- +// layoutPartialWidth +//--------------------------------------------------------- + +void StaffLines::layoutPartialWidth(qreal w, qreal wPartial, bool alignRight) + { + const Staff* s = staff(); + qreal _spatium = spatium(); + wPartial *= spatium(); + qreal dist = _spatium; + setPos(QPointF(0.0, 0.0)); + int _lines; + if (s) { + setMag(s->mag(measure()->tick())); + setColor(s->color(measure()->tick())); + const StaffType* st = s->staffType(measure()->tick()); + dist *= st->lineDistance().val(); + _lines = st->lines(); + rypos() = st->yoffset().val() * _spatium; + } + else { + _lines = 5; + setColor(MScore::defaultColor); + } + lw = score()->styleS(Sid::staffLineWidth).val() * _spatium; + qreal x1 = pos().x(); + qreal x2 = x1 + w; + qreal y = pos().y(); + bbox().setRect(x1, -lw * .5 + y, w, (_lines-1) * dist + lw); + + if (_lines == 1) { + qreal extraSize = _spatium; + bbox().adjust(0, -extraSize, 0, extraSize); + } + + lines.clear(); + for (int i = 0; i < _lines; ++i) { + if (alignRight) + lines.push_back(QLineF(x2-wPartial, y, x2, y)); + else + lines.push_back(QLineF(x1, y, x1 + wPartial, y)); + y += dist; + } + } + //--------------------------------------------------------- // draw //--------------------------------------------------------- diff --git a/libmscore/stafflines.h b/libmscore/stafflines.h index 92d54b6bbd99f..b60f2e34f125b 100644 --- a/libmscore/stafflines.h +++ b/libmscore/stafflines.h @@ -38,6 +38,7 @@ class StaffLines final : public Element { Measure* measure() const { return (Measure*)parent(); } qreal y1() const; void layoutForWidth(qreal width); + void layoutPartialWidth(qreal w, qreal wPartial, bool alignLeft); }; } // namespace Ms