From 0819633fb943c0d333d94e549140a5c2102aef7d Mon Sep 17 00:00:00 2001 From: Marc Sabatella Date: Fri, 3 Jul 2020 12:11:03 -0600 Subject: [PATCH] fix #185056: hard to enter notes above/below staff + collect_artifacts Resolves: https://musescore.org/en/node/185056 Currently, when you click to enter a note in note input mode, and you click a location between two staves or systems, we try to guess which you mean using a simple split point located half way between the staves or systems. This makes it hard to enter notes far above or below the staff, because at some point we think you mean a different staff. This comes up all the time for piano music and also guitar, especially guitar+tab. My fix here is simple, I prefer the current system and staff. Current meaning, the one where the note input cursor is. I let this staff take 75% of the stave above and below, instead of only 50%. Thus, clicking far above/below the current staff will still enter notes onto that staff until you get much closer to the adjacent staff. The code is based on existing code that already does the same thing when choosing which *system* (and hence measure) to use. This code exists for things like dragging line handles. One issue is that the existing code actually went all out in preferring a system - claiming *all* of the space up until the next system. So I modified that existing code to take an additional parameter to control the spacing factor for preferred staves, defaulting to 1.0 so the exisitng use cases are unaffected (and I checked the math carefully to be sure the effect is the same). --- libmscore/score.cpp | 43 +++++++++++++++++++++++++++++++++++-------- libmscore/score.h | 4 ++-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/libmscore/score.cpp b/libmscore/score.cpp index c16f86a77ece3..3b572faa0ff5a 100644 --- a/libmscore/score.cpp +++ b/libmscore/score.cpp @@ -907,7 +907,7 @@ Page* Score::searchPage(const QPointF& p) const /// \returns List of found systems. //--------------------------------------------------------- -QList Score::searchSystem(const QPointF& pos, const System* preferredSystem, qreal spacingFactor) const +QList Score::searchSystem(const QPointF& pos, const System* preferredSystem, qreal spacingFactor, qreal preferredSpacingFactor) const { QList systems; Page* page = searchPage(pos); @@ -929,13 +929,15 @@ QList Score::searchSystem(const QPointF& pos, const System* preferredSy if ((ii == n) || (ns == 0)) y2 = page->height(); else { + qreal currentSpacingFactor; qreal sy2 = s->y() + s->bbox().height(); if (s == preferredSystem) - y2 = ns->y(); + currentSpacingFactor = preferredSpacingFactor; //y2 = ns->y(); else if (ns == preferredSystem) - y2 = sy2; + currentSpacingFactor = 1.0 - preferredSpacingFactor; //y2 = sy2; else - y2 = sy2 + (ns->y() - sy2) * spacingFactor; + currentSpacingFactor = spacingFactor; + y2 = sy2 + (ns->y() - sy2) * currentSpacingFactor; } if (y < y2) { systems.append(s); @@ -957,9 +959,9 @@ QList Score::searchSystem(const QPointF& pos, const System* preferredSy /// space to measures in this system when searching. //--------------------------------------------------------- -Measure* Score::searchMeasure(const QPointF& p, const System* preferredSystem, qreal spacingFactor) const +Measure* Score::searchMeasure(const QPointF& p, const System* preferredSystem, qreal spacingFactor, qreal preferredSpacingFactor) const { - QList systems = searchSystem(p, preferredSystem, spacingFactor); + QList systems = searchSystem(p, preferredSystem, spacingFactor, preferredSpacingFactor); for (System* system : systems) { qreal x = p.x() - system->canvasPos().x(); for (MeasureBase* mb : system->measures()) { @@ -1038,7 +1040,22 @@ static Segment* getNextValidInputSegment(Segment* s, int track, int voice) bool Score::getPosition(Position* pos, const QPointF& p, int voice) const { - Measure* measure = searchMeasure(p); + System* preferredSystem = nullptr; + int preferredStaffIdx = -1; + const qreal spacingFactor = 0.5; + const qreal preferredSpacingFactor = 0.75; + if (noteEntryMode() && inputState().staffGroup() != StaffGroup::TAB) { + // for non-tab staves, prefer the current system & staff + // this makes it easier to add notes far above or below the staff + // not helpful for tab since notes are not entered above or below + Segment* seg = inputState().segment(); + if (seg) + preferredSystem = seg->system(); + int track = inputState().track(); + if (track >= 0) + preferredStaffIdx = track >> 2; + } + Measure* measure = searchMeasure(p, preferredSystem, spacingFactor, preferredSpacingFactor); if (measure == 0) return false; @@ -1058,6 +1075,7 @@ bool Score::getPosition(Position* pos, const QPointF& p, int voice) const SysStaff* ss = system->staff(pos->staffIdx); if (!ss->show()) continue; + int nidx = -1; SysStaff* nstaff = 0; // find next visible staff @@ -1070,12 +1088,21 @@ bool Score::getPosition(Position* pos, const QPointF& p, int voice) const nstaff = 0; continue; } + if (i == preferredStaffIdx) + nidx = i; break; } if (nstaff) { + qreal currentSpacingFactor; + if (pos->staffIdx == preferredStaffIdx) + currentSpacingFactor = preferredSpacingFactor; + else if (nidx == preferredStaffIdx) + currentSpacingFactor = 1.0 - preferredSpacingFactor; + else + currentSpacingFactor = spacingFactor; qreal s1y2 = ss->bbox().bottom(); - sy2 = system->page()->canvasPos().y() + s1y2 + (nstaff->bbox().y() - s1y2) * .5; + sy2 = system->page()->canvasPos().y() + s1y2 + (nstaff->bbox().y() - s1y2) * currentSpacingFactor; } else sy2 = system->page()->canvasPos().y() + system->page()->height() - system->pagePos().y(); // system->height(); diff --git a/libmscore/score.h b/libmscore/score.h index 34ae90ecbc313..a2a1bd42aeb45 100644 --- a/libmscore/score.h +++ b/libmscore/score.h @@ -967,8 +967,8 @@ class Score : public QObject, public ScoreElement { void lassoSelectEnd(); Page* searchPage(const QPointF&) const; - QList searchSystem(const QPointF& p, const System* preferredSystem = nullptr, qreal spacingFactor = 0.5) const; - Measure* searchMeasure(const QPointF& p, const System* preferredSystem = nullptr, qreal spacingFactor = 0.5) const; + QList searchSystem(const QPointF& p, const System* preferredSystem = nullptr, qreal spacingFactor = 0.5, qreal preferredSpacingFactor = 1.0) const; + Measure* searchMeasure(const QPointF& p, const System* preferredSystem = nullptr, qreal spacingFactor = 0.5, qreal preferredSpacingFactor = 1.0) const; bool getPosition(Position* pos, const QPointF&, int voice) const;