Joystick smooth movement + joystick rework

This commit is contained in:
Romain Graillot 2019-04-27 13:26:28 +02:00
parent 194864cac4
commit 5d9aa6f969

View File

@ -89,33 +89,41 @@ unsigned long X11_clipboard_size = 0;
// -- // --
// Digital joystick state // Digital joystick state
byte Directional_up; #define PAD_MAX_SPEED 3 /// Max speed per pixel when using the gamepad or keyboard directional keys
byte Directional_up_right; static byte Directional_click = 0;
byte Directional_right; static byte Digital_joystick_state = 0;
byte Directional_down_right; #define D_JOYSTICK_UP (1 << 0)
byte Directional_down; #define D_JOYSTICK_UP_RIGHT (1 << 1)
byte Directional_down_left; #define D_JOYSTICK_RIGHT (1 << 2)
byte Directional_left; #define D_JOYSTICK_DOWN_RIGHT (1 << 3)
byte Directional_up_left; #define D_JOYSTICK_DOWN (1 << 4)
byte Directional_click; #define D_JOYSTICK_DOWN_LEFT (1 << 5)
#define D_JOYSTICK_LEFT (1 << 6)
#define D_JOYSTICK_UP_LEFT (1 << 7)
// Emulated directional controller. // Emulated directional controller.
// This has a distinct state from Directional_, because some joysticks send // This has a distinct state from Directional_, because some joysticks send
// "I'm not moving" SDL events when idle, thus stopping the emulated one. // "I'm not moving" SDL events when idle, thus stopping the emulated one.
byte Directional_emulated_up; static byte Directional_emulated;
byte Directional_emulated_right;
byte Directional_emulated_down; // Analog joystick state (mouse emulation)
byte Directional_emulated_left; #if defined(USE_JOYSTICK)
#define STICK_MAX_SPEED 3 // Max speed per pixel using the analog stick
long Joystick_vertical = 0; // 16.16 fixed point value
long Joystick_horizontal = 0; // 16.16 fixed point value
#endif
word Input_new_mouse_X;
word Input_new_mouse_Y;
word Input_new_mouse_X_frac; // fractional part of Input_new_mouse_X
word Input_new_mouse_Y_frac; // fractional part of Input_new_mouse_Y
byte Input_new_mouse_K;
byte Button_inverter=0; // State of the key that swaps mouse buttons.
long Directional_first_move; long Directional_first_move;
long Directional_last_move; long Directional_last_move;
int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs. int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs.
word Input_new_mouse_X;
word Input_new_mouse_Y;
byte Input_new_mouse_K;
byte Button_inverter=0; // State of the key that swaps mouse buttons.
byte Pan_shortcut_pressed; byte Pan_shortcut_pressed;
// Joystick/pad configurations for the various console ports. // Joystick/pad configurations for the various console ports.
@ -727,22 +735,22 @@ int Handle_special_key_press(void)
{ {
if(Is_shortcut(Key,SPECIAL_MOUSE_UP)) if(Is_shortcut(Key,SPECIAL_MOUSE_UP))
{ {
Directional_emulated_up=1; Directional_emulated |= D_JOYSTICK_UP;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN)) else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN))
{ {
Directional_emulated_down=1; Directional_emulated |= D_JOYSTICK_DOWN;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT)) else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT))
{ {
Directional_emulated_left=1; Directional_emulated |= D_JOYSTICK_LEFT;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT)) else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT))
{ {
Directional_emulated_right=1; Directional_emulated |= D_JOYSTICK_RIGHT;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0) else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0)
@ -853,22 +861,22 @@ int Release_control(int key_code, int modifier)
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier))
{ {
Directional_emulated_up=0; Directional_emulated &= ~D_JOYSTICK_UP;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier))
{ {
Directional_emulated_down=0; Directional_emulated &= ~D_JOYSTICK_DOWN;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier))
{ {
Directional_emulated_left=0; Directional_emulated &= ~D_JOYSTICK_LEFT;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier))
{ {
Directional_emulated_right=0; Directional_emulated &= ~D_JOYSTICK_RIGHT;
} }
if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier))
@ -1009,42 +1017,42 @@ static int Handle_joystick_press(SDL_JoyButtonEvent * event)
{ {
#ifdef JOY_BUTTON_UP #ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP: case JOY_BUTTON_UP:
Directional_up=1; Digital_joystick_state |= D_JOYSTICK_UP;
break; break;
#endif #endif
#ifdef JOY_BUTTON_UPRIGHT #ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT: case JOY_BUTTON_UPRIGHT:
Directional_up_right=1; Digital_joystick_state |= D_JOYSTICK_UP_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_RIGHT #ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT: case JOY_BUTTON_RIGHT:
Directional_right=1; Digital_joystick_state |= D_JOYSTICK_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWNRIGHT #ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT: case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1; Digital_joystick_state |= D_JOYSTICK_DOWN_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWN #ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN: case JOY_BUTTON_DOWN:
Directional_down=1; Digital_joystick_state |= D_JOYSTICK_DOWN;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWNLEFT #ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT: case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1; Digital_joystick_state |= D_JOYSTICK_DOWN_LEFT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_LEFT #ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT: case JOY_BUTTON_LEFT:
Directional_left=1; Digital_joystick_state |= D_JOYSTICK_LEFT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_UPLEFT #ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT: case JOY_BUTTON_UPLEFT:
Directional_up_left=1; Digital_joystick_state |= D_JOYSTICK_UP_LEFT;
break; break;
#endif #endif
@ -1094,42 +1102,42 @@ static int Handle_joystick_release(SDL_JoyButtonEvent * event)
{ {
#ifdef JOY_BUTTON_UP #ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP: case JOY_BUTTON_UP:
Directional_up=0; Digital_joystick_state &= ~D_JOYSTICK_UP;
break; break;
#endif #endif
#ifdef JOY_BUTTON_UPRIGHT #ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT: case JOY_BUTTON_UPRIGHT:
Directional_up_right=0; Digital_joystick_state &= ~D_JOYSTICK_UP_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_RIGHT #ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT: case JOY_BUTTON_RIGHT:
Directional_right=0; Digital_joystick_state &= ~D_JOYSTICK_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWNRIGHT #ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT: case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=0; Digital_joystick_state &= ~D_JOYSTICK_DOWN_RIGHT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWN #ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN: case JOY_BUTTON_DOWN:
Directional_down=0; Digital_joystick_state &= ~D_JOYSTICK_DOWN;
break; break;
#endif #endif
#ifdef JOY_BUTTON_DOWNLEFT #ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT: case JOY_BUTTON_DOWNLEFT:
Directional_down_left=0; Digital_joystick_state &= ~D_JOYSTICK_DOWN_LEFT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_LEFT #ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT: case JOY_BUTTON_LEFT:
Directional_left=0; Digital_joystick_state &= ~D_JOYSTICK_LEFT;
break; break;
#endif #endif
#ifdef JOY_BUTTON_UPLEFT #ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT: case JOY_BUTTON_UPLEFT:
Directional_up_left=0; Digital_joystick_state &= ~D_JOYSTICK_UP_LEFT;
break; break;
#endif #endif
@ -1143,54 +1151,62 @@ static void Handle_joystick_movement(SDL_JoyAxisEvent * event)
{ {
if (event->axis == JOYSTICK_AXIS_X) if (event->axis == JOYSTICK_AXIS_X)
{ {
Directional_right = Directional_left = 0; if (event->value < -JOYSTICK_THRESHOLD || event->value > JOYSTICK_THRESHOLD)
if (event->value < -JOYSTICK_THRESHOLD) Joystick_horizontal = event->value << 1;
Directional_left=1; else
else if (event->value > JOYSTICK_THRESHOLD) Joystick_horizontal = 0;
Directional_right=1;
} }
else if (event->axis == JOYSTICK_AXIS_Y) else if (event->axis == JOYSTICK_AXIS_Y)
{ {
Directional_up = Directional_down = 0; if (event->value < -JOYSTICK_THRESHOLD || event->value > JOYSTICK_THRESHOLD)
if (event->value < -JOYSTICK_THRESHOLD) Joystick_vertical = event->value << 1;
Directional_up = 1; else
else if (event->value > JOYSTICK_THRESHOLD) Joystick_vertical = 0;
Directional_down=1;
} }
} }
#endif #endif
// Attempts to move the mouse cursor by the given deltas (may be more than 1 pixel at a time) /** Attempts to move the mouse cursor by the given deltas
int Cursor_displace(short delta_x, short delta_y) * @param step move multiply factor
* @param delta_x 16.16 fixed point value
* @param delta_y 16.16 fixed point value
* @return feedback
*/
static int Cursor_displace(int step, long delta_x, long delta_y)
{ {
int x = Input_new_mouse_X; long x, y;
int y = Input_new_mouse_Y;
x = ((long)Input_new_mouse_X << 16) + Input_new_mouse_X_frac;
y = ((long)Input_new_mouse_Y << 16) + Input_new_mouse_Y_frac;
if(Main.magnifier_mode && Input_new_mouse_Y < Menu_Y && Input_new_mouse_X > Main.separator_position) if(Main.magnifier_mode && Input_new_mouse_Y < Menu_Y && Input_new_mouse_X > Main.separator_position)
{ {
// Cursor in zoomed area // Cursor in zoomed area
x += Main.magnifier_factor * delta_x;
if (delta_x<0) if (x < (Main.separator_position << 16))
x = Max(Main.separator_position, x-Main.magnifier_factor); x = Main.separator_position << 16;
else if (delta_x>0) else if (x > ((Screen_width-1) << 16))
x = Min(Screen_width-1, x+Main.magnifier_factor); x = (Screen_width-1) << 16;
if (delta_y<0) y += Main.magnifier_factor * delta_y;
y = Max(0, y-Main.magnifier_factor);
else if (delta_y>0)
y = Min(Screen_height-1, y+Main.magnifier_factor);
} }
else else
{ {
if (delta_x<0) x += delta_x * step;
x = Max(0, x+delta_x); if (x < 0)
else if (delta_x>0) x = 0;
x = Min(Screen_width-1, x+delta_x); else if (x > ((Screen_width-1) << 16))
if (delta_y<0) x = (Screen_width-1) << 16;
y = Max(0, y+delta_y); y += delta_y * step;
else if (delta_y>0)
y = Min(Screen_height-1, y+delta_y);
} }
return Move_cursor_with_constraints(x, y); if (y < 0)
y = 0;
else if (y > ((Screen_height-1) << 16))
y = (Screen_height-1) << 16;
Input_new_mouse_X_frac = x & 0xffff;
Input_new_mouse_Y_frac = y & 0xffff;
return Move_cursor_with_constraints(x >> 16, y >> 16);
} }
// This function is the acceleration profile for directional (digital) cursor // This function is the acceleration profile for directional (digital) cursor
@ -1525,12 +1541,12 @@ int Get_input(int sleep_time)
break; break;
} }
} }
// Directional controller // Directional and analog controller
if (!(Directional_up||Directional_up_right||Directional_right|| if (!(Digital_joystick_state||Directional_emulated)
Directional_down_right||Directional_down||Directional_down_left|| #if defined(USE_JOYSTICK)
Directional_left||Directional_up_left||Directional_emulated_up|| && !(Joystick_vertical != 0 || Joystick_horizontal != 0)
Directional_emulated_right||Directional_emulated_down|| #endif
Directional_emulated_left)) )
{ {
Directional_first_move=0; Directional_first_move=0;
} }
@ -1538,7 +1554,9 @@ int Get_input(int sleep_time)
{ {
long time_now; long time_now;
int step=0; int step=0;
#if defined(USE_JOYSTICK)
int joy_step = 0;
#endif
time_now=GFX2_GetTicks(); time_now=GFX2_GetTicks();
if (Directional_first_move==0) if (Directional_first_move==0)
@ -1556,36 +1574,52 @@ int Get_input(int sleep_time)
Directional_acceleration(Directional_last_move - Directional_first_move); Directional_acceleration(Directional_last_move - Directional_first_move);
// Clip speed at 3 pixel per visible frame. // Clip speed at 3 pixel per visible frame.
if (step > 3) if (step > PAD_MAX_SPEED)
step=3; step = PAD_MAX_SPEED;
#if defined(USE_JOYSTICK)
joy_step =
Directional_acceleration(time_now) -
Directional_acceleration(Directional_last_move);
if (joy_step > STICK_MAX_SPEED)
joy_step = STICK_MAX_SPEED;
#endif
} }
Directional_last_move = time_now; Directional_last_move = time_now;
#if defined(USE_JOYSTICK)
// Analog joystick
if (Joystick_vertical != 0 || Joystick_horizontal != 0)
{
Cursor_displace(joy_step, Joystick_horizontal, Joystick_vertical);
}
#endif
if (step) if (step)
{ {
long delta_x = 0;
long delta_y = 0;
// Directional controller UP // Directional controller UP
if ((Directional_up||Directional_emulated_up||Directional_up_left||Directional_up_right) && if ((Digital_joystick_state & (D_JOYSTICK_UP | D_JOYSTICK_UP_RIGHT | D_JOYSTICK_UP_LEFT))
!(Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left)) || (Directional_emulated & D_JOYSTICK_UP))
{ delta_y -= 1 << 16;
Cursor_displace(0, -step);
}
// Directional controller RIGHT
if ((Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right) &&
!(Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left))
{
Cursor_displace(step,0);
}
// Directional controller DOWN // Directional controller DOWN
if ((Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left) && if ((Digital_joystick_state & (D_JOYSTICK_DOWN | D_JOYSTICK_DOWN_RIGHT | D_JOYSTICK_DOWN_LEFT))
!(Directional_up_left||Directional_up||Directional_emulated_up||Directional_up_right)) || (Directional_emulated & D_JOYSTICK_DOWN))
{ delta_y += 1 << 16;
Cursor_displace(0, step);
} // Directional controller RIGHT
if ((Digital_joystick_state & (D_JOYSTICK_RIGHT | D_JOYSTICK_UP_RIGHT | D_JOYSTICK_DOWN_RIGHT))
|| (Directional_emulated & D_JOYSTICK_RIGHT))
delta_x += 1 << 16;
// Directional controller LEFT // Directional controller LEFT
if ((Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left) && if ((Digital_joystick_state & (D_JOYSTICK_LEFT | D_JOYSTICK_UP_LEFT | D_JOYSTICK_DOWN_LEFT))
!(Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right)) || (Directional_emulated & D_JOYSTICK_LEFT))
delta_x -= 1 << 16;
if (delta_x != 0 || delta_y != 0)
{ {
Cursor_displace(-step,0); Cursor_displace(step, delta_x, delta_y);
} }
} }
} }
@ -1595,8 +1629,11 @@ int Get_input(int sleep_time)
{ {
Compute_paintbrush_coordinates(); Compute_paintbrush_coordinates();
Display_cursor(); Display_cursor();
#if defined(USE_SDL2) #if defined(USE_SDL2) && defined(USE_JOYSTICK)
//GFX2_UpdateScreen(); // To achieve mouse smooth movement using a joystick, we update the screen now and return
// this is because for mouse coordinate the joystick use floats internally and Mouse_moved become always
// true and stop updating the screen until the axis are released.
GFX2_UpdateScreen();
#endif #endif
return 1; return 1;
} }