summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerinput.cpp')
-rw-r--r--indra/newview/llviewerinput.cpp788
1 files changed, 607 insertions, 181 deletions
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index ddcabd9cda..2559f1065f 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -35,6 +35,7 @@
#include "llagentcamera.h"
#include "llfloaterimnearbychat.h"
#include "llfocusmgr.h"
+#include "llgamecontrol.h"
#include "llkeybind.h" // LLKeyData
#include "llmorphview.h"
#include "llmoveview.h"
@@ -47,6 +48,7 @@
#include "llfloatercamera.h"
#include "llinitparam.h"
#include "llselectmgr.h"
+#include "llviewercamera.h"
//
// Constants
@@ -61,15 +63,18 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
+static U64 g_lastUpdateTime { 0 };
+static F32 g_deltaTime { 0.0f };
+
struct LLKeybindFunctionData
{
- LLKeybindFunctionData(std::function<bool(EKeystate keystate)> function, bool global)
+ LLKeybindFunctionData(LLKeyFunc function, bool global)
:
mFunction(function),
mIsGlobal(global)
{
}
- std::function<bool(EKeystate keystate)> mFunction;
+ LLKeyFunc mFunction;
// todo: might be good idea to make this into enum, like: global/inworld/menu
bool mIsGlobal;
};
@@ -82,16 +87,16 @@ struct LLKeyboardActionRegistry
LLViewerInput gViewerInput;
-bool agent_jump( EKeystate s )
+bool agent_jump( const LLKeyPressState& s )
{
static bool first_fly_attempt(true);
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
first_fly_attempt = true;
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < FLY_TIME
|| frame_count <= FLY_FRAMES
@@ -109,9 +114,22 @@ bool agent_jump( EKeystate s )
return true;
}
-bool agent_push_down( EKeystate s )
+bool agent_push_down( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ gAgent.moveUp(-1);
+ return true;
+}
+
+bool agent_toggle_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
+
+ if (KEYSTATE_DOWN == s.mState
+ && !gAgent.getFlying())
+ {
+ gAgent.toggleCrouch();
+ }
gAgent.moveUp(-1);
return true;
}
@@ -128,16 +146,16 @@ static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode)
}
}
-static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
+static void agent_handle_doubletap_run(const LLKeyPressState& s, LLAgent::EDoubleTapRunMode mode)
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Note: in case shift is already released, slide left/right run
// will be released in agent_turn_left()/agent_turn_right()
agent_check_temporary_run(mode);
}
else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
- KEYSTATE_DOWN == s &&
+ KEYSTATE_DOWN == s.mState &&
!gAgent.getRunning())
{
if (gAgent.mDoubleTapRunMode == mode &&
@@ -155,13 +173,13 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
}
}
-static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+static void agent_push_forwardbackward( const LLKeyPressState& s, S32 direction, LLAgent::EDoubleTapRunMode mode )
{
agent_handle_doubletap_run(s, mode);
- if (KEYSTATE_UP == s) return;
+ if (KEYSTATE_UP == s.mState) return;
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
{
@@ -173,9 +191,9 @@ static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDo
}
}
-bool camera_move_forward( EKeystate s );
+bool camera_move_forward( const LLKeyPressState& s );
-bool agent_push_forward( EKeystate s )
+bool agent_push_forward( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
@@ -191,9 +209,9 @@ bool agent_push_forward( EKeystate s )
return true;
}
-bool camera_move_backward( EKeystate s );
+bool camera_move_backward( const LLKeyPressState& s );
-bool agent_push_backward( EKeystate s )
+bool agent_push_backward( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
@@ -213,12 +231,12 @@ bool agent_push_backward( EKeystate s )
return true;
}
-static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+static void agent_slide_leftright( const LLKeyPressState& s, S32 direction, LLAgent::EDoubleTapRunMode mode )
{
agent_handle_doubletap_run(s, mode);
- if( KEYSTATE_UP == s ) return;
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ if( KEYSTATE_UP == s.mState ) return;
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
{
@@ -231,7 +249,7 @@ static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleT
}
-bool agent_slide_left( EKeystate s )
+bool agent_slide_left( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
@@ -239,16 +257,16 @@ bool agent_slide_left( EKeystate s )
}
-bool agent_slide_right( EKeystate s )
+bool agent_slide_right( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
return true;
}
-bool camera_spin_around_cw( EKeystate s );
+bool camera_spin_around_cw( const LLKeyPressState& s );
-bool agent_turn_left(EKeystate s)
+bool agent_turn_left(const LLKeyPressState& s)
{
//in free camera control mode we need to intercept keyboard events for avatar movements
if (LLFloaterCamera::inFreeCameraMode())
@@ -265,21 +283,21 @@ bool agent_turn_left(EKeystate s)
}
else
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Check temporary running. In case user released 'left' key with shift already released.
agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDELEFT);
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
+ F32 time = s.mElapsedTime;
+ gAgent.moveYaw( LLFloaterMove::getYawRate( time ) * s.mValue );
}
return true;
}
-bool camera_spin_around_ccw( EKeystate s );
+bool camera_spin_around_ccw( const LLKeyPressState& s );
-bool agent_turn_right( EKeystate s )
+bool agent_turn_right( const LLKeyPressState& s )
{
//in free camera control mode we need to intercept keyboard events for avatar movements
if (LLFloaterCamera::inFreeCameraMode())
@@ -296,48 +314,58 @@ bool agent_turn_right( EKeystate s )
}
else
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Check temporary running. In case user released 'right' key with shift already released.
agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDERIGHT);
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
+ F32 time = s.mElapsedTime;
+ gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) * s.mValue );
}
return true;
}
-bool agent_look_up( EKeystate s )
+bool agent_look_up( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgent.movePitch(-1);
//gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
return true;
}
-bool agent_look_down( EKeystate s )
+bool agent_look_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgent.movePitch(1);
//gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
return true;
}
-bool agent_toggle_fly( EKeystate s )
+bool agent_toggle_fly( const LLKeyPressState& s )
{
// Only catch the edge
- if (KEYSTATE_DOWN == s )
+ if (KEYSTATE_DOWN == s.mState )
{
LLAgent::toggleFlying();
}
return true;
}
-F32 get_orbit_rate()
+bool agent_toggle_flycam( const LLKeyPressState& s )
+{
+ // Only catch the edge
+ if (KEYSTATE_DOWN == s.mState )
+ {
+ gAgent.toggleFlycam();
+ }
+ return true;
+}
+
+F32 get_orbit_rate( const LLKeyPressState& s )
{
- F32 time = gKeyboard->getCurKeyElapsedTime();
+ F32 time = s.mElapsedTime;
if( time < NUDGE_TIME )
{
F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
@@ -350,26 +378,46 @@ F32 get_orbit_rate()
}
}
-bool camera_spin_around_ccw( EKeystate s )
+// Keyboard-driven flycam translate/rotate: sets a per-channel rate that
+// LLAgent::updateFlycam() blends in and clears every frame (same
+// "set while held, cleared once consumed" idiom as mOrbitInKey/mPanUpKey).
+template <U8 CHANNEL, S32 SIGN>
+bool flycam_axis_key(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState) return true;
+ gAgent.setFlycamKeyInput(CHANNEL, SIGN * get_orbit_rate(s));
+ return true;
+}
+
+bool flycam_unroll_key(const LLKeyPressState& s)
{
- if( KEYSTATE_UP == s ) return true;
+ if (KEYSTATE_DOWN == s.mState)
+ {
+ gAgent.setFlycamKeyUnroll(true);
+ }
+ return true;
+}
+
+bool camera_spin_around_ccw( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_around_cw( EKeystate s )
+bool camera_spin_around_cw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_around_ccw_sitting( EKeystate s )
+bool camera_spin_around_ccw_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return true;
if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
{
//send keystrokes, but do not change camera
@@ -379,15 +427,15 @@ bool camera_spin_around_ccw_sitting( EKeystate s )
{
//change camera but do not send keystrokes
gAgentCamera.unlockView();
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_around_cw_sitting( EKeystate s )
+bool camera_spin_around_cw_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return true;
if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
{
//send keystrokes, but do not change camera
@@ -397,32 +445,32 @@ bool camera_spin_around_cw_sitting( EKeystate s )
{
//change camera but do not send keystrokes
gAgentCamera.unlockView();
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_over( EKeystate s )
+bool camera_spin_over( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_under( EKeystate s )
+bool camera_spin_under( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_over_sitting( EKeystate s )
+bool camera_spin_over_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
if (gAgent.upGrabbed() || gAgentCamera.sitCameraEnabled())
{
//send keystrokes, but do not change camera
@@ -431,15 +479,15 @@ bool camera_spin_over_sitting( EKeystate s )
else
{
//change camera but do not send keystrokes
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_under_sitting( EKeystate s )
+bool camera_spin_under_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
if (gAgent.downGrabbed() || gAgentCamera.sitCameraEnabled())
{
//send keystrokes, but do not change camera
@@ -448,45 +496,68 @@ bool camera_spin_under_sitting( EKeystate s )
else
{
//change camera but do not send keystrokes
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_move_forward( EKeystate s )
+bool camera_roll_left(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState) return true;
+ gAgentCamera.unlockView();
+ gAgentCamera.setRollLeftKey(get_orbit_rate(s));
+ return true;
+}
+
+bool camera_roll_right(const LLKeyPressState& s)
{
- if( KEYSTATE_UP == s ) return true;
+ if (KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setRollRightKey(get_orbit_rate(s));
return true;
}
+bool camera_roll_reset(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState ) return true;
+ gAgentCamera.resetCameraRoll();
+ return true;
+}
-bool camera_move_backward( EKeystate s )
+bool camera_move_forward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
return true;
}
-bool camera_move_forward_sitting( EKeystate s )
+
+bool camera_move_backward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
+ gAgentCamera.unlockView();
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
+ return true;
+}
+
+bool camera_move_forward_sitting( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return true;
if (gAgent.forwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
{
agent_push_forward(s);
}
else
{
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_move_backward_sitting( EKeystate s )
+bool camera_move_backward_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return true;
if (gAgent.backwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
{
@@ -494,137 +565,137 @@ bool camera_move_backward_sitting( EKeystate s )
}
else
{
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_pan_up( EKeystate s )
+bool camera_pan_up( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanUpKey( get_orbit_rate() );
+ gAgentCamera.setPanUpKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_down( EKeystate s )
+bool camera_pan_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanDownKey( get_orbit_rate() );
+ gAgentCamera.setPanDownKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_left( EKeystate s )
+bool camera_pan_left( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanLeftKey( get_orbit_rate() );
+ gAgentCamera.setPanLeftKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_right( EKeystate s )
+bool camera_pan_right( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanRightKey( get_orbit_rate() );
+ gAgentCamera.setPanRightKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_in( EKeystate s )
+bool camera_pan_in( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanInKey( get_orbit_rate() );
+ gAgentCamera.setPanInKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_out( EKeystate s )
+bool camera_pan_out( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanOutKey( get_orbit_rate() );
+ gAgentCamera.setPanOutKey( get_orbit_rate(s) );
return true;
}
-bool camera_move_forward_fast( EKeystate s )
+bool camera_move_forward_fast( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
gAgentCamera.setOrbitInKey(2.5f);
return true;
}
-bool camera_move_backward_fast( EKeystate s )
+bool camera_move_backward_fast( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
gAgentCamera.setOrbitOutKey(2.5f);
return true;
}
-bool edit_avatar_spin_ccw( EKeystate s )
+bool edit_avatar_spin_ccw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
- //gMorphView->orbitLeft( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
+ //gMorphView->orbitLeft( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_cw( EKeystate s )
+bool edit_avatar_spin_cw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
- //gMorphView->orbitRight( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
+ //gMorphView->orbitRight( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_over( EKeystate s )
+bool edit_avatar_spin_over( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
- //gMorphView->orbitUp( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
+ //gMorphView->orbitUp( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_under( EKeystate s )
+bool edit_avatar_spin_under( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
- //gMorphView->orbitDown( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
+ //gMorphView->orbitDown( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_move_forward( EKeystate s )
+bool edit_avatar_move_forward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
//gMorphView->orbitIn();
return true;
}
-bool edit_avatar_move_backward( EKeystate s )
+bool edit_avatar_move_backward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
//gMorphView->orbitOut();
return true;
}
-bool stop_moving( EKeystate s )
+bool stop_moving( const LLKeyPressState& s )
{
//it's supposed that 'stop moving' key will be held down for some time
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
// stop agent
gAgent.setControlFlags(AGENT_CONTROL_STOP);
@@ -633,23 +704,23 @@ bool stop_moving( EKeystate s )
return true;
}
-bool start_chat( EKeystate s )
+bool start_chat( const LLKeyPressState& s )
{
if (LLAppViewer::instance()->quitRequested())
{
return true; // can't talk, gotta go, kthxbye!
}
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
// start chat
LLFloaterIMNearbyChat::startChat(NULL);
return true;
}
-bool start_gesture( EKeystate s )
+bool start_gesture( const LLKeyPressState& s )
{
LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
- if (KEYSTATE_UP == s &&
+ if (KEYSTATE_UP == s.mState &&
! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
{
if ((LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->getCurrentChat().empty())
@@ -666,9 +737,9 @@ bool start_gesture( EKeystate s )
return true;
}
-bool run_forward(EKeystate s)
+bool run_forward(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD)
{
@@ -680,7 +751,7 @@ bool run_forward(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if(KEYSTATE_UP == s)
+ else if(KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_FORWARD)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -691,9 +762,9 @@ bool run_forward(EKeystate s)
return true;
}
-bool run_backward(EKeystate s)
+bool run_backward(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD)
{
@@ -705,7 +776,7 @@ bool run_backward(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_BACKWARD)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -716,9 +787,9 @@ bool run_backward(EKeystate s)
return true;
}
-bool run_left(EKeystate s)
+bool run_left(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT)
{
@@ -730,7 +801,7 @@ bool run_left(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDELEFT)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -741,9 +812,9 @@ bool run_left(EKeystate s)
return true;
}
-bool run_right(EKeystate s)
+bool run_right(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT)
{
@@ -755,7 +826,7 @@ bool run_right(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDERIGHT)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -766,9 +837,9 @@ bool run_right(EKeystate s)
return true;
}
-bool toggle_run(EKeystate s)
+bool toggle_run(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool run = gAgent.getAlwaysRun();
if (run)
{
@@ -784,9 +855,9 @@ bool toggle_run(EKeystate s)
return true;
}
-bool toggle_sit(EKeystate s)
+bool toggle_sit(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
if (gAgent.isSitting())
{
gAgent.standUp();
@@ -798,25 +869,25 @@ bool toggle_sit(EKeystate s)
return true;
}
-bool toggle_pause_media(EKeystate s) // analogue of play/pause button in top bar
+bool toggle_pause_media(const LLKeyPressState& s) // analogue of play/pause button in top bar
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool pause = LLViewerMedia::getInstance()->isAnyMediaPlaying();
LLViewerMedia::getInstance()->setAllMediaPaused(pause);
return true;
}
-bool toggle_enable_media(EKeystate s)
+bool toggle_enable_media(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool pause = LLViewerMedia::getInstance()->isAnyMediaPlaying() || LLViewerMedia::getInstance()->isAnyMediaShowing();
LLViewerMedia::getInstance()->setAllMediaEnabled(!pause);
return true;
}
-bool walk_to(EKeystate s)
+bool walk_to(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s)
+ if (KEYSTATE_DOWN != s.mState)
{
// teleport/walk is usually on mouseclick, mouseclick needs
// to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't,
@@ -827,29 +898,29 @@ bool walk_to(EKeystate s)
return LLToolPie::getInstance()->walkToClickedLocation();
}
-bool teleport_to(EKeystate s)
+bool teleport_to(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return false;
+ if (KEYSTATE_DOWN != s.mState) return false;
return LLToolPie::getInstance()->teleportToClickedLocation();
}
-bool toggle_voice(EKeystate s)
+bool toggle_voice(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
if (!LLAgent::isActionAllowed("speak")) return false;
LLVoiceClient::getInstance()->toggleUserPTTState();
return true;
}
-bool voice_follow_key(EKeystate s)
+bool voice_follow_key(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN == s)
+ if (KEYSTATE_DOWN == s.mState)
{
if (!LLAgent::isActionAllowed("speak")) return false;
LLVoiceClient::getInstance()->setUserPTTState(true);
return true;
}
- else if (KEYSTATE_UP == s && LLVoiceClient::getInstance()->getUserPTTState())
+ else if (KEYSTATE_UP == s.mState && LLVoiceClient::getInstance()->getUserPTTState())
{
LLVoiceClient::getInstance()->setUserPTTState(false);
return true;
@@ -857,7 +928,7 @@ bool voice_follow_key(EKeystate s)
return false;
}
-bool script_trigger_lbutton(EKeystate s)
+bool script_trigger_lbutton(const LLKeyPressState& s)
{
// Check for script overriding/expecting left mouse button.
// Note that this does not pass event further and depends onto mouselook.
@@ -866,7 +937,7 @@ bool script_trigger_lbutton(EKeystate s)
if (gAgent.leftButtonGrabbed())
{
bool mouselook = gAgentCamera.cameraMouselook();
- switch (s)
+ switch (s.mState)
{
case KEYSTATE_DOWN:
if (mouselook)
@@ -895,11 +966,56 @@ bool script_trigger_lbutton(EKeystate s)
return false;
}
+bool agent_pitch(const LLKeyPressState& s, F32 direction)
+{
+ if(!gAgentCamera.cameraMouselook() || KEYSTATE_UP == s.mState)
+ {
+ return false;
+ }
+ // const F32 NOMINAL_MOUSE_SENSITIVITY = 0.0025f;
+
+ // static LLCachedControl<F32> mouse_sensitivity_setting(gSavedSettings, "MouseSensitivity");
+ // F32 mouse_sensitivity = clamp_rescale(mouse_sensitivity_setting, 0.f, 15.f, 0.5f, 2.75f) * NOMINAL_MOUSE_SENSITIVITY;
+
+ const F32 fov = LLViewerCamera::getInstance()->getView() / DEFAULT_FIELD_OF_VIEW;
+ // pitch (vertical)
+ gAgent.pitch(s.mValue * fov * direction * g_deltaTime); // or -dy if InvertMouse
+ return true;
+}
+
+bool agent_pitch_forward(const LLKeyPressState& s)
+{
+ return agent_pitch(s,1);
+}
+
+bool agent_pitch_backward(const LLKeyPressState& s)
+{
+ return agent_pitch(s,-1);
+}
+
+bool agent_spin_over( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ //change camera but do not send keystrokes
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
+ return true;
+}
+
+
+bool agent_spin_under( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ //change camera but do not send keystrokes
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
+ return true;
+}
+
+
// Used by scripts, for overriding/handling left mouse button
// see mControlsTakenCount
-bool agent_control_lbutton_handle(EKeystate s)
+bool agent_control_lbutton_handle(const LLKeyPressState& s)
{
- switch (s)
+ switch (s.mState)
{
case KEYSTATE_DOWN:
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
@@ -913,6 +1029,20 @@ bool agent_control_lbutton_handle(EKeystate s)
return true;
}
+template <U8 N>
+bool game_control_button(const LLKeyPressState& s)
+{
+ if ( KEYSTATE_DOWN == s.mState )
+ {
+ gAgent.pressGameControlButton(N);
+ }
+ else if ( KEYSTATE_UP == s.mState )
+ {
+ gAgent.releaseGameControlButton(N);
+ }
+ return true;
+}
+
// In-world keybindings, like walking or camera
#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, false));
// Global keybindings that should work even with floaters focused, like voice
@@ -936,6 +1066,10 @@ REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
+REGISTER_KEYBOARD_ACTION("pitch_forward", agent_pitch_forward);
+REGISTER_KEYBOARD_ACTION("pitch_backward", agent_pitch_backward);
+REGISTER_KEYBOARD_ACTION("spin_over_agent", agent_spin_over);
+REGISTER_KEYBOARD_ACTION("spin_under_agent", agent_spin_under);
REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
@@ -962,6 +1096,7 @@ REGISTER_KEYBOARD_ACTION("run_backward", run_backward);
REGISTER_KEYBOARD_ACTION("run_left", run_left);
REGISTER_KEYBOARD_ACTION("run_right", run_right);
REGISTER_KEYBOARD_ACTION("toggle_run", toggle_run);
+REGISTER_KEYBOARD_ACTION("toggle_down", agent_toggle_down);
REGISTER_KEYBOARD_ACTION("toggle_sit", toggle_sit);
REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
@@ -970,6 +1105,55 @@ REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton);
+REGISTER_KEYBOARD_ACTION("roll_left", camera_roll_left);
+REGISTER_KEYBOARD_ACTION("roll_right", camera_roll_right);
+REGISTER_KEYBOARD_ACTION("roll_reset", camera_roll_reset);
+REGISTER_KEYBOARD_ACTION("toggle_flycam", agent_toggle_flycam);
+REGISTER_KEYBOARD_ACTION("flycam_move_forward", (flycam_axis_key<LLGameControl::FLYCAM_DOLLY, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_backward", (flycam_axis_key<LLGameControl::FLYCAM_DOLLY, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_truck_left", (flycam_axis_key<LLGameControl::FLYCAM_TRUCK, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_truck_right", (flycam_axis_key<LLGameControl::FLYCAM_TRUCK, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_up", (flycam_axis_key<LLGameControl::FLYCAM_BOOM, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_down", (flycam_axis_key<LLGameControl::FLYCAM_BOOM, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_yaw_left", (flycam_axis_key<LLGameControl::FLYCAM_PAN, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_yaw_right", (flycam_axis_key<LLGameControl::FLYCAM_PAN, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_pitch_up", (flycam_axis_key<LLGameControl::FLYCAM_TILT, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_pitch_down", (flycam_axis_key<LLGameControl::FLYCAM_TILT, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_roll_left", (flycam_axis_key<LLGameControl::FLYCAM_ROLL, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_roll_right", (flycam_axis_key<LLGameControl::FLYCAM_ROLL, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_unroll", flycam_unroll_key);
+REGISTER_KEYBOARD_ACTION("game_control_button_0", game_control_button<0>);
+REGISTER_KEYBOARD_ACTION("game_control_button_1", game_control_button<1>);
+REGISTER_KEYBOARD_ACTION("game_control_button_2", game_control_button<2>);
+REGISTER_KEYBOARD_ACTION("game_control_button_3", game_control_button<3>);
+REGISTER_KEYBOARD_ACTION("game_control_button_4", game_control_button<4>);
+REGISTER_KEYBOARD_ACTION("game_control_button_5", game_control_button<5>);
+REGISTER_KEYBOARD_ACTION("game_control_button_6", game_control_button<6>);
+REGISTER_KEYBOARD_ACTION("game_control_button_7", game_control_button<7>);
+REGISTER_KEYBOARD_ACTION("game_control_button_8", game_control_button<8>);
+REGISTER_KEYBOARD_ACTION("game_control_button_9", game_control_button<9>);
+REGISTER_KEYBOARD_ACTION("game_control_button_10", game_control_button<10>);
+REGISTER_KEYBOARD_ACTION("game_control_button_11", game_control_button<11>);
+REGISTER_KEYBOARD_ACTION("game_control_button_12", game_control_button<12>);
+REGISTER_KEYBOARD_ACTION("game_control_button_13", game_control_button<13>);
+REGISTER_KEYBOARD_ACTION("game_control_button_14", game_control_button<14>);
+REGISTER_KEYBOARD_ACTION("game_control_button_15", game_control_button<15>);
+REGISTER_KEYBOARD_ACTION("game_control_button_16", game_control_button<16>);
+REGISTER_KEYBOARD_ACTION("game_control_button_17", game_control_button<17>);
+REGISTER_KEYBOARD_ACTION("game_control_button_18", game_control_button<18>);
+REGISTER_KEYBOARD_ACTION("game_control_button_19", game_control_button<19>);
+REGISTER_KEYBOARD_ACTION("game_control_button_20", game_control_button<20>);
+REGISTER_KEYBOARD_ACTION("game_control_button_21", game_control_button<21>);
+REGISTER_KEYBOARD_ACTION("game_control_button_22", game_control_button<22>);
+REGISTER_KEYBOARD_ACTION("game_control_button_23", game_control_button<23>);
+REGISTER_KEYBOARD_ACTION("game_control_button_24", game_control_button<24>);
+REGISTER_KEYBOARD_ACTION("game_control_button_25", game_control_button<25>);
+REGISTER_KEYBOARD_ACTION("game_control_button_26", game_control_button<26>);
+REGISTER_KEYBOARD_ACTION("game_control_button_27", game_control_button<27>);
+REGISTER_KEYBOARD_ACTION("game_control_button_28", game_control_button<28>);
+REGISTER_KEYBOARD_ACTION("game_control_button_29", game_control_button<29>);
+REGISTER_KEYBOARD_ACTION("game_control_button_30", game_control_button<30>);
+REGISTER_KEYBOARD_ACTION("game_control_button_31", game_control_button<31>);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1026,6 +1210,11 @@ bool LLViewerInput::modeFromString(const std::string& string, S32 *mode)
*mode = MODE_SITTING;
return true;
}
+ else if (cmp_string == "flycam")
+ {
+ *mode = MODE_FLYCAM;
+ return true;
+ }
S32 val = atoi(string.c_str());
if (val >= 0 && val < MODE_COUNT)
@@ -1175,8 +1364,7 @@ bool LLViewerInput::handleGlobalBindsMouse(EMouseClickType clicktype, MASK mask,
bool LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{
size_t index;
- typedef std::function<bool(EKeystate)> function_t;
- function_t function = nullptr;
+ LLKeyFunc function = nullptr;
std::string name;
// Allow remapping of F2-F12
@@ -1265,8 +1453,7 @@ bool LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons
bool LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name)
{
size_t index;
- typedef std::function<bool(EKeystate)> function_t;
- function_t function = nullptr;
+ LLKeyFunc function = nullptr;
if (mouse == CLICK_LEFT
&& mask == MASK_NONE
@@ -1344,11 +1531,79 @@ bool LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
return true;
}
+bool LLViewerInput::bindController(const S32 mode, const LLGameControl::ActionType actionType, U8 action, const std::string& function_name)
+{
+ size_t index;
+ LLKeyFunc function = nullptr;
+
+ LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
+ if (result)
+ {
+ function = result->mFunction;
+ }
+
+ if (!function)
+ {
+ LL_WARNS_ONCE() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL;
+ return false;
+ }
+
+ if (mode >= MODE_COUNT)
+ {
+ LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+ return false;
+ }
+
+ // check for duplicate first and overwrite
+ if (result->mIsGlobal)
+ {
+ auto size = mGlobalControllerBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (actionType == mGlobalControllerBindings[mode][index].mActionType && action == mGlobalControllerBindings[mode][index].mAction)
+ {
+ mGlobalControllerBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ auto size = mControllerBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (actionType == mControllerBindings[mode][index].mActionType && action == mControllerBindings[mode][index].mAction)
+ {
+ mControllerBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+
+ LLControllerBinding bind;
+ bind.mActionType = actionType;
+ bind.mAction = action;
+ bind.mFunction = function;
+ bind.mFunctionName = function_name;
+
+ if (result->mIsGlobal)
+ {
+ mGlobalControllerBindings[mode].push_back(bind);
+ }
+ else
+ {
+ mControllerBindings[mode].push_back(bind);
+ }
+
+ return true;
+}
+
LLViewerInput::KeyBinding::KeyBinding()
: key("key"),
mouse("mouse"),
mask("mask"),
- command("command")
+ command("command"),
+ controller("controller")
{}
LLViewerInput::KeyMode::KeyMode()
@@ -1360,6 +1615,7 @@ LLViewerInput::Keys::Keys()
third_person("third_person"),
sitting("sitting"),
edit_avatar("edit_avatar"),
+ flycam("flycam"),
xml_version("xml_version", 0)
{}
@@ -1369,8 +1625,10 @@ void LLViewerInput::resetBindings()
{
mGlobalKeyBindings[i].clear();
mGlobalMouseBindings[i].clear();
+ mGlobalControllerBindings[i].clear();
mKeyBindings[i].clear();
mMouseBindings[i].clear();
+ mControllerBindings[i].clear();
mLMouseDefaultHandling[i] = false;
}
}
@@ -1390,8 +1648,11 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON);
binding_count += loadBindingMode(keys.sitting, MODE_SITTING);
binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR);
+ binding_count += loadBindingMode(keys.flycam, MODE_FLYCAM);
// verify version
+ bool needs_rewrite = false;
+
if (keys.xml_version < 1)
{
// updating from a version that was not aware of LMouse bindings
@@ -1427,6 +1688,35 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
keys.edit_avatar.bindings.add(mouse_binding);
}
+ needs_rewrite = true;
+ }
+
+ if (keys.xml_version < 2 && !keys.flycam.isProvided())
+ {
+ // Updating from a version that predates the flycam mode: an old
+ // customized key_bindings.xml has no <flycam> block at all, so
+ // without this fixup the user would get zero flycam keybindings
+ // (no LLKeyConflictHandler-style fallback exists in this runtime
+ // loader). Pull the authoritative default flycam bindings from
+ // the shipped app_settings file and merge them in.
+ std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
+ if (default_filename != filename)
+ {
+ Keys default_keys;
+ LLSimpleXUIParser default_parser;
+ if (default_parser.readXUI(default_filename, default_keys)
+ && default_keys.validateBlock()
+ && default_keys.flycam.isProvided())
+ {
+ keys.flycam.set(default_keys.flycam.getValue(), true);
+ binding_count += loadBindingMode(keys.flycam, MODE_FLYCAM);
+ needs_rewrite = true;
+ }
+ }
+ }
+
+ if (needs_rewrite)
+ {
// fix version
keys.xml_version.set(keybindings_xml_version, true);
@@ -1481,6 +1771,16 @@ bool compare_mouse_by_mask(LLMouseBinding i1, LLMouseBinding i2)
return (count_masks(i1.mMask) > count_masks(i2.mMask));
}
+void LLViewerInput::storeDeltaTime()
+{
+ // measure delta time and frame
+ // Note: it is possible for the deltas to be very large
+ // and it is the duty of the code that uses them to clamp as necessary
+ U64 now = LLFrameTimer::getTotalTime();
+ g_deltaTime = F32(now - g_lastUpdateTime) / (F32)(USEC_PER_SEC);
+ g_lastUpdateTime = now;
+}
+
S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode)
{
S32 binding_count = 0;
@@ -1523,6 +1823,20 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo
LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
}
}
+ if(!processed && it->controller.isProvided() && !it->controller.getValue().empty())
+ {
+ LLGameControl::ActionType actionType;
+ U8 action;
+ if(LLGameControl::actionFromString(it->controller.getValue(), actionType, action))
+ {
+ bindController(mode, actionType, action, it->command);
+ processed = true;
+ }
+ else
+ {
+ LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
+ }
+ }
if (processed)
{
// total
@@ -1539,7 +1853,11 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo
EKeyboardMode LLViewerInput::getMode() const
{
- if ( gAgentCamera.cameraMouselook() )
+ if ( gAgent.isUsingFlycam() )
+ {
+ return MODE_FLYCAM;
+ }
+ else if ( gAgentCamera.cameraMouselook() )
{
return MODE_FIRST_PERSON;
}
@@ -1566,29 +1884,38 @@ bool LLViewerInput::scanKey(const std::vector<LLKeyboardBinding> &binding,
bool key_level,
bool repeat) const
{
+ // TODO implement time
+ LLKeyPressState state = LLKeyPressState(key_up, key_down, key_level, 1.0);
+ state.mRepeat = repeat;
+
for (S32 i = 0; i < binding_count; i++)
{
if (binding[i].mKey == key)
{
if ((binding[i].mMask & mask) == binding[i].mMask)
{
+ state.mElapsedTime = gKeyboard->getCurKeyElapsedTime();
+ state.mElapsedFrames = gKeyboard->getCurKeyElapsedFrameCount();
bool res = false;
if (key_down && !repeat)
{
// ...key went down this frame, call function
- res = binding[i].mFunction( KEYSTATE_DOWN );
+ state.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction( state );
return true;
}
else if (key_up)
{
// ...key went down this frame, call function
- res = binding[i].mFunction( KEYSTATE_UP );
+ state.mState = KEYSTATE_UP;
+ res = binding[i].mFunction( state );
}
else if (key_level)
{
// ...key held down from previous frame
// Not windows, just call the function.
- res = binding[i].mFunction( KEYSTATE_LEVEL );
+ state.mState = KEYSTATE_LEVEL;
+ res = binding[i].mFunction( state );
}//if
// Key+Mask combinations are supposed to be unique, so we won't find anything else
return res;
@@ -1623,6 +1950,82 @@ bool LLViewerInput::scanKey(KEY key, bool key_down, bool key_up, bool key_level)
return res;
}
+bool LLViewerInput::scanControllerInput(const LLGameControl::ActionType actionType, const U8 action, const LLKeyPressState& state) const
+{
+ S32 mode = getMode();
+
+ for(auto binding : mControllerBindings[mode])
+ {
+ if (binding.mActionType != actionType || binding.mAction != action)
+ {
+ continue;
+ }
+
+ LL_WARNS() << "Controller Val " << LLGameControl::stringFromAction(actionType, action) << state.mValue << LL_ENDL;
+
+ bool res = binding.mFunction(state);
+ if (state.mDown)
+ {
+ return true;
+ }
+ return res;
+ }
+ return false;
+}
+
+void LLViewerInput::scanController()
+{
+ LLGameControl::computeFinalState();
+ const LLGameControl::State& state = LLGameControl::getState();
+ // HACK: GameControl: supply hard-coded threshold for ON/OFF zones
+ constexpr U16 AXIS_THRESHOLD = 32768 / 8;
+
+ // TODO: GameControl: This is kind of inificient, it would be more efficient to
+ // loop the bindings and check if the keys/axes they want are active
+ // rather than looping all keys/axes then all bindings for each one
+ // But copying scanMouse pattern for now.
+
+ LLKeyPressState keyState = LLKeyPressState(true, false, false, 0.0);
+ keyState.mAnalog = true;
+
+ for(U8 i = 0;i < state.mAxes.size();i++)
+ {
+ U16 current = state.mAxes[i];
+ U16 prev = state.mPrevAxes[i];
+ keyState.mDown = prev < AXIS_THRESHOLD && current >= AXIS_THRESHOLD;
+ keyState.mLevel = prev >= AXIS_THRESHOLD && current >= AXIS_THRESHOLD;
+ keyState.mUp = prev >= AXIS_THRESHOLD && current < AXIS_THRESHOLD;
+
+ if(keyState.mDown || keyState.mLevel || keyState.mUp)
+ {
+ keyState.mElapsedTime = LLGameControl::getControllerHeldTime(LLGameControl::ActionType::DOF, i);
+ keyState.mElapsedFrames = LLGameControl::getControllerHeldFrames(LLGameControl::ActionType::DOF, i);
+ keyState.mValue = std::clamp(((F32)current) / 32767.0f, 0.0f, 1.0f);
+ keyState.mState = keyState.mDown ? KEYSTATE_DOWN : (keyState.mLevel ? KEYSTATE_LEVEL : KEYSTATE_UP);
+ scanControllerInput(LLGameControl::ActionType::DOF, i, keyState);
+ }
+ }
+
+ keyState.mAnalog = false;
+ for(U8 i = 0; i < LLGameControl::Button::NUM_BUTTONS; i++)
+ {
+ U32 flag = 1 << i;
+ bool current = (state.mButtons & flag) == flag;
+ bool prev = (state.mPrevButtons & flag) == flag;
+ if(current || prev)
+ {
+ keyState.mDown = current && !prev;
+ keyState.mLevel = current && prev;
+ keyState.mUp = !current && prev;
+ keyState.mElapsedTime = LLGameControl::getControllerHeldTime(LLGameControl::ActionType::BUTTON, i);
+ keyState.mElapsedFrames = LLGameControl::getControllerHeldFrames(LLGameControl::ActionType::BUTTON, i);
+ keyState.mValue = current ? 1.0f : 0.0f;
+ keyState.mState = keyState.mDown ? KEYSTATE_DOWN : (keyState.mLevel ? KEYSTATE_LEVEL : KEYSTATE_UP);
+ scanControllerInput(LLGameControl::ActionType::BUTTON, i, keyState);
+ }
+ }
+}
+
bool LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, bool down)
{
bool is_toolmgr_action = false;
@@ -1742,6 +2145,7 @@ bool LLViewerInput::scanMouse(
bool ignore_additional_masks
) const
{
+ LLKeyPressState keyState = LLKeyPressState(false,false,false,1.0);
for (S32 i = 0; i < binding_count; i++)
{
if (binding[i].mMouse == mouse && (ignore_additional_masks ? (binding[i].mMask & mask) == binding[i].mMask : binding[i].mMask == mask))
@@ -1750,20 +2154,31 @@ bool LLViewerInput::scanMouse(
switch (state)
{
case MOUSE_STATE_DOWN:
- res = binding[i].mFunction(KEYSTATE_DOWN);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction(keyState);
break;
case MOUSE_STATE_CLICK:
// Button went down and up in scope of single frame
// might not work best with some functions,
// but some function need specific states specifically
- res = binding[i].mFunction(KEYSTATE_DOWN);
- res |= binding[i].mFunction(KEYSTATE_UP);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction(keyState);
+ keyState.mDown = false;
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ res |= binding[i].mFunction(keyState);
break;
case MOUSE_STATE_LEVEL:
- res = binding[i].mFunction(KEYSTATE_LEVEL);
+ keyState.mLevel = true;
+ keyState.mState = KEYSTATE_LEVEL;
+ res = binding[i].mFunction(keyState);
break;
case MOUSE_STATE_UP:
- res = binding[i].mFunction(KEYSTATE_UP);
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ res = binding[i].mFunction(keyState);
break;
default:
break;
@@ -1775,7 +2190,7 @@ bool LLViewerInput::scanMouse(
return false;
}
-// todo: this recods key, scanMouse() triggers functions with EKeystate
+// todo: this recods key, scanMouse() triggers functions with LLKeyPressState
bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
{
bool res = false;
@@ -1790,6 +2205,8 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
// and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls
// are leftButtonGrabbed(), send a normal click otherwise.
+ LLKeyPressState keyState = LLKeyPressState(false,false,false,1.0);
+
if (!res
&& mLMouseDefaultHandling[mode]
&& (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed())
@@ -1799,18 +2216,27 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
switch (state)
{
case MOUSE_STATE_DOWN:
- agent_control_lbutton_handle(KEYSTATE_DOWN);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
case MOUSE_STATE_CLICK:
// might not work best with some functions,
// but some function need specific states too specifically
- agent_control_lbutton_handle(KEYSTATE_DOWN);
- agent_control_lbutton_handle(KEYSTATE_UP);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ agent_control_lbutton_handle(keyState);
+ keyState.mDown = false;
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
case MOUSE_STATE_UP:
- agent_control_lbutton_handle(KEYSTATE_UP);
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
default: