Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #306234: added teleportation to smooth scrolling, for dealing with repeats + improved comments #6191

Merged
merged 1 commit into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions framework/preferencekeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@
#define PREF_PAN_MODIFIER_MAX "smoothPan/modifier/maxSpeed"
#define PREF_PAN_CURSOR_POS "smoothPan/cursor/position"
#define PREF_PAN_CURSOR_VISIBLE "smoothPan/cursor/visible"
#define PREF_PAN_TELEPORT_RIGHT "smoothPan/cursor/teleportRight"
#define PREF_PAN_TELEPORT_LEFT "smoothPan/cursor/teleportLeft"
//#define PREF_PAN_DISTANCE_LEFT "smoothPan/distance/left"
//#define PREF_PAN_DISTANCE_LEFT1 "smoothPan/distance/left1"
//#define PREF_PAN_DISTANCE_LEFT2 "smoothPan/distance/left2"
Expand Down
2 changes: 2 additions & 0 deletions mscore/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ void Preferences::init(bool storeInMemoryOnly)
{ PREF_PAN_CURSOR_VISIBLE, new BoolPreference(false, true) },
{ PREF_PAN_CURSOR_POS, new DoublePreference(0.3, true) },
{ PREF_PAN_SMOOTHLY_ENABLED, new BoolPreference(false, true) },
{ PREF_PAN_TELEPORT_LEFT, new BoolPreference(true, true) },
{ PREF_PAN_TELEPORT_RIGHT, new BoolPreference(false, true) },
// {PREF_PAN_DISTANCE_LEFT, new DoublePreference(-250, false)},
// {PREF_PAN_DISTANCE_LEFT1, new DoublePreference(-125, false)},
// {PREF_PAN_DISTANCE_LEFT2, new DoublePreference(-50, false)},
Expand Down
38 changes: 33 additions & 5 deletions mscore/scoreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,8 @@ void ScoreView::moveControlCursor(const Fraction& tick)
int controlX = _controlCursor->rect().x();
double distance = realX - controlX;

if (seq->isPlaying()) {
//playbackCursor in front of the controlCursor
if (seq->isPlaying() && isCursorDistanceReasonable()) {
// playbackCursor in front of the controlCursor
if (distance > _panSettings.rightDistance) {
_controlModifier += _panSettings.controlModifierSteps;
} else if (distance > _panSettings.rightDistance1 && _controlModifier < _panSettings.rightMod1) {
Expand All @@ -683,7 +683,7 @@ void ScoreView::moveControlCursor(const Fraction& tick)
} else if (_controlModifier > _panSettings.rightMod3 && distance < _panSettings.rightDistance3) {
_controlModifier = _panSettings.controlModifierBase;
}
//playbackCursor behind the controlCursor
// playbackCursor behind the controlCursor
else if (distance < _panSettings.leftDistance) {
_controlModifier -= _panSettings.controlModifierSteps;
} else if (_controlModifier < _panSettings.leftMod1 && distance > _panSettings.leftDistance1) {
Expand All @@ -694,7 +694,7 @@ void ScoreView::moveControlCursor(const Fraction& tick)
_controlModifier = _panSettings.controlModifierBase;
}

//enforce limits
// enforce limits
if (_controlModifier < _panSettings.minContinuousModifier) {
_controlModifier = _panSettings.minContinuousModifier;
} else if (_controlModifier > _panSettings.maxContinuousModifier) {
Expand Down Expand Up @@ -737,7 +737,7 @@ void ScoreView::moveControlCursor(const Fraction& tick)
_playbackCursorTimer.restart();
}

//Calculate the position of the controlCursor based on the timeElapsed (which is not the real time that has passed)
// Calculate the position of the controlCursor based on the timeElapsed (which is not the real time that has passed)
qreal x = score()->firstMeasure()->pos().x()
+ (score()->lastMeasure()->pos().x() - score()->firstMeasure()->pos().x())
* (_timeElapsed / (score()->duration() * 1000));
Expand All @@ -746,6 +746,32 @@ void ScoreView::moveControlCursor(const Fraction& tick)
update(_matrix.mapRect(_controlCursor->rect()).toRect().adjusted(-1,-1,1,1));
}

//---------------------------------------------------------
// isCursorDistanceReasonable
// check if the control cursor needs to be teleported
// to catch up with the playback cursor (for smooth panning)
//---------------------------------------------------------

bool ScoreView::isCursorDistanceReasonable()
{
qreal viewWidth = canvasViewport().width();
qreal controlX = _controlCursor->rect().x();
qreal playbackX = _cursor->rect().x();
qreal cursorDistance = abs(controlX - playbackX);
double maxLeftDistance = viewWidth * (_panSettings.controlCursorScreenPos + 0.07); // 0.05 left margin + 0.02 for making this less sensitive
double maxRightDistance = viewWidth * (1 - _panSettings.controlCursorScreenPos + 0.15); // teleporting to the right is harder to trigger (we don't want to overdo it)

if (controlX < playbackX && _panSettings.teleportRightEnabled) {
return cursorDistance < maxRightDistance;
}

if (playbackX < controlX && _panSettings.teleportLeftEnabled) {
return cursorDistance < maxLeftDistance;
}

return true;
}

//---------------------------------------------------------
// moveCursor
// move cursor in note input mode
Expand Down Expand Up @@ -5635,5 +5661,7 @@ void SmoothPanSettings::loadFromPreferences()
// advancedWeighting = preferences.getBool(PREF_PAN_WEIGHT_ADVANCED);
// cursorTimerDuration = preferences.getInt(PREF_PAN_SMART_TIMER_DURATION);
controlCursorScreenPos = preferences.getDouble(PREF_PAN_CURSOR_POS);
teleportLeftEnabled = preferences.getBool(PREF_PAN_TELEPORT_LEFT);
teleportRightEnabled = preferences.getBool(PREF_PAN_TELEPORT_RIGHT);
}
} // namespace Ms
27 changes: 16 additions & 11 deletions mscore/scoreview.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,32 @@ enum class MagIdx : char;
struct SmoothPanSettings {
// these are all actually loaded from the loadFromPreferences method so don't change these initializations to change the default values,
// change the corresponding default preference value
double controlModifierBase { 1 };
double controlModifierSteps { 0.01 };
double minContinuousModifier { 0.2 };
double maxContinuousModifier { 5 };
double controlModifierBase { 1 }; // initial speed modifier
double controlModifierSteps { 0.01 }; // modification steps for the modifier
double minContinuousModifier { 0.2 }; // minimum speed, 0.2 was chosen instead of 0 to remove stuttering
double maxContinuousModifier { 5 }; // maximum speed

// Changing the distance will change the sensitivity/accuracy/jitter of the algorithm. Larger absolut values are generally smoother.
double leftDistance { -250 };
// Changing the distance will change the sensitivity/accuracy/jitter of the algorithm. Larger absolute values are generally smoother.
double leftDistance { -250 }; // decelarate
double leftDistance1 { -125 };
double leftDistance2 { -50 };
double leftDistance3 { -25 };
double rightDistance { 500 };
double rightDistance { 500 }; // accelerate
double rightDistance1 { 250 };
double rightDistance2 { 125 };
double rightDistance3 { 50 };
double leftMod1 { 0.8 };
double leftMod2 { 0.9 };
// used to smooth back to normal speed when the playback cursor is getting closer
double leftMod1 { 0.8 }; // minimum speed at the first level
double leftMod2 { 0.9 }; // etc
double leftMod3 { 0.95 };
double rightMod1 { 1.2 };
double rightMod2 { 1.1 };
// used to smooth back to normal speed when the control cursor is getting closer to the playback cursor
double rightMod1 { 1.2 }; // maximum speed at the first level
double rightMod2 { 1.1 }; // etc
double rightMod3 { 1.05 };

double controlCursorScreenPos { 0.3 };
bool teleportLeftEnabled { true };
bool teleportRightEnabled { false };

bool advancedWeighting { false }; // enables the 'smart weight'
double normalWeight { 1 };
Expand Down Expand Up @@ -359,6 +363,7 @@ public slots:

void moveCursor(const Fraction& tick);
void moveControlCursor(const Fraction& tick);
bool isCursorDistanceReasonable();
Fraction cursorTick() const;
void setCursorOn(bool);
void setBackground(QPixmap*);
Expand Down