FIRE-30873: Add infinite-scroll mode to trackpad

And increase sensitivities
master
Angeldark Raymaker 2024-09-23 19:20:51 +01:00
parent e50f230f76
commit 3ddb953e08
5 changed files with 118 additions and 45 deletions

View File

@ -1127,26 +1127,34 @@ void FSFloaterPoser::onLimbTrackballChanged()
pitch = trackPadPos.mV[VY];
LLButton *toggleSensitivityButton = getChild<LLButton>(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<LLSliderCtrl>(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<LLButton>(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<LLButton>(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<LLSliderCtrl>(POSER_AVATAR_SLIDER_POSX_NAME);
LLSliderCtrl *xSlider = getChild<LLSliderCtrl>(POSER_AVATAR_SLIDER_POSX_NAME);
LLSliderCtrl *ySlider = getChild<LLSliderCtrl>(POSER_AVATAR_SLIDER_POSY_NAME);
LLSliderCtrl *zSlider = getChild<LLSliderCtrl>(POSER_AVATAR_SLIDER_POSZ_NAME);
LLSliderCtrl *zSlider = getChild<LLSliderCtrl>(POSER_AVATAR_SLIDER_POSZ_NAME);
if (!xSlider || !ySlider || !zSlider)
return;

View File

@ -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.
/// </summary>
const F32 normalTrackballRangeInRads = F_PI;
const F32 normalTrackpadRangeInRads = F_PI;
/// <summary>
/// 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.
/// </summary>
const F32 zoomedTrackballRangeInRads = F_PI_BY_TWO;
const F32 trackPadDefaultSensitivity = 0.8;
/// <summary>
/// These are defaults, subjective and should be overridden by optional values in XML.
/// </summary>
const F32 trackPadHighSensitivity = 0.3;
/// <summary>
/// Refreshes the pose load/save list.

View File

@ -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)
{

View File

@ -42,7 +42,8 @@ public:
{
Optional<LLViewBorder::Params> border;
Optional<LLUIImage *> image_moon_back, image_moon_front, image_sphere, image_sun_back, image_sun_front;
Optional<bool> pinch_mode;
Optional<bool> pinch_mode;
Optional<bool> 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:
/// <summary>
/// Whether we allow the second cursor to appear.
/// </summary>
bool mAllowPinchMode = false;
bool mAllowPinchMode = false;
/// <summary>
/// Whether to allow the cursor(s) to 'wrap'.
/// </summary>
/// <example>
/// 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.
/// </example>
bool mInfiniteScrollMode = false;
/// <summary>
/// Whether we should be moving the pinch cursor now
/// </summary>
bool doingPinchMode = false;
/// <summary>
/// The various values placing the cursors and documenting behaviours.
/// Where relevant, all are scaled in pixels.
/// </summary>
S32 _valueX;
S32 _valueY;
S32 _valueWheelClicks;

View File

@ -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"/>
<panel
follows="left|top|bottom"
height="22"