From 3ddb953e08fe734748e2a84ad1d0a62fe1dce622 Mon Sep 17 00:00:00 2001 From: Angeldark Raymaker Date: Mon, 23 Sep 2024 19:20:51 +0100 Subject: [PATCH] FIRE-30873: Add infinite-scroll mode to trackpad And increase sensitivities --- indra/newview/fsfloaterposer.cpp | 66 ++++++++++--------- indra/newview/fsfloaterposer.h | 11 +++- indra/newview/fsvirtualtrackpad.cpp | 62 +++++++++++++++-- indra/newview/fsvirtualtrackpad.h | 21 +++++- .../skins/default/xui/en/floater_poser.xml | 3 +- 5 files changed, 118 insertions(+), 45 deletions(-) diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp index c00c9bbdda..22fb817df6 100644 --- a/indra/newview/fsfloaterposer.cpp +++ b/indra/newview/fsfloaterposer.cpp @@ -1127,26 +1127,34 @@ void FSFloaterPoser::onLimbTrackballChanged() pitch = trackPadPos.mV[VY]; LLButton *toggleSensitivityButton = getChild(POSER_AVATAR_TOGGLEBUTTON_TRACKPADSENSITIVITY); - if (!toggleSensitivityButton) - { - yaw *= normalTrackballRangeInRads; - pitch *= normalTrackballRangeInRads; - } - else + if (toggleSensitivityButton) { bool moreSensitive = toggleSensitivityButton->getValue().asBoolean(); if (moreSensitive) { - yaw *= zoomedTrackballRangeInRads; - pitch *= zoomedTrackballRangeInRads; + yaw *= trackPadHighSensitivity; + pitch *= trackPadHighSensitivity; } else { - yaw *= normalTrackballRangeInRads; - pitch *= normalTrackballRangeInRads; + yaw *= trackPadDefaultSensitivity; + pitch *= trackPadDefaultSensitivity; } } + // if the trackpad is in 'infinite scroll' mode, it can produce normalized-values outside the range of the sliders; this wraps them to by the slider full-scale + while (yaw > 1) + yaw -= 2; + while (yaw < -1) + yaw += 2; + while (pitch > 1) + pitch -= 2; + while (pitch < -1) + pitch += 2; + + yaw *= normalTrackpadRangeInRads; + pitch *= normalTrackpadRangeInRads; + LLSliderCtrl *rollSlider = getChild(POSER_AVATAR_SLIDER_ROLL_NAME); if (rollSlider) roll = (F32) rollSlider->getValue().asReal(); // roll starts from its own slider @@ -1198,24 +1206,21 @@ void FSFloaterPoser::onLimbYawPitchRollChanged() if (!trackBall) return; + yaw /= normalTrackpadRangeInRads; + pitch /= normalTrackpadRangeInRads; LLButton *toggleSensitivityButton = getChild(POSER_AVATAR_TOGGLEBUTTON_TRACKPADSENSITIVITY); - if (!toggleSensitivityButton) - { - yaw /= normalTrackballRangeInRads; - pitch /= normalTrackballRangeInRads; - } - else + if (toggleSensitivityButton) { bool moreSensitive = toggleSensitivityButton->getValue().asBoolean(); if (moreSensitive) { - yaw /= zoomedTrackballRangeInRads; - pitch /= zoomedTrackballRangeInRads; + yaw /= trackPadHighSensitivity; + pitch /= trackPadHighSensitivity; } else { - yaw /= normalTrackballRangeInRads; - pitch /= normalTrackballRangeInRads; + yaw /= trackPadDefaultSensitivity; + pitch /= trackPadDefaultSensitivity; } } @@ -1233,24 +1238,21 @@ void FSFloaterPoser::refreshTrackpadCursor() axis1 = rotation.mV[VX]; axis2 = rotation.mV[VY]; + axis1 /= normalTrackpadRangeInRads; + axis2 /= normalTrackpadRangeInRads; LLButton *toggleSensitivityButton = getChild(POSER_AVATAR_TOGGLEBUTTON_TRACKPADSENSITIVITY); - if (!toggleSensitivityButton) - { - axis1 /= normalTrackballRangeInRads; - axis2 /= normalTrackballRangeInRads; - } - else + if (toggleSensitivityButton) { bool moreSensitive = toggleSensitivityButton->getValue().asBoolean(); if (moreSensitive) { - axis1 /= zoomedTrackballRangeInRads; - axis2 /= zoomedTrackballRangeInRads; + axis1 /= trackPadHighSensitivity; + axis2 /= trackPadHighSensitivity; } else { - axis1 /= normalTrackballRangeInRads; - axis2 /= normalTrackballRangeInRads; + axis1 /= trackPadDefaultSensitivity; + axis2 /= trackPadDefaultSensitivity; } } @@ -1273,9 +1275,9 @@ void FSFloaterPoser::refreshAvatarPositionSliders() if (!boost::iequals(activeTabName, POSER_AVATAR_TAB_POSITION)) return; // if the active tab isn't the av position one, don't set anything. - LLSliderCtrl *xSlider = getChild(POSER_AVATAR_SLIDER_POSX_NAME); + LLSliderCtrl *xSlider = getChild(POSER_AVATAR_SLIDER_POSX_NAME); LLSliderCtrl *ySlider = getChild(POSER_AVATAR_SLIDER_POSY_NAME); - LLSliderCtrl *zSlider = getChild(POSER_AVATAR_SLIDER_POSZ_NAME); + LLSliderCtrl *zSlider = getChild(POSER_AVATAR_SLIDER_POSZ_NAME); if (!xSlider || !ySlider || !zSlider) return; diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h index 2219ff12ee..e80ad0d74d 100644 --- a/indra/newview/fsfloaterposer.h +++ b/indra/newview/fsfloaterposer.h @@ -80,12 +80,17 @@ class FSFloaterPoser : public LLFloater /// The amount of deflection 'one unit' on the trackpad translates to in radians. /// The trackpad ordinarily has a range of +1..-1; multiplied by PI, gives PI to -PI, or all 360 degrees of deflection. /// - const F32 normalTrackballRangeInRads = F_PI; + const F32 normalTrackpadRangeInRads = F_PI; /// - /// The counterpart to above, when using the trackpad in zoom-mode, its maximum deflection on either axis is plus/minus this. + /// The trackpad is the size it is, mousing on it has arbitrary 'sensitivity': how much angular change do we want per pixels moved. /// - const F32 zoomedTrackballRangeInRads = F_PI_BY_TWO; + const F32 trackPadDefaultSensitivity = 0.8; + + /// + /// These are defaults, subjective and should be overridden by optional values in XML. + /// + const F32 trackPadHighSensitivity = 0.3; /// /// Refreshes the pose load/save list. diff --git a/indra/newview/fsvirtualtrackpad.cpp b/indra/newview/fsvirtualtrackpad.cpp index 99a192707b..393684123d 100644 --- a/indra/newview/fsvirtualtrackpad.cpp +++ b/indra/newview/fsvirtualtrackpad.cpp @@ -41,7 +41,8 @@ FSVirtualTrackpad::Params::Params() image_sphere("image_sphere"), image_sun_back("image_sun_back"), image_sun_front("image_sun_front"), - pinch_mode("pinch_mode") + pinch_mode("pinch_mode"), + infinite_scroll_mode("infinite_scroll_mode") { } @@ -52,7 +53,8 @@ FSVirtualTrackpad::FSVirtualTrackpad(const FSVirtualTrackpad::Params &p) mImgSunBack(p.image_sun_back), mImgSunFront(p.image_sun_front), mImgSphere(p.image_sphere), - mAllowPinchMode(p.pinch_mode) + mAllowPinchMode(p.pinch_mode), + mInfiniteScrollMode(p.infinite_scroll_mode) { LLRect border_rect = getLocalRect(); _valueX = _lastValueX = _pinchValueX = _lastPinchValueX = border_rect.getCenterX(); @@ -89,6 +91,8 @@ void FSVirtualTrackpad::drawThumb(bool isPinchThumb) S32 x = isPinchThumb ? _pinchValueX : _valueX; S32 y = isPinchThumb ? _pinchValueY : _valueY; + wrapOrClipCursorPosition(&x, &y); + S32 halfThumbWidth = thumb->getWidth() / 2; S32 halfThumbHeight = thumb->getHeight() / 2; @@ -212,6 +216,29 @@ LLSD FSVirtualTrackpad::getPinchValue() return result; } +void FSVirtualTrackpad::wrapOrClipCursorPosition(S32* x, S32* y) +{ + if (!x || !y) + return; + + LLRect rect = mTouchArea->getRect(); + if (mInfiniteScrollMode) + { + while (*x > rect.mRight) + *x -= rect.getWidth(); + while (*x < rect.mLeft) + *x += rect.getWidth(); + while (*y > rect.mTop) + *y -= rect.getHeight(); + while (*y < rect.mBottom) + *y += rect.getHeight(); + } + else + { + rect.clampPointToRect(*x, *y); + } +} + bool FSVirtualTrackpad::handleHover(S32 x, S32 y, MASK mask) { if (!hasMouseCapture()) @@ -229,13 +256,13 @@ bool FSVirtualTrackpad::handleHover(S32 x, S32 y, MASK mask) correctedY = y + _thumbClickOffsetY; } - LLRect rect = mTouchArea->getRect(); - rect.clampPointToRect(correctedX, correctedY); + if (!mInfiniteScrollMode) + wrapOrClipCursorPosition(&correctedX, &correctedY); if (doingPinchMode) { _pinchValueX = correctedX; - _pinchValueX = correctedY; + _pinchValueY = correctedY; } else { @@ -278,8 +305,16 @@ void FSVirtualTrackpad::convertNormalizedToPixelPos(F32 x, F32 y, S32 *valX, S32 S32 width = rect.getWidth(); S32 height = rect.getHeight(); - *valX = centerX + ll_round(llclamp(x, -1, 1) * width / 2); - *valY = centerY + ll_round(llclamp(y, -1, 1) * height / 2); + if (mInfiniteScrollMode) + { + *valX = centerX + ll_round(x * width / 2); + *valY = centerY + ll_round(y * height / 2); + } + else + { + *valX = centerX + ll_round(llclamp(x, -1, 1) * width / 2); + *valY = centerY + ll_round(llclamp(y, -1, 1) * height / 2); + } } bool FSVirtualTrackpad::handleMouseUp(S32 x, S32 y, MASK mask) @@ -312,6 +347,19 @@ bool FSVirtualTrackpad::handleMouseDown(S32 x, S32 y, MASK mask) return LLView::handleMouseDown(x, y, mask); } +bool FSVirtualTrackpad::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + if (hasMouseCapture()) + { + doingPinchMode = false; + gFocusMgr.setMouseCapture(NULL); + + make_ui_sound("UISndClickRelease"); + } + + return LLView::handleRightMouseUp(x, y, mask); +} + // move pinch cursor bool FSVirtualTrackpad::handleRightMouseDown(S32 x, S32 y, MASK mask) { diff --git a/indra/newview/fsvirtualtrackpad.h b/indra/newview/fsvirtualtrackpad.h index da89fb5737..80c6d857d7 100644 --- a/indra/newview/fsvirtualtrackpad.h +++ b/indra/newview/fsvirtualtrackpad.h @@ -42,7 +42,8 @@ public: { Optional border; Optional image_moon_back, image_moon_front, image_sphere, image_sun_back, image_sun_front; - Optional pinch_mode; + Optional pinch_mode; + Optional infinite_scroll_mode; Params(); }; @@ -54,6 +55,7 @@ public: virtual bool handleHover(S32 x, S32 y, MASK mask); virtual bool handleMouseUp(S32 x, S32 y, MASK mask); virtual bool handleMouseDown(S32 x, S32 y, MASK mask); + virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask); virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask); virtual bool handleScrollWheel(S32 x, S32 y, S32 clicks); @@ -94,6 +96,7 @@ private: void setPinchValueAndCommit(const S32 x, const S32 y); void drawThumb(bool isPinchThumb); bool isPointInTouchArea(S32 x, S32 y) const; + void wrapOrClipCursorPosition(S32* x, S32* y); void determineThumbClickError(S32 x, S32 y); void determineThumbClickErrorForPinch(S32 x, S32 y); @@ -111,13 +114,27 @@ private: /// /// Whether we allow the second cursor to appear. /// - bool mAllowPinchMode = false; + bool mAllowPinchMode = false; + + /// + /// Whether to allow the cursor(s) to 'wrap'. + /// + /// + /// When false, the cursor is constrained to the control-area. + /// When true, the cursor 'disappears' out the top, and starts from the bottom, + /// effectively allowing infinite scrolling. + /// + bool mInfiniteScrollMode = false; /// /// Whether we should be moving the pinch cursor now /// bool doingPinchMode = false; + /// + /// The various values placing the cursors and documenting behaviours. + /// Where relevant, all are scaled in pixels. + /// S32 _valueX; S32 _valueY; S32 _valueWheelClicks; diff --git a/indra/newview/skins/default/xui/en/floater_poser.xml b/indra/newview/skins/default/xui/en/floater_poser.xml index 34c3e2eedb..bc4ff29c4c 100644 --- a/indra/newview/skins/default/xui/en/floater_poser.xml +++ b/indra/newview/skins/default/xui/en/floater_poser.xml @@ -594,7 +594,8 @@ width="565"> height="153" width="153" tool_tip="Change the rotation of the currently selected joint(s). Roll the wheel while holding to adjust the 3rd axis" - thumb_mode="sun"/> + pinch_mode="false" + infinite_scroll_mode="true"/>