2020-04-08 10:48:23 +00:00
# include "mousemanager.hpp"
# include <MyGUI_Button.h>
# include <MyGUI_InputManager.h>
# include <MyGUI_RenderManager.h>
# include <MyGUI_Widget.h>
# include <components/debug/debuglog.hpp>
# include <components/sdlutil/sdlinputwrapper.hpp>
# include "../mwbase/environment.hpp"
# include "../mwbase/inputmanager.hpp"
# include "../mwbase/windowmanager.hpp"
# include "../mwbase/world.hpp"
# include "../mwworld/player.hpp"
# include "actions.hpp"
2020-04-17 11:21:23 +00:00
# include "bindingsmanager.hpp"
2020-04-08 10:48:23 +00:00
# include "sdlmappings.hpp"
namespace MWInput
{
2020-04-17 11:21:23 +00:00
MouseManager : : MouseManager ( BindingsManager * bindingsManager , SDLUtil : : InputWrapper * inputWrapper , SDL_Window * window )
2020-04-08 10:48:23 +00:00
: mInvertX ( Settings : : Manager : : getBool ( " invert x axis " , " Input " ) )
, mInvertY ( Settings : : Manager : : getBool ( " invert y axis " , " Input " ) )
2020-05-26 07:24:47 +00:00
, mGrabCursor ( Settings : : Manager : : getBool ( " grab cursor " , " Input " ) )
, mCameraSensitivity ( Settings : : Manager : : getFloat ( " camera sensitivity " , " Input " ) )
, mCameraYMultiplier ( Settings : : Manager : : getFloat ( " camera y multiplier " , " Input " ) )
2020-04-17 11:21:23 +00:00
, mBindingsManager ( bindingsManager )
2020-04-08 10:48:23 +00:00
, mInputWrapper ( inputWrapper )
, mInvUiScalingFactor ( 1.f )
, mGuiCursorX ( 0 )
, mGuiCursorY ( 0 )
, mMouseWheel ( 0 )
, mMouseLookEnabled ( false )
, mGuiCursorEnabled ( true )
{
float uiScale = Settings : : Manager : : getFloat ( " scaling factor " , " GUI " ) ;
if ( uiScale ! = 0.f )
mInvUiScalingFactor = 1.f / uiScale ;
int w , h ;
SDL_GetWindowSize ( window , & w , & h ) ;
mGuiCursorX = mInvUiScalingFactor * w / 2.f ;
mGuiCursorY = mInvUiScalingFactor * h / 2.f ;
}
void MouseManager : : processChangedSettings ( const Settings : : CategorySettingVector & changed )
{
2020-04-17 11:21:23 +00:00
for ( const auto & setting : changed )
2020-04-08 10:48:23 +00:00
{
2020-04-17 11:21:23 +00:00
if ( setting . first = = " Input " & & setting . second = = " invert x axis " )
2020-04-08 10:48:23 +00:00
mInvertX = Settings : : Manager : : getBool ( " invert x axis " , " Input " ) ;
2020-04-17 11:21:23 +00:00
if ( setting . first = = " Input " & & setting . second = = " invert y axis " )
2020-04-08 10:48:23 +00:00
mInvertY = Settings : : Manager : : getBool ( " invert y axis " , " Input " ) ;
2020-04-17 11:21:23 +00:00
if ( setting . first = = " Input " & & setting . second = = " camera sensitivity " )
2020-04-08 10:48:23 +00:00
mCameraSensitivity = Settings : : Manager : : getFloat ( " camera sensitivity " , " Input " ) ;
2020-05-26 07:24:47 +00:00
if ( setting . first = = " Input " & & setting . second = = " grab cursor " )
mGrabCursor = Settings : : Manager : : getBool ( " grab cursor " , " Input " ) ;
2020-04-08 10:48:23 +00:00
}
}
void MouseManager : : mouseMoved ( const SDLUtil : : MouseMotionEvent & arg )
{
2020-04-17 11:21:23 +00:00
mBindingsManager - > mouseMoved ( arg ) ;
2020-04-08 10:48:23 +00:00
MWBase : : InputManager * input = MWBase : : Environment : : get ( ) . getInputManager ( ) ;
input - > setJoystickLastUsed ( false ) ;
input - > resetIdleTime ( ) ;
if ( mGuiCursorEnabled )
{
input - > setGamepadGuiCursorEnabled ( true ) ;
// We keep track of our own mouse position, so that moving the mouse while in
// game mode does not move the position of the GUI cursor
mGuiCursorX = static_cast < float > ( arg . x ) * mInvUiScalingFactor ;
mGuiCursorY = static_cast < float > ( arg . y ) * mInvUiScalingFactor ;
mMouseWheel = static_cast < int > ( arg . z ) ;
MyGUI : : InputManager : : getInstance ( ) . injectMouseMove ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , mMouseWheel ) ;
// FIXME: inject twice to force updating focused widget states (tooltips) resulting from changing the viewport by scroll wheel
MyGUI : : InputManager : : getInstance ( ) . injectMouseMove ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , mMouseWheel ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setCursorActive ( true ) ;
}
2020-05-26 06:58:24 +00:00
if ( mMouseLookEnabled & & ! input - > controlsDisabled ( ) )
2020-04-08 10:48:23 +00:00
{
2020-04-17 13:06:19 +00:00
float x = arg . xrel * mCameraSensitivity * ( mInvertX ? - 1 : 1 ) / 256.f ;
float y = arg . yrel * mCameraSensitivity * ( mInvertY ? - 1 : 1 ) * mCameraYMultiplier / 256.f ;
2020-04-08 10:48:23 +00:00
float rot [ 3 ] ;
rot [ 0 ] = - y ;
rot [ 1 ] = 0.0f ;
rot [ 2 ] = - x ;
// Only actually turn player when we're not in vanity mode
2020-04-17 12:51:47 +00:00
if ( ! MWBase : : Environment : : get ( ) . getWorld ( ) - > vanityRotateCamera ( rot ) & & input - > getControlSwitch ( " playerlooking " ) )
2020-04-08 10:48:23 +00:00
{
MWWorld : : Player & player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayer ( ) ;
player . yaw ( x ) ;
player . pitch ( y ) ;
}
if ( arg . zrel & & input - > getControlSwitch ( " playerviewswitch " ) & & input - > getControlSwitch ( " playercontrols " ) ) //Check to make sure you are allowed to zoomout and there is a change
{
MWBase : : Environment : : get ( ) . getWorld ( ) - > changeVanityModeScale ( static_cast < float > ( arg . zrel ) ) ;
}
}
}
void MouseManager : : mouseReleased ( const SDL_MouseButtonEvent & arg , Uint8 id )
{
MWBase : : Environment : : get ( ) . getInputManager ( ) - > setJoystickLastUsed ( false ) ;
2020-04-17 13:06:19 +00:00
if ( mBindingsManager - > isDetectingBindingState ( ) )
2020-04-08 10:48:23 +00:00
{
2020-04-17 11:21:23 +00:00
mBindingsManager - > mouseReleased ( arg , id ) ;
2020-04-08 10:48:23 +00:00
}
else
{
bool guiMode = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) ;
guiMode = MyGUI : : InputManager : : getInstance ( ) . injectMouseRelease ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , sdlButtonToMyGUI ( id ) ) & & guiMode ;
2020-04-17 12:51:47 +00:00
if ( mBindingsManager - > isDetectingBindingState ( ) )
return ; // don't allow same mouseup to bind as initiated bind
2020-04-08 10:48:23 +00:00
2020-04-17 11:21:23 +00:00
mBindingsManager - > setPlayerControlsEnabled ( ! guiMode ) ;
mBindingsManager - > mouseReleased ( arg , id ) ;
2020-04-08 10:48:23 +00:00
}
}
void MouseManager : : mouseWheelMoved ( const SDL_MouseWheelEvent & arg )
{
2020-05-26 06:58:24 +00:00
MWBase : : InputManager * input = MWBase : : Environment : : get ( ) . getInputManager ( ) ;
if ( mBindingsManager - > isDetectingBindingState ( ) | | ! input - > controlsDisabled ( ) )
2020-04-17 11:21:23 +00:00
mBindingsManager - > mouseWheelMoved ( arg ) ;
2020-04-08 10:48:23 +00:00
2020-05-26 06:58:24 +00:00
input - > setJoystickLastUsed ( false ) ;
2020-04-08 10:48:23 +00:00
}
void MouseManager : : mousePressed ( const SDL_MouseButtonEvent & arg , Uint8 id )
{
MWBase : : Environment : : get ( ) . getInputManager ( ) - > setJoystickLastUsed ( false ) ;
bool guiMode = false ;
if ( id = = SDL_BUTTON_LEFT | | id = = SDL_BUTTON_RIGHT ) // MyGUI only uses these mouse events
{
guiMode = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) ;
guiMode = MyGUI : : InputManager : : getInstance ( ) . injectMousePress ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , sdlButtonToMyGUI ( id ) ) & & guiMode ;
2020-04-17 12:51:47 +00:00
if ( MyGUI : : InputManager : : getInstance ( ) . getMouseFocusWidget ( ) ! = 0 )
2020-04-08 10:48:23 +00:00
{
2020-04-17 12:51:47 +00:00
MyGUI : : Button * b = MyGUI : : InputManager : : getInstance ( ) . getMouseFocusWidget ( ) - > castType < MyGUI : : Button > ( false ) ;
2020-04-08 10:48:23 +00:00
if ( b & & b - > getEnabled ( ) & & id = = SDL_BUTTON_LEFT )
{
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > playSound ( " Menu Click " ) ;
}
}
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setCursorActive ( true ) ;
}
2020-04-17 11:21:23 +00:00
mBindingsManager - > setPlayerControlsEnabled ( ! guiMode ) ;
2020-04-08 10:48:23 +00:00
// Don't trigger any mouse bindings while in settings menu, otherwise rebinding controls becomes impossible
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMode ( ) ! = MWGui : : GM_Settings )
2020-04-17 11:21:23 +00:00
mBindingsManager - > mousePressed ( arg , id ) ;
2020-04-08 10:48:23 +00:00
}
2020-05-26 07:24:47 +00:00
void MouseManager : : updateCursorMode ( )
{
bool grab = ! MWBase : : Environment : : get ( ) . getWindowManager ( ) - > containsMode ( MWGui : : GM_MainMenu )
& & ! MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isConsoleMode ( ) ;
bool wasRelative = mInputWrapper - > getMouseRelative ( ) ;
bool isRelative = ! MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isGuiMode ( ) ;
// don't keep the pointer away from the window edge in gui mode
// stop using raw mouse motions and switch to system cursor movements
mInputWrapper - > setMouseRelative ( isRelative ) ;
//we let the mouse escape in the main menu
mInputWrapper - > setGrabPointer ( grab & & ( mGrabCursor | | isRelative ) ) ;
//we switched to non-relative mode, move our cursor to where the in-game
//cursor is
if ( ! isRelative & & wasRelative ! = isRelative )
{
warpMouse ( ) ;
}
}
2020-05-26 06:58:24 +00:00
void MouseManager : : update ( float dt )
2020-04-08 10:48:23 +00:00
{
if ( ! mMouseLookEnabled )
2020-04-16 12:36:32 +00:00
return ;
2020-04-08 10:48:23 +00:00
2020-04-17 13:06:19 +00:00
float xAxis = mBindingsManager - > getActionValue ( A_LookLeftRight ) * 2.0f - 1.0f ;
float yAxis = mBindingsManager - > getActionValue ( A_LookUpDown ) * 2.0f - 1.0f ;
2020-04-08 10:48:23 +00:00
if ( xAxis = = 0 & & yAxis = = 0 )
2020-04-16 12:36:32 +00:00
return ;
2020-04-08 10:48:23 +00:00
float rot [ 3 ] ;
2020-04-17 13:06:19 +00:00
rot [ 0 ] = yAxis * dt * 1000.0f * mCameraSensitivity * ( mInvertY ? - 1 : 1 ) * mCameraYMultiplier / 256.f ;
2020-04-08 10:48:23 +00:00
rot [ 1 ] = 0.0f ;
2020-04-17 13:06:19 +00:00
rot [ 2 ] = xAxis * dt * 1000.0f * mCameraSensitivity * ( mInvertX ? - 1 : 1 ) / 256.f ;
2020-04-08 10:48:23 +00:00
// Only actually turn player when we're not in vanity mode
2020-04-17 13:06:19 +00:00
if ( ! MWBase : : Environment : : get ( ) . getWorld ( ) - > vanityRotateCamera ( rot ) & & MWBase : : Environment : : get ( ) . getInputManager ( ) - > getControlSwitch ( " playercontrols " ) )
2020-04-08 10:48:23 +00:00
{
MWWorld : : Player & player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayer ( ) ;
player . yaw ( rot [ 2 ] ) ;
player . pitch ( rot [ 0 ] ) ;
}
2020-04-16 12:36:32 +00:00
MWBase : : Environment : : get ( ) . getInputManager ( ) - > resetIdleTime ( ) ;
2020-04-08 10:48:23 +00:00
}
bool MouseManager : : injectMouseButtonPress ( Uint8 button )
{
return MyGUI : : InputManager : : getInstance ( ) . injectMousePress ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , sdlButtonToMyGUI ( button ) ) ;
}
bool MouseManager : : injectMouseButtonRelease ( Uint8 button )
{
return MyGUI : : InputManager : : getInstance ( ) . injectMousePress ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , sdlButtonToMyGUI ( button ) ) ;
}
void MouseManager : : injectMouseMove ( int xMove , int yMove , int mouseWheelMove )
{
mGuiCursorX + = xMove ;
mGuiCursorY + = yMove ;
mMouseWheel + = mouseWheelMove ;
const MyGUI : : IntSize & viewSize = MyGUI : : RenderManager : : getInstance ( ) . getViewSize ( ) ;
2020-04-17 13:06:19 +00:00
mGuiCursorX = std : : max ( 0.f , std : : min ( mGuiCursorX , float ( viewSize . width - 1 ) ) ) ;
mGuiCursorY = std : : max ( 0.f , std : : min ( mGuiCursorY , float ( viewSize . height - 1 ) ) ) ;
2020-04-08 10:48:23 +00:00
MyGUI : : InputManager : : getInstance ( ) . injectMouseMove ( static_cast < int > ( mGuiCursorX ) , static_cast < int > ( mGuiCursorY ) , mMouseWheel ) ;
}
void MouseManager : : warpMouse ( )
{
2020-04-17 13:06:19 +00:00
mInputWrapper - > warpMouse ( static_cast < int > ( mGuiCursorX / mInvUiScalingFactor ) , static_cast < int > ( mGuiCursorY / mInvUiScalingFactor ) ) ;
2020-04-08 10:48:23 +00:00
}
}