@@ -1,34 +1,527 @@
// 4J_Input.cpp - GLFW keyboard + mouse input for the Linux port
// Replaces the SDL2 oldimpl with GLFW equivalents.
// Uses glfwGetCurrentContext() to get the window the render manager created,
// avoiding a coupling dependency on 4J_Render.h.
# include "4J_Input.h"
# include "../Minecraft.Client/Build/Common/App_enums.h"
# include <GLFW/glfw3.h>
# include <math.h>
# include <string.h>
# include <stdio.h>
C_4JInput InputManager ;
void C_4JInput : : Initialise ( int iInputStateC , unsigned char ucMapC , unsigned char ucActionC , unsigned char ucMenuActionC ) { }
void C_4JInput : : Tick ( void ) { }
void C_4JInput : : SetDeadzoneAndMovementRange ( unsigned int uiDeadzone , unsigned int uiMovementRangeMax ) { }
void C_4JInput : : SetGameJoypadMaps ( unsigned char ucMap , unsigned char ucAction , unsigned int uiActionVal ) { }
unsigned int C_4JInput : : GetGameJoypadMaps ( unsigned char ucMap , unsigned char ucAction ) { return 0 ; }
void C_4JInput : : SetJoypadMapVal ( int iPad , unsigned char ucMap ) { }
unsigned char C_4JInput : : GetJoypadMapVal ( int iPad ) { return 0 ; }
void C_4JInput : : SetJoypadSensitivity ( int iPad , float fSensitivity ) { }
unsigned int C_4JInput : : GetValue ( int iPad , unsigned char ucAction , bool bRepeat ) { return 0 ; }
bool C_4JInput : : ButtonPressed ( int iPad , unsigned char ucAction ) { return false ; }
bool C_4JInput : : ButtonReleased ( int iPad , unsigned char ucAction ) { return false ; }
bool C_4JInput : : ButtonDown ( int iPad , unsigned char ucAction ) { return false ; }
void C_4JInput : : SetJoypadStickAxisMap ( int iPad , unsigned int uiFrom , unsigned int uiTo ) { }
void C_4JInput : : SetJoypadStickTriggerMap ( int iPad , unsigned int uiFrom , unsigned int uiTo ) { }
void C_4JInput : : SetKeyRepeatRate ( float fRepeatDelaySecs , float fRepeatRateSecs ) { }
void C_4JInput : : SetDebugSequence ( const char * chSequenceA , int ( * Func ) ( LPVOID ) , LPVOID lpParam ) { }
FLOAT C_4JInput : : GetIdleSeconds ( int iPad ) { return 0.0f ; }
bool C_4JInput : : IsPadConnected ( int iPad ) { return iPad = = 0 ; }
float C_4JInput : : GetJoypadStick_LX ( int iPad , bool bCheckMenuDisplay ) { return 0.0f ; }
float C_4JInput : : GetJoypadStick_LY ( int iPad , bool bCheckMenuDisplay ) { return 0.0f ; }
float C_4JInput : : GetJoypadStick_RX ( int iPad , bool bCheckMenuDisplay ) { return 0.0f ; }
float C_4JInput : : GetJoypadStick_RY ( int iPad , bool bCheckMenuDisplay ) { return 0.0f ; }
unsigned char C_4JInput : : GetJoypadLTrigger ( int iPad , bool bCheckMenuDisplay ) { return 0 ; }
unsigned char C_4JInput : : GetJoypadRTrigger ( int iPad , bool bCheckMenuDisplay ) { return 0 ; }
void C_4JInput : : SetMenuDisplayed ( int iPad , bool bVal ) { }
EKeyboardResult C_4JInput : : RequestKeyboard ( LPCWSTR Title , LPCWSTR Text , DWORD dwPad , UINT uiMaxChars , int ( * Func ) ( LPVOID , const bool ) , LPVOID lpParam , C_4JInput : : EKeyboardMode eMode ) { return EKeyboard_Cancelled ; }
// ---------------------------------------------------------------------------
// State - all static to avoid adding new fields to C_4JInput
// ---------------------------------------------------------------------------
static const int KEY_COUNT = GLFW_KEY_LAST + 1 ; // 349 on GLFW 3
static bool s_keysCurrent [ KEY_COUNT ] = { } ;
static bool s_keysPrev [ KEY_COUNT ] = { } ;
static bool s_mouseLeftCurrent = false , s_mouseLeftPrev = false ;
static bool s_mouseRightCurrent = false , s_mouseRightPrev = false ;
// Accumulated cursor delta from the GLFW cursor-pos callback.
// Snapshotted into s_frameRelX/Y at Tick() start, then reset to 0.
static double s_lastCursorX = 0.0 , s_lastCursorY = 0.0 ;
static bool s_cursorInitialized = false ;
static float s_mouseAccumX = 0.0f , s_mouseAccumY = 0.0f ; // callback accumulator
static float s_frameRelX = 0.0f , s_frameRelY = 0.0f ; // per-frame snapshot
// Scroll wheel
static float s_scrollAccum = 0.0f ; // callback accumulator
static float s_scrollFrame = 0.0f ; // current frame snapshot
static float s_scrollPrevFrame = 0.0f ;
// Mouse lock / menu state
static bool s_mouseLocked = false ;
static bool s_menuDisplayed [ 4 ] = { } ;
static bool s_prevMenuDisplayed = true ; // start as "in menu" so auto-lock triggers after first frame
// Sensitivity: scales raw pixel delta before sqrt-compression
// Smaller value = less mouse movement per pixel
static const float MOUSE_SCALE = 0.012f ;
// ---------------------------------------------------------------------------
// GLFW window (obtained lazily via glfwGetCurrentContext on the render thread)
// ---------------------------------------------------------------------------
static GLFWwindow * s_inputWindow = nullptr ;
static GLFWwindow * getWindow ( ) {
if ( ! s_inputWindow ) {
s_inputWindow = glfwGetCurrentContext ( ) ;
}
return s_inputWindow ;
}
// ---------------------------------------------------------------------------
// GLFW callbacks
// ---------------------------------------------------------------------------
static void onCursorPos ( GLFWwindow * /*w*/ , double x , double y ) {
if ( s_cursorInitialized ) {
s_mouseAccumX + = ( float ) ( x - s_lastCursorX ) ;
s_mouseAccumY + = ( float ) ( y - s_lastCursorY ) ;
} else {
s_cursorInitialized = true ;
}
s_lastCursorX = x ;
s_lastCursorY = y ;
}
static void onScroll ( GLFWwindow * /*w*/ , double /*xoffset*/ , double yoffset ) {
s_scrollAccum + = ( float ) yoffset ;
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
static inline bool KDown ( int key ) {
return ( key > = 0 & & key < KEY_COUNT ) ? s_keysCurrent [ key ] : false ;
}
static inline bool KPressed ( int key ) {
return ( key > = 0 & & key < KEY_COUNT ) ? ( s_keysCurrent [ key ] & & ! s_keysPrev [ key ] ) : false ;
}
static inline bool KReleased ( int key ) {
return ( key > = 0 & & key < KEY_COUNT ) ? ( ! s_keysCurrent [ key ] & & s_keysPrev [ key ] ) : false ;
}
static inline bool MouseLDown ( ) { return s_mouseLeftCurrent ; }
static inline bool MouseLPressed ( ) { return s_mouseLeftCurrent & & ! s_mouseLeftPrev ; }
static inline bool MouseLReleased ( ) { return ! s_mouseLeftCurrent & & s_mouseLeftPrev ; }
static inline bool MouseRDown ( ) { return s_mouseRightCurrent ; }
static inline bool MouseRPressed ( ) { return s_mouseRightCurrent & & ! s_mouseRightPrev ; }
static inline bool MouseRReleased ( ) { return ! s_mouseRightCurrent & & s_mouseRightPrev ; }
static inline bool WheelUp ( ) { return s_scrollFrame > 0.1f ; }
static inline bool WheelDown ( ) { return s_scrollFrame < - 0.1f ; }
static inline bool WheelUpEdge ( ) { return s_scrollFrame > 0.1f & & s_scrollPrevFrame < = 0.1f ; }
static inline bool WheelDownEdge ( ) { return s_scrollFrame < - 0.1f & & s_scrollPrevFrame > = - 0.1f ; }
// Keys to snapshot each Tick (avoid iterating all 349 entries)
static const int s_watchedKeys [ ] = {
GLFW_KEY_W , GLFW_KEY_A , GLFW_KEY_S , GLFW_KEY_D ,
GLFW_KEY_SPACE , GLFW_KEY_LEFT_SHIFT , GLFW_KEY_RIGHT_SHIFT ,
GLFW_KEY_E , GLFW_KEY_Q , GLFW_KEY_F ,
GLFW_KEY_ESCAPE , GLFW_KEY_ENTER ,
GLFW_KEY_F3 , GLFW_KEY_F5 ,
GLFW_KEY_UP , GLFW_KEY_DOWN , GLFW_KEY_LEFT , GLFW_KEY_RIGHT ,
GLFW_KEY_PAGE_UP , GLFW_KEY_PAGE_DOWN ,
GLFW_KEY_TAB ,
GLFW_KEY_LEFT_CONTROL , GLFW_KEY_RIGHT_CONTROL ,
GLFW_KEY_1 , GLFW_KEY_2 , GLFW_KEY_3 , GLFW_KEY_4 , GLFW_KEY_5 ,
GLFW_KEY_6 , GLFW_KEY_7 , GLFW_KEY_8 , GLFW_KEY_9 ,
} ;
static const int s_watchedKeyCount = ( int ) ( sizeof ( s_watchedKeys ) / sizeof ( s_watchedKeys [ 0 ] ) ) ;
// ---------------------------------------------------------------------------
// C_4JInput::Initialise
// ---------------------------------------------------------------------------
void C_4JInput : : Initialise ( int /*iInputStateC*/ , unsigned char /*ucMapC*/ ,
unsigned char /*ucActionC*/ , unsigned char /*ucMenuActionC*/ ) {
memset ( s_keysCurrent , 0 , sizeof ( s_keysCurrent ) ) ;
memset ( s_keysPrev , 0 , sizeof ( s_keysPrev ) ) ;
memset ( s_menuDisplayed , 0 , sizeof ( s_menuDisplayed ) ) ;
s_mouseLeftCurrent = s_mouseLeftPrev = false ;
s_mouseRightCurrent = s_mouseRightPrev = false ;
s_mouseAccumX = s_mouseAccumY = 0.0f ;
s_frameRelX = s_frameRelY = 0.0f ;
s_scrollAccum = s_scrollFrame = s_scrollPrevFrame = 0.0f ;
s_mouseLocked = false ;
s_prevMenuDisplayed = true ; // triggers auto-lock once game leaves first menu
s_cursorInitialized = false ;
GLFWwindow * w = getWindow ( ) ;
if ( w ) {
glfwSetCursorPosCallback ( w , onCursorPos ) ;
glfwSetScrollCallback ( w , onScroll ) ;
if ( glfwRawMouseMotionSupported ( ) ) {
glfwSetInputMode ( w , GLFW_RAW_MOUSE_MOTION , GLFW_TRUE ) ;
}
}
printf ( " [4J_Input] GLFW input initialised \n " ) ;
printf ( " WASD=move Mouse=look LMB=attack RMB=use \n " ) ;
printf ( " Space=jump LShift=sneak E=inventory Q=drop Esc=pause \n " ) ;
printf ( " F5=3rd-person F3=debug Scroll=hotbar \n " ) ;
fflush ( stdout ) ;
}
// ---------------------------------------------------------------------------
// C_4JInput::Tick (called once per frame, BEFORE Present / glfwPollEvents)
// ---------------------------------------------------------------------------
void C_4JInput : : Tick ( void ) {
GLFWwindow * w = getWindow ( ) ;
if ( ! w ) return ;
// 1. Save previous frame
memcpy ( s_keysPrev , s_keysCurrent , sizeof ( s_keysCurrent ) ) ;
s_mouseLeftPrev = s_mouseLeftCurrent ;
s_mouseRightPrev = s_mouseRightCurrent ;
s_scrollPrevFrame = s_scrollFrame ;
// 2. Snapshot current keyboard state for watched keys
for ( int i = 0 ; i < s_watchedKeyCount ; i + + ) {
int k = s_watchedKeys [ i ] ;
s_keysCurrent [ k ] = ( glfwGetKey ( w , k ) = = GLFW_PRESS ) ;
}
// 3. Snapshot and reset scroll accumulator
s_scrollFrame = s_scrollAccum ;
s_scrollAccum = 0.0f ;
// 4. Mouse-lock management based on menu display state
bool menuNow = s_menuDisplayed [ 0 ] ;
if ( menuNow & & s_mouseLocked ) {
// Re-entered a menu → release mouse cursor
s_mouseLocked = false ;
glfwSetInputMode ( w , GLFW_CURSOR , GLFW_CURSOR_NORMAL ) ;
// Discard stale delta so the view doesn't jerk on re-lock
s_mouseAccumX = s_mouseAccumY = 0.0f ;
s_cursorInitialized = false ;
}
if ( ! menuNow & & s_prevMenuDisplayed & & ! s_mouseLocked ) {
// Left the menu → lock mouse for look control
s_mouseLocked = true ;
glfwSetInputMode ( w , GLFW_CURSOR , GLFW_CURSOR_DISABLED ) ;
s_mouseAccumX = s_mouseAccumY = 0.0f ;
s_cursorInitialized = false ;
}
s_prevMenuDisplayed = menuNow ;
// 5. Snapshot and reset mouse delta from callback
s_frameRelX = s_mouseAccumX ;
s_frameRelY = s_mouseAccumY ;
s_mouseAccumX = s_mouseAccumY = 0.0f ;
// 6. Mouse buttons (only meaningful when locked in-game)
if ( s_mouseLocked ) {
s_mouseLeftCurrent = ( glfwGetMouseButton ( w , GLFW_MOUSE_BUTTON_LEFT ) = = GLFW_PRESS ) ;
s_mouseRightCurrent = ( glfwGetMouseButton ( w , GLFW_MOUSE_BUTTON_RIGHT ) = = GLFW_PRESS ) ;
} else {
// Not locked. Allow a left-click to re-lock (if not in a menu)
bool lclick = ( glfwGetMouseButton ( w , GLFW_MOUSE_BUTTON_LEFT ) = = GLFW_PRESS ) ;
if ( ! menuNow & & lclick ) {
s_mouseLocked = true ;
glfwSetInputMode ( w , GLFW_CURSOR , GLFW_CURSOR_DISABLED ) ;
s_mouseAccumX = s_mouseAccumY = 0.0f ;
s_cursorInitialized = false ;
}
s_mouseLeftCurrent = false ;
s_mouseRightCurrent = false ;
s_frameRelX = s_frameRelY = 0.0f ;
}
}
// ---------------------------------------------------------------------------
// ButtonDown – is action held this frame?
// ---------------------------------------------------------------------------
bool C_4JInput : : ButtonDown ( int /*iPad*/ , unsigned char ucAction ) {
switch ( ucAction ) {
// ---- Menu navigation ----
case ACTION_MENU_UP : return KDown ( GLFW_KEY_UP ) | | KDown ( GLFW_KEY_W ) ;
case ACTION_MENU_DOWN : return KDown ( GLFW_KEY_DOWN ) | | KDown ( GLFW_KEY_S ) ;
case ACTION_MENU_LEFT : return KDown ( GLFW_KEY_LEFT ) | | KDown ( GLFW_KEY_A ) ;
case ACTION_MENU_RIGHT : return KDown ( GLFW_KEY_RIGHT ) | | KDown ( GLFW_KEY_D ) ;
case ACTION_MENU_A :
case ACTION_MENU_OK :
return KDown ( GLFW_KEY_ENTER ) | | KDown ( GLFW_KEY_SPACE ) ;
case ACTION_MENU_B :
case ACTION_MENU_CANCEL :
return KDown ( GLFW_KEY_ESCAPE ) ;
case ACTION_MENU_X : return KDown ( GLFW_KEY_F ) ;
case ACTION_MENU_Y : return KDown ( GLFW_KEY_E ) ;
case ACTION_MENU_PAGEUP : return KDown ( GLFW_KEY_PAGE_UP ) | | KDown ( GLFW_KEY_LEFT_SHIFT ) ;
case ACTION_MENU_PAGEDOWN : return KDown ( GLFW_KEY_PAGE_DOWN ) | | KDown ( GLFW_KEY_RIGHT_SHIFT ) ;
case ACTION_MENU_RIGHT_SCROLL : return KDown ( GLFW_KEY_RIGHT_SHIFT ) | | WheelUp ( ) ;
case ACTION_MENU_LEFT_SCROLL : return KDown ( GLFW_KEY_LEFT_SHIFT ) | | WheelDown ( ) ;
case ACTION_MENU_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_UP : return KDown ( GLFW_KEY_UP ) ;
case ACTION_MENU_OTHER_STICK_DOWN : return KDown ( GLFW_KEY_DOWN ) ;
case ACTION_MENU_OTHER_STICK_LEFT : return KDown ( GLFW_KEY_LEFT ) ;
case ACTION_MENU_OTHER_STICK_RIGHT : return KDown ( GLFW_KEY_RIGHT ) ;
case ACTION_MENU_PAUSEMENU : return KDown ( GLFW_KEY_ESCAPE ) ;
// ---- Minecraft in-game ----
case MINECRAFT_ACTION_JUMP : return KDown ( GLFW_KEY_SPACE ) ;
case MINECRAFT_ACTION_FORWARD : return KDown ( GLFW_KEY_W ) ;
case MINECRAFT_ACTION_BACKWARD : return KDown ( GLFW_KEY_S ) ;
case MINECRAFT_ACTION_LEFT : return KDown ( GLFW_KEY_A ) ;
case MINECRAFT_ACTION_RIGHT : return KDown ( GLFW_KEY_D ) ;
// Look axes are handled by analog stick RX/RY (mouse)
case MINECRAFT_ACTION_LOOK_LEFT : return false ;
case MINECRAFT_ACTION_LOOK_RIGHT : return false ;
case MINECRAFT_ACTION_LOOK_UP : return false ;
case MINECRAFT_ACTION_LOOK_DOWN : return false ;
case MINECRAFT_ACTION_USE : return MouseRDown ( ) ;
case MINECRAFT_ACTION_ACTION : return MouseLDown ( ) ;
case MINECRAFT_ACTION_LEFT_SCROLL : return WheelDown ( ) ;
case MINECRAFT_ACTION_RIGHT_SCROLL : return WheelUp ( ) ;
case MINECRAFT_ACTION_INVENTORY : return KDown ( GLFW_KEY_E ) ;
case MINECRAFT_ACTION_PAUSEMENU : return KDown ( GLFW_KEY_ESCAPE ) ;
case MINECRAFT_ACTION_DROP : return KDown ( GLFW_KEY_Q ) ;
case MINECRAFT_ACTION_SNEAK_TOGGLE : return KDown ( GLFW_KEY_LEFT_SHIFT ) ;
case MINECRAFT_ACTION_CRAFTING : return KDown ( GLFW_KEY_F ) ;
case MINECRAFT_ACTION_RENDER_THIRD_PERSON : return KDown ( GLFW_KEY_F5 ) ;
case MINECRAFT_ACTION_GAME_INFO : return KDown ( GLFW_KEY_F3 ) ;
case MINECRAFT_ACTION_DPAD_LEFT : return KDown ( GLFW_KEY_LEFT ) ;
case MINECRAFT_ACTION_DPAD_RIGHT : return KDown ( GLFW_KEY_RIGHT ) ;
case MINECRAFT_ACTION_DPAD_UP : return KDown ( GLFW_KEY_UP ) ;
case MINECRAFT_ACTION_DPAD_DOWN : return KDown ( GLFW_KEY_DOWN ) ;
default : return false ;
}
}
// ---------------------------------------------------------------------------
// ButtonPressed – rising edge (press event this frame)
// ---------------------------------------------------------------------------
bool C_4JInput : : ButtonPressed ( int /*iPad*/ , unsigned char ucAction ) {
switch ( ucAction ) {
case ACTION_MENU_UP : return KPressed ( GLFW_KEY_UP ) | | KPressed ( GLFW_KEY_W ) ;
case ACTION_MENU_DOWN : return KPressed ( GLFW_KEY_DOWN ) | | KPressed ( GLFW_KEY_S ) ;
case ACTION_MENU_LEFT : return KPressed ( GLFW_KEY_LEFT ) | | KPressed ( GLFW_KEY_A ) ;
case ACTION_MENU_RIGHT : return KPressed ( GLFW_KEY_RIGHT ) | | KPressed ( GLFW_KEY_D ) ;
case ACTION_MENU_A :
case ACTION_MENU_OK :
return KPressed ( GLFW_KEY_ENTER ) | | KPressed ( GLFW_KEY_SPACE ) ;
case ACTION_MENU_B :
case ACTION_MENU_CANCEL :
return KPressed ( GLFW_KEY_ESCAPE ) ;
case ACTION_MENU_X : return KPressed ( GLFW_KEY_F ) ;
case ACTION_MENU_Y : return KPressed ( GLFW_KEY_E ) ;
case ACTION_MENU_PAGEUP : return KPressed ( GLFW_KEY_PAGE_UP ) | | KPressed ( GLFW_KEY_LEFT_SHIFT ) ;
case ACTION_MENU_PAGEDOWN : return KPressed ( GLFW_KEY_PAGE_DOWN ) | | KPressed ( GLFW_KEY_RIGHT_SHIFT ) ;
case ACTION_MENU_RIGHT_SCROLL : return KPressed ( GLFW_KEY_RIGHT_SHIFT ) | | WheelUpEdge ( ) ;
case ACTION_MENU_LEFT_SCROLL : return KPressed ( GLFW_KEY_LEFT_SHIFT ) | | WheelDownEdge ( ) ;
case ACTION_MENU_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_UP : return KPressed ( GLFW_KEY_UP ) ;
case ACTION_MENU_OTHER_STICK_DOWN : return KPressed ( GLFW_KEY_DOWN ) ;
case ACTION_MENU_OTHER_STICK_LEFT : return KPressed ( GLFW_KEY_LEFT ) ;
case ACTION_MENU_OTHER_STICK_RIGHT : return KPressed ( GLFW_KEY_RIGHT ) ;
case ACTION_MENU_PAUSEMENU : return KPressed ( GLFW_KEY_ESCAPE ) ;
case MINECRAFT_ACTION_JUMP : return KPressed ( GLFW_KEY_SPACE ) ;
case MINECRAFT_ACTION_FORWARD : return KPressed ( GLFW_KEY_W ) ;
case MINECRAFT_ACTION_BACKWARD : return KPressed ( GLFW_KEY_S ) ;
case MINECRAFT_ACTION_LEFT : return KPressed ( GLFW_KEY_A ) ;
case MINECRAFT_ACTION_RIGHT : return KPressed ( GLFW_KEY_D ) ;
case MINECRAFT_ACTION_LOOK_LEFT :
case MINECRAFT_ACTION_LOOK_RIGHT :
case MINECRAFT_ACTION_LOOK_UP :
case MINECRAFT_ACTION_LOOK_DOWN :
return false ;
case MINECRAFT_ACTION_USE : return MouseRPressed ( ) ;
case MINECRAFT_ACTION_ACTION : return MouseLPressed ( ) ;
case MINECRAFT_ACTION_LEFT_SCROLL : return WheelDownEdge ( ) ;
case MINECRAFT_ACTION_RIGHT_SCROLL : return WheelUpEdge ( ) ;
case MINECRAFT_ACTION_INVENTORY : return KPressed ( GLFW_KEY_E ) ;
case MINECRAFT_ACTION_PAUSEMENU : return KPressed ( GLFW_KEY_ESCAPE ) ;
case MINECRAFT_ACTION_DROP : return KPressed ( GLFW_KEY_Q ) ;
case MINECRAFT_ACTION_SNEAK_TOGGLE : return KPressed ( GLFW_KEY_LEFT_SHIFT ) ;
case MINECRAFT_ACTION_CRAFTING : return KPressed ( GLFW_KEY_F ) ;
case MINECRAFT_ACTION_RENDER_THIRD_PERSON : return KPressed ( GLFW_KEY_F5 ) ;
case MINECRAFT_ACTION_GAME_INFO : return KPressed ( GLFW_KEY_F3 ) ;
case MINECRAFT_ACTION_DPAD_LEFT : return KPressed ( GLFW_KEY_LEFT ) ;
case MINECRAFT_ACTION_DPAD_RIGHT : return KPressed ( GLFW_KEY_RIGHT ) ;
case MINECRAFT_ACTION_DPAD_UP : return KPressed ( GLFW_KEY_UP ) ;
case MINECRAFT_ACTION_DPAD_DOWN : return KPressed ( GLFW_KEY_DOWN ) ;
default : return false ;
}
}
// ---------------------------------------------------------------------------
// ButtonReleased – falling edge (released this frame)
// ---------------------------------------------------------------------------
bool C_4JInput : : ButtonReleased ( int /*iPad*/ , unsigned char ucAction ) {
switch ( ucAction ) {
case ACTION_MENU_UP : return KReleased ( GLFW_KEY_UP ) | | KReleased ( GLFW_KEY_W ) ;
case ACTION_MENU_DOWN : return KReleased ( GLFW_KEY_DOWN ) | | KReleased ( GLFW_KEY_S ) ;
case ACTION_MENU_LEFT : return KReleased ( GLFW_KEY_LEFT ) | | KReleased ( GLFW_KEY_A ) ;
case ACTION_MENU_RIGHT : return KReleased ( GLFW_KEY_RIGHT ) | | KReleased ( GLFW_KEY_D ) ;
case ACTION_MENU_A :
case ACTION_MENU_OK :
return KReleased ( GLFW_KEY_ENTER ) | | KReleased ( GLFW_KEY_SPACE ) ;
case ACTION_MENU_B :
case ACTION_MENU_CANCEL :
return KReleased ( GLFW_KEY_ESCAPE ) ;
case ACTION_MENU_X : return KReleased ( GLFW_KEY_F ) ;
case ACTION_MENU_Y : return KReleased ( GLFW_KEY_E ) ;
case ACTION_MENU_PAGEUP : return KReleased ( GLFW_KEY_PAGE_UP ) | | KReleased ( GLFW_KEY_LEFT_SHIFT ) ;
case ACTION_MENU_PAGEDOWN : return KReleased ( GLFW_KEY_PAGE_DOWN ) | | KReleased ( GLFW_KEY_RIGHT_SHIFT ) ;
case ACTION_MENU_RIGHT_SCROLL : return KReleased ( GLFW_KEY_RIGHT_SHIFT ) ;
case ACTION_MENU_LEFT_SCROLL : return KReleased ( GLFW_KEY_LEFT_SHIFT ) ;
case ACTION_MENU_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_PRESS : return false ;
case ACTION_MENU_OTHER_STICK_UP : return KReleased ( GLFW_KEY_UP ) ;
case ACTION_MENU_OTHER_STICK_DOWN : return KReleased ( GLFW_KEY_DOWN ) ;
case ACTION_MENU_OTHER_STICK_LEFT : return KReleased ( GLFW_KEY_LEFT ) ;
case ACTION_MENU_OTHER_STICK_RIGHT : return KReleased ( GLFW_KEY_RIGHT ) ;
case ACTION_MENU_PAUSEMENU : return KReleased ( GLFW_KEY_ESCAPE ) ;
case MINECRAFT_ACTION_JUMP : return KReleased ( GLFW_KEY_SPACE ) ;
case MINECRAFT_ACTION_FORWARD : return KReleased ( GLFW_KEY_W ) ;
case MINECRAFT_ACTION_BACKWARD : return KReleased ( GLFW_KEY_S ) ;
case MINECRAFT_ACTION_LEFT : return KReleased ( GLFW_KEY_A ) ;
case MINECRAFT_ACTION_RIGHT : return KReleased ( GLFW_KEY_D ) ;
case MINECRAFT_ACTION_LOOK_LEFT :
case MINECRAFT_ACTION_LOOK_RIGHT :
case MINECRAFT_ACTION_LOOK_UP :
case MINECRAFT_ACTION_LOOK_DOWN :
return false ;
case MINECRAFT_ACTION_USE : return MouseRReleased ( ) ;
case MINECRAFT_ACTION_ACTION : return MouseLReleased ( ) ;
case MINECRAFT_ACTION_LEFT_SCROLL : return false ; // scroll wheel has no "release"
case MINECRAFT_ACTION_RIGHT_SCROLL : return false ;
case MINECRAFT_ACTION_INVENTORY : return KReleased ( GLFW_KEY_E ) ;
case MINECRAFT_ACTION_PAUSEMENU : return KReleased ( GLFW_KEY_ESCAPE ) ;
case MINECRAFT_ACTION_DROP : return KReleased ( GLFW_KEY_Q ) ;
case MINECRAFT_ACTION_SNEAK_TOGGLE : return KReleased ( GLFW_KEY_LEFT_SHIFT ) ;
case MINECRAFT_ACTION_CRAFTING : return KReleased ( GLFW_KEY_F ) ;
case MINECRAFT_ACTION_RENDER_THIRD_PERSON : return KReleased ( GLFW_KEY_F5 ) ;
case MINECRAFT_ACTION_GAME_INFO : return KReleased ( GLFW_KEY_F3 ) ;
case MINECRAFT_ACTION_DPAD_LEFT : return KReleased ( GLFW_KEY_LEFT ) ;
case MINECRAFT_ACTION_DPAD_RIGHT : return KReleased ( GLFW_KEY_RIGHT ) ;
case MINECRAFT_ACTION_DPAD_UP : return KReleased ( GLFW_KEY_UP ) ;
case MINECRAFT_ACTION_DPAD_DOWN : return KReleased ( GLFW_KEY_DOWN ) ;
default : return false ;
}
}
// ---------------------------------------------------------------------------
// GetValue – returns 1 if action held, 0 otherwise
// ---------------------------------------------------------------------------
unsigned int C_4JInput : : GetValue ( int iPad , unsigned char ucAction , bool /*bRepeat*/ ) {
return ButtonDown ( iPad , ucAction ) ? 1u : 0u ;
}
// ---------------------------------------------------------------------------
// Analog sticks
//
// Left stick = WASD keyboard (±1.0)
// Right stick = mouse delta with sqrt-compression to linearise the quadratic
// look-speed formula used by the console game code:
// turnSpeed = rx * |rx| * 50 * sensitivity
// Passing sqrt(|raw|)*sign(raw) makes turn speed proportional
// to raw pixel delta, giving a natural mouse feel.
// ---------------------------------------------------------------------------
float C_4JInput : : GetJoypadStick_LX ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
// Return 0 while cursor is still in menu mode so Input::tick()'s
// lReset guard sees a zero-stick frame during the menu->game transition.
// Once s_mouseLocked becomes true (cursor captured for gameplay), return
// the real WASD values.
if ( ! s_mouseLocked ) return 0.0f ;
float v = 0.0f ;
if ( KDown ( GLFW_KEY_A ) ) v - = 1.0f ;
if ( KDown ( GLFW_KEY_D ) ) v + = 1.0f ;
return v ;
}
float C_4JInput : : GetJoypadStick_LY ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
if ( ! s_mouseLocked ) return 0.0f ;
float v = 0.0f ;
if ( KDown ( GLFW_KEY_W ) ) v - = 1.0f ; // W = forward = negative Y on consoles
if ( KDown ( GLFW_KEY_S ) ) v + = 1.0f ;
return v ;
}
float C_4JInput : : GetJoypadStick_RX ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
if ( ! s_mouseLocked ) return 0.0f ;
float raw = s_frameRelX * MOUSE_SCALE ;
float absRaw = fabsf ( raw ) ;
if ( absRaw > 1.0f ) absRaw = 1.0f ;
if ( absRaw < 0.0001f ) return 0.0f ;
return ( raw > = 0.0f ? 1.0f : - 1.0f ) * sqrtf ( absRaw ) ;
}
float C_4JInput : : GetJoypadStick_RY ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
if ( ! s_mouseLocked ) return 0.0f ;
float raw = s_frameRelY * MOUSE_SCALE ;
float absRaw = fabsf ( raw ) ;
if ( absRaw > 1.0f ) absRaw = 1.0f ;
if ( absRaw < 0.0001f ) return 0.0f ;
return ( raw > = 0.0f ? 1.0f : - 1.0f ) * sqrtf ( absRaw ) ;
}
// Left trigger = right mouse button (use/place)
// Right trigger = left mouse button (attack/destroy)
unsigned char C_4JInput : : GetJoypadLTrigger ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
return s_mouseRightCurrent ? 255 : 0 ;
}
unsigned char C_4JInput : : GetJoypadRTrigger ( int /*iPad*/ , bool /*bCheckMenuDisplay*/ ) {
return s_mouseLeftCurrent ? 255 : 0 ;
}
// ---------------------------------------------------------------------------
// Joypad map / sensitivity stubs (not meaningful for keyboard+mouse)
// ---------------------------------------------------------------------------
void C_4JInput : : SetDeadzoneAndMovementRange ( unsigned int /*uiDeadzone*/ , unsigned int /*uiMovementRangeMax*/ ) { }
void C_4JInput : : SetGameJoypadMaps ( unsigned char /*ucMap*/ , unsigned char /*ucAction*/ , unsigned int /*uiActionVal*/ ) { }
unsigned int C_4JInput : : GetGameJoypadMaps ( unsigned char /*ucMap*/ , unsigned char /*ucAction*/ ) { return 0 ; }
void C_4JInput : : SetJoypadMapVal ( int /*iPad*/ , unsigned char /*ucMap*/ ) { }
unsigned char C_4JInput : : GetJoypadMapVal ( int /*iPad*/ ) { return 0 ; }
void C_4JInput : : SetJoypadSensitivity ( int /*iPad*/ , float /*fSensitivity*/ ) { }
void C_4JInput : : SetJoypadStickAxisMap ( int /*iPad*/ , unsigned int /*uiFrom*/ , unsigned int /*uiTo*/ ) { }
void C_4JInput : : SetJoypadStickTriggerMap ( int /*iPad*/ , unsigned int /*uiFrom*/ , unsigned int /*uiTo*/ ) { }
void C_4JInput : : SetKeyRepeatRate ( float /*fRepeatDelaySecs*/ , float /*fRepeatRateSecs*/ ) { }
void C_4JInput : : SetDebugSequence ( const char * /*chSequenceA*/ , int ( */ * Func */ ) ( LPVOID ) , LPVOID /*lpParam*/ ) { }
FLOAT C_4JInput : : GetIdleSeconds ( int /*iPad*/ ) { return 0.0f ; }
bool C_4JInput : : IsPadConnected ( int iPad ) { return iPad = = 0 ; } // slot 0 = keyboard+mouse
void C_4JInput : : SetMenuDisplayed ( int iPad , bool bVal ) {
if ( iPad > = 0 & & iPad < 4 ) s_menuDisplayed [ iPad ] = bVal ;
}
// ---------------------------------------------------------------------------
// Keyboard (text entry) / string verification stubs
// ---------------------------------------------------------------------------
EKeyboardResult C_4JInput : : RequestKeyboard ( LPCWSTR /*Title*/ , LPCWSTR /*Text*/ , DWORD /*dwPad*/ ,
UINT /*uiMaxChars*/ ,
int ( */ * Func */ ) ( LPVOID , const bool ) , LPVOID /*lpParam*/ ,
C_4JInput : : EKeyboardMode /*eMode*/ ) {
return EKeyboard_Cancelled ;
}
void C_4JInput : : GetText ( uint16_t * UTF16String ) { if ( UTF16String ) UTF16String [ 0 ] = 0 ; }
bool C_4JInput : : VerifyStrings ( WCHAR * * pwStringA , int iStringC , int ( * Func ) ( LPVOID , STRING_VERIFY_RESPONSE * ) , LPVOID lpParam ) { return true ; }
void C_4JInput : : CancelQueuedVerifyStrings ( int ( * Func ) ( LPVOID , STRING_VERIFY_RESPONSE * ) , LPVOID lpParam ) { }
bool C_4JInput : : VerifyStrings ( WCHAR * * /*pwStringA*/ , int /*iStringC*/ ,
int ( */ * Func */ ) ( LPVOID , STRING_VERIFY_RESPONSE * ) , LPVOID /*lpParam*/ ) { return true ; }
void C_4JInput : : CancelQueuedVerifyStrings ( int ( */ * Func */ ) ( LPVOID , STRING_VERIFY_RESPONSE * ) , LPVOID /*lpParam*/ ) { }
void C_4JInput : : CancelAllVerifyInProgress ( void ) { }