mirror of
https://github.com/AloUltraExt/sm64ex-alo.git
synced 2025-01-22 07:32:15 -05:00
Better mouse handling plus DXGI support (from sm64coopdx)
Set DXGI mouse visibility (from HM64) Proper mouse relative mode and buttons in DXGI (from sm64coopdx) Ensure mouse doesn't escape window and simplify visible state
This commit is contained in:
parent
a3ff29bbe2
commit
5717a8c092
12 changed files with 347 additions and 148 deletions
|
@ -6,7 +6,7 @@ Fork of [sm64pc/sm64ex](https://github.com/sm64pc/sm64ex) with additional featur
|
|||
* Based of the latest refresh (since sm64ex is stuck on 12)
|
||||
* Puppycam 2 (sm64ex still has Puppycam 1)
|
||||
* Quality of life fixes and features (QOL_FIXES=1 and QOL_FEATURES=1 respectively)
|
||||
* Mouse support for desktop targets (MOUSE_ACTIONS=1) (SDL1/SDL2 only, DirectX Mouse not implemented yet)
|
||||
* Mouse support for desktop targets (MOUSE_ACTIONS=1)
|
||||
* Simple debug options menu (EXT_DEBUG_MENU=1)
|
||||
* Kaze's more objects patch (PORT_MOP_OBJS=1)
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ PORT_MOP_OBJS ?= 0
|
|||
VANILLA_CHECKS ?= 1
|
||||
# Enable extended bounds
|
||||
EXTENDED_BOUNDS ?= 0
|
||||
# Enable Mouse support
|
||||
MOUSE_ACTIONS ?= 1
|
||||
# Accept RM2C level folder output
|
||||
RM2C ?= 0
|
||||
|
||||
|
@ -99,8 +101,8 @@ endif
|
|||
# Use PC-only exclusive defines
|
||||
ifeq ($(TARGET_PORT_CONSOLE),0)
|
||||
|
||||
# Check for Mouse Option (no DirectX yet)
|
||||
ifneq ($(WINDOW_API),DXGI)
|
||||
# Check for Mouse Option
|
||||
ifeq ($(MOUSE_ACTIONS),1)
|
||||
CUSTOM_C_DEFINES += -DMOUSE_ACTIONS
|
||||
endif
|
||||
|
||||
|
@ -108,7 +110,7 @@ ifeq ($(TARGET_PORT_CONSOLE),0)
|
|||
ifeq ($(DISCORDRPC),1)
|
||||
CUSTOM_C_DEFINES += -DDISCORDRPC
|
||||
endif
|
||||
|
||||
|
||||
# Check for Command Line Options
|
||||
ifeq ($(COMMAND_LINE_OPTIONS),1)
|
||||
CUSTOM_C_DEFINES += -DCOMMAND_LINE_OPTIONS
|
||||
|
|
|
@ -762,16 +762,16 @@ static void puppycam_input_mouse(void) {
|
|||
f32 ivY = ((gPuppyCam.options.invertY * 2) - 1) * (gPuppyCam.options.sensitivityY / PUPPYCAM_SENSITIVITY);
|
||||
|
||||
if (configMouse && gPuppyCam.options.mouse) {
|
||||
gMouseHasCenterControl = TRUE;
|
||||
mouse_has_center_control = TRUE;
|
||||
|
||||
if (gPuppyCam.flags & PUPPYCAM_BEHAVIOUR_FREE) {
|
||||
if (gPlayer1Controller->buttonDown & A_BUTTON) {
|
||||
gPuppyCam.yawTarget -= ivX * gMouseXPos * (gPuppyCam.options.mouseSpeed * 1.5);
|
||||
gPuppyCam.pitchTarget += ivY * gMouseYPos * (gPuppyCam.options.mouseSpeed * 1.5);
|
||||
gPuppyCam.yawTarget -= ivX * mouse_x * (gPuppyCam.options.mouseSpeed * 1.5);
|
||||
gPuppyCam.pitchTarget += ivY * mouse_y * (gPuppyCam.options.mouseSpeed * 1.5);
|
||||
}
|
||||
} else {
|
||||
gPuppyCam.yawTarget -= ivX * gMouseXPos * gPuppyCam.options.mouseSpeed;
|
||||
gPuppyCam.pitchTarget += ivY * gMouseYPos * gPuppyCam.options.mouseSpeed;
|
||||
gPuppyCam.yawTarget -= ivX * mouse_x * gPuppyCam.options.mouseSpeed;
|
||||
gPuppyCam.pitchTarget += ivY * mouse_y * gPuppyCam.options.mouseSpeed;
|
||||
// We allow free movement even on classic but after 15 frames of no mouse movement camera gets snapped.
|
||||
if (gPuppyCam.options.inputType == PUPPYCAM_INPUT_CLASSIC_STYLE && gPuppyCam.framesSinceMouse == 15) {
|
||||
if (!(gPuppyCam.mode3Flags & PUPPYCAM_MODE3_ZOOMED_IN)) {
|
||||
|
@ -784,7 +784,7 @@ static void puppycam_input_mouse(void) {
|
|||
}
|
||||
|
||||
// Increase timer when mouse is on idle, resets when mouse gets moved on any direction.
|
||||
if (gMouseXPos + gMouseYPos != 0) {
|
||||
if (mouse_x + mouse_y != 0) {
|
||||
gPuppyCam.framesSinceMouse = 0;
|
||||
} else {
|
||||
if (gPuppyCam.framesSinceMouse <= 20) {
|
||||
|
@ -792,7 +792,7 @@ static void puppycam_input_mouse(void) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
gMouseHasCenterControl = FALSE;
|
||||
mouse_has_center_control = FALSE;
|
||||
gPuppyCam.framesSinceMouse = 20;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -819,10 +819,10 @@ s32 act_in_cannon(struct MarioState *m) {
|
|||
marioObj->oMarioCannonInputYaw -= (s16)(m->controller->stickX * 10.0f);
|
||||
#ifdef MOUSE_ACTIONS
|
||||
if (configMouse) {
|
||||
gMouseHasCenterControl = TRUE;
|
||||
mouse_has_center_control = TRUE;
|
||||
|
||||
m->faceAngle[0] -= (s16)(gMouseYPos * 10.0f);
|
||||
marioObj->oMarioCannonInputYaw -= (s16)(gMouseXPos * 10.0f);
|
||||
m->faceAngle[0] -= (s16)(mouse_y * 10.0f);
|
||||
marioObj->oMarioCannonInputYaw -= (s16)(mouse_x * 10.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -856,7 +856,7 @@ s32 act_in_cannon(struct MarioState *m) {
|
|||
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
gMouseHasCenterControl = FALSE;
|
||||
mouse_has_center_control = FALSE;
|
||||
#endif
|
||||
|
||||
set_mario_action(m, ACT_SHOT_FROM_CANNON, 0);
|
||||
|
|
|
@ -2532,40 +2532,32 @@ void parse_p1_controller(void) {
|
|||
sDebugViews[sCurrDebugViewIndex - 1]->flags |= VIEW_UPDATE;
|
||||
}
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
controller_mouse_read_window();
|
||||
#endif
|
||||
|
||||
// deadzone checks
|
||||
if (ABS(gdctrl->stickX) >= 6) {
|
||||
gdctrl->csrX += gdctrl->stickX * 0.1;
|
||||
#ifdef MOUSE_ACTIONS
|
||||
gMouseHasFreeControl = FALSE;
|
||||
mouse_has_current_control = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ABS(gdctrl->stickY) >= 6) {
|
||||
gdctrl->csrY -= gdctrl->stickY * 0.1;
|
||||
#ifdef MOUSE_ACTIONS
|
||||
gMouseHasFreeControl = FALSE;
|
||||
mouse_has_current_control = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
if (!(sHandView->flags & VIEW_UPDATE))
|
||||
gMouseHasFreeControl = FALSE;
|
||||
|
||||
if ((gMouseXPos - gOldMouseXPos != 0 || gMouseYPos - gOldMouseYPos != 0) && (sHandView->flags & VIEW_UPDATE)) {
|
||||
gMouseHasFreeControl = TRUE;
|
||||
}
|
||||
|
||||
float screenScale = (float) gfx_current_dimensions.height / (float)SCREEN_HEIGHT;
|
||||
if (configMouse && gMouseHasFreeControl) {
|
||||
gdctrl->csrX = (gMouseXPos - (gfx_current_dimensions.width - (screenScale * (float)SCREEN_WIDTH))/ 2)/ screenScale;
|
||||
gdctrl->csrY = gMouseYPos / screenScale;
|
||||
}
|
||||
|
||||
gOldMouseXPos = gMouseXPos;
|
||||
gOldMouseYPos = gMouseYPos;
|
||||
|
||||
if (!gMouseHasFreeControl) {
|
||||
float screenScale = (float) gfx_current_dimensions.height / SCREEN_HEIGHT;
|
||||
f32 mousePosX = (f32) ((mouse_window_x - (gfx_current_dimensions.width - (screenScale * (float)SCREEN_WIDTH))/ 2)/ screenScale);
|
||||
f32 mousePosY = (f32) (mouse_window_y / screenScale);
|
||||
if (!controller_mouse_set_position(&gdctrl->csrX, &gdctrl->csrY, mousePosX, mousePosY, (sHandView->flags & VIEW_UPDATE), TRUE))
|
||||
#endif
|
||||
{
|
||||
// clamp cursor position within screen view bounds
|
||||
if (gdctrl->csrX < sScreenView->parent->upperLeft.x + GFX_DIMENSIONS_FROM_LEFT_EDGE(16.0f)) {
|
||||
gdctrl->csrX = sScreenView->parent->upperLeft.x + GFX_DIMENSIONS_FROM_LEFT_EDGE(16.0f);
|
||||
|
@ -2586,10 +2578,7 @@ if (!gMouseHasFreeControl) {
|
|||
for (i = 0; i < sizeof(OSContPad); i++) {
|
||||
((u8 *) prevInputs)[i] = ((u8 *) currInputs)[i];
|
||||
}
|
||||
#ifdef MOUSE_ACTIONS
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void stub_renderer_4(f32 arg0) {
|
||||
|
|
|
@ -1709,23 +1709,25 @@ void handle_controller_cursor_input(void) {
|
|||
s16 rawStickX = gPlayer1Controller->rawStickX;
|
||||
s16 rawStickY = gPlayer1Controller->rawStickY;
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
controller_mouse_read_window();
|
||||
#endif
|
||||
|
||||
// Handle deadzone
|
||||
if (rawStickY > -2 && rawStickY < 2) {
|
||||
rawStickY = 0;
|
||||
}
|
||||
#ifdef MOUSE_ACTIONS
|
||||
else
|
||||
{
|
||||
gMouseHasFreeControl = FALSE;
|
||||
else {
|
||||
mouse_has_current_control = FALSE;
|
||||
}
|
||||
#endif
|
||||
if (rawStickX > -2 && rawStickX < 2) {
|
||||
rawStickX = 0;
|
||||
}
|
||||
#ifdef MOUSE_ACTIONS
|
||||
else
|
||||
{
|
||||
gMouseHasFreeControl = FALSE;
|
||||
else {
|
||||
mouse_has_current_control = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1734,26 +1736,12 @@ void handle_controller_cursor_input(void) {
|
|||
sCursorPos[1] += rawStickY / 8;
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
if (sSelectedFileNum != 0)
|
||||
gMouseHasFreeControl = FALSE;
|
||||
|
||||
if ((gMouseXPos - gOldMouseXPos != 0 || gMouseYPos - gOldMouseYPos != 0) && sSelectedFileNum == 0) {
|
||||
gMouseHasFreeControl = TRUE;
|
||||
}
|
||||
|
||||
static float screenScale;
|
||||
screenScale = (float) gfx_current_dimensions.height / SCREEN_HEIGHT;
|
||||
if (gMouseHasFreeControl && configMouse) {
|
||||
sCursorPos[0] = ((gMouseXPos - (gfx_current_dimensions.width - (screenScale * 320)) / 2) / screenScale) - 160.0f;
|
||||
sCursorPos[1] = (gMouseYPos / screenScale - 120.0f) * -1;
|
||||
}
|
||||
|
||||
gOldMouseXPos = gMouseXPos;
|
||||
gOldMouseYPos = gMouseYPos;
|
||||
|
||||
if (!gMouseHasFreeControl) {
|
||||
float screenScale = (float) gfx_current_dimensions.height / SCREEN_HEIGHT;
|
||||
f32 mousePosX = (((mouse_window_x - (gfx_current_dimensions.width - (screenScale * 320)) / 2) / screenScale) - 160.0f);
|
||||
f32 mousePosY = ((mouse_window_y / screenScale - 120.0f) * -1);
|
||||
if (!controller_mouse_set_position(&sCursorPos[0], &sCursorPos[1], mousePosX, mousePosY, sSelectedFileNum == 0, FALSE))
|
||||
#endif
|
||||
|
||||
{
|
||||
// Stop cursor from going offscreen
|
||||
if (sCursorPos[0] > GFX_DIMENSIONS_FROM_RIGHT_EDGE(188.0f)) {
|
||||
sCursorPos[0] = GFX_DIMENSIONS_FROM_RIGHT_EDGE(188.0f);
|
||||
|
@ -1768,9 +1756,7 @@ if (!gMouseHasFreeControl) {
|
|||
if (sCursorPos[1] < -90.0f) {
|
||||
sCursorPos[1] = -90.0f;
|
||||
}
|
||||
#ifdef MOUSE_ACTIONS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sCursorClickingTimer == 0) {
|
||||
handle_cursor_button_input();
|
||||
|
|
200
src/pc/controller/controller_mouse.c
Normal file
200
src/pc/controller/controller_mouse.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
#include "controller_mouse.h"
|
||||
#include "../configfile.h"
|
||||
|
||||
#ifdef WAPI_DXGI
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
extern HWND gfx_dxgi_get_h_wnd(void);
|
||||
extern void gfx_dxgi_set_cursor_visibility(bool visible);
|
||||
#elif defined(CAPI_SDL1)
|
||||
#include <SDL/SDL.h>
|
||||
#elif defined(CAPI_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
|
||||
int mouse_prev_window_x;
|
||||
int mouse_prev_window_y;
|
||||
|
||||
int mouse_has_center_control;
|
||||
int mouse_has_current_control;
|
||||
|
||||
bool mouse_init_ok;
|
||||
|
||||
u32 mouse_buttons;
|
||||
s32 mouse_x;
|
||||
s32 mouse_y;
|
||||
|
||||
u32 mouse_window_buttons;
|
||||
s32 mouse_window_x;
|
||||
s32 mouse_window_y;
|
||||
|
||||
bool mouse_relative_enabled;
|
||||
|
||||
#ifdef WAPI_DXGI
|
||||
u32 mouse_relative_buttons_held_on_focus;
|
||||
u32 mouse_window_buttons_held_on_focus;
|
||||
bool mouse_dxgi_prev_focus;
|
||||
|
||||
static u32 controller_mouse_dxgi_button_state(u32* mouse_held, bool has_focus) {
|
||||
u32 mouse =
|
||||
((GetKeyState(VK_LBUTTON) < 0) ? (1 << 0) : 0) |
|
||||
((GetKeyState(VK_MBUTTON) < 0) ? (1 << 1) : 0) |
|
||||
((GetKeyState(VK_RBUTTON) < 0) ? (1 << 2) : 0);
|
||||
|
||||
bool prev_focus = mouse_dxgi_prev_focus;
|
||||
mouse_dxgi_prev_focus = has_focus;
|
||||
|
||||
// Ignore mouse clicks when game window doesn't have focus.
|
||||
if (!has_focus) { return 0; }
|
||||
if (mouse_held == NULL) { return mouse; }
|
||||
|
||||
// Window just received input focus, ignore any held down mouse buttons.
|
||||
if (!prev_focus && has_focus) {
|
||||
*mouse_held = mouse;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait for a mouse button held down (e.g. while clicking on the window)
|
||||
// to be released and pressed again.
|
||||
*mouse_held = (*mouse_held) & mouse;
|
||||
return ~(*mouse_held) & mouse;
|
||||
}
|
||||
#endif // WAPI_DXGI
|
||||
|
||||
static void controller_mouse_is_visible(int visible) {
|
||||
#if defined(WAPI_DXGI)
|
||||
gfx_dxgi_set_cursor_visibility(visible);
|
||||
#elif defined(CAPI_SDL1) || defined(CAPI_SDL2)
|
||||
SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void controller_mouse_set_visible(void) {
|
||||
if (configWindow.fullscreen) {
|
||||
controller_mouse_is_visible(false);
|
||||
} else {
|
||||
controller_mouse_is_visible(!mouse_has_current_control);
|
||||
}
|
||||
}
|
||||
|
||||
int controller_mouse_set_position(void *cursorX, void *cursorY, f32 mPosX, f32 mPosY, int hasControlCondition, int isInteger) {
|
||||
// Disable control is mouse config is off
|
||||
if (!configMouse) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Disable mouse control if condition isn't met
|
||||
if (!hasControlCondition) {
|
||||
mouse_has_current_control = FALSE;
|
||||
}
|
||||
|
||||
// Check if the mouse moved and update control status if condition is met
|
||||
if ((mouse_window_x - mouse_prev_window_x != 0 || mouse_window_y - mouse_prev_window_y != 0) && hasControlCondition) {
|
||||
mouse_has_current_control = TRUE;
|
||||
}
|
||||
|
||||
// Scale calculations and cursor position update if the mouse has control
|
||||
if (configMouse && mouse_has_current_control) {
|
||||
float posX = mPosX;
|
||||
float posY = mPosY;
|
||||
|
||||
// Update position based on type
|
||||
if (isInteger) { // Mario Head cursor
|
||||
*(s32*)cursorX = (s32)posX;
|
||||
*(s32*)cursorY = (s32)posY;
|
||||
} else { // Float, File select cursor
|
||||
*(float*)cursorX = posX;
|
||||
*(float*)cursorY = posY;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the controller mouse visible and update the previous mouse position
|
||||
controller_mouse_set_visible();
|
||||
mouse_prev_window_x = mouse_window_x;
|
||||
mouse_prev_window_y = mouse_window_y;
|
||||
|
||||
return mouse_has_current_control;
|
||||
}
|
||||
|
||||
void controller_mouse_read_window(void) {
|
||||
if (!mouse_init_ok) { return; }
|
||||
|
||||
#if defined(WAPI_DXGI)
|
||||
HWND game_window = gfx_dxgi_get_h_wnd();
|
||||
|
||||
mouse_window_buttons = controller_mouse_dxgi_button_state(
|
||||
&mouse_window_buttons_held_on_focus,
|
||||
GetFocus() == game_window);
|
||||
|
||||
POINT p;
|
||||
if (GetCursorPos(&p) && ScreenToClient(game_window, &p)) {
|
||||
mouse_window_x = p.x;
|
||||
mouse_window_y = p.y;
|
||||
}
|
||||
#elif defined(CAPI_SDL1) || defined(CAPI_SDL2)
|
||||
mouse_window_buttons = SDL_GetMouseState(&mouse_window_x, &mouse_window_y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void controller_mouse_read_relative(void) {
|
||||
if (!mouse_init_ok) { return; }
|
||||
|
||||
#if defined(WAPI_DXGI)
|
||||
HWND game_window = gfx_dxgi_get_h_wnd();
|
||||
|
||||
// Always get the buttons state, regardless if the relative mode is enabled.
|
||||
mouse_buttons = controller_mouse_dxgi_button_state(
|
||||
&mouse_relative_buttons_held_on_focus,
|
||||
GetFocus() == game_window);
|
||||
|
||||
if (mouse_relative_enabled) {
|
||||
static POINT p0;
|
||||
POINT p1;
|
||||
RECT rect;
|
||||
if (GetWindowRect(gfx_dxgi_get_h_wnd(), &rect) && GetCursorPos(&p1)) {
|
||||
mouse_x = p1.x - p0.x;
|
||||
mouse_y = p1.y - p0.y;
|
||||
|
||||
p0.x = rect.left + (rect.right - rect.left) / 2;
|
||||
p0.y = rect.top + (rect.bottom - rect.top) / 2;
|
||||
ClipCursor(&rect); // Prevents visible mouse if you move it too fast
|
||||
SetCursorPos(p0.x, p0.y);
|
||||
}
|
||||
} else {
|
||||
ClipCursor(NULL);
|
||||
mouse_x = 0;
|
||||
mouse_y = 0;
|
||||
}
|
||||
|
||||
#elif defined(CAPI_SDL1) || defined(CAPI_SDL2)
|
||||
mouse_buttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void controller_mouse_enter_relative(void) {
|
||||
if (!mouse_relative_enabled) {
|
||||
mouse_relative_enabled = true;
|
||||
|
||||
#if defined(WAPI_DXGI)
|
||||
gfx_dxgi_set_cursor_visibility(false);
|
||||
#elif defined(CAPI_SDL1)
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
#elif defined(CAPI_SDL2)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void controller_mouse_leave_relative(void) {
|
||||
if (mouse_relative_enabled) {
|
||||
mouse_relative_enabled = false;
|
||||
|
||||
#if defined(WAPI_DXGI)
|
||||
gfx_dxgi_set_cursor_visibility(configWindow.fullscreen ? FALSE : TRUE);
|
||||
#elif defined(CAPI_SDL1)
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
#elif defined(CAPI_SDL2)
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -3,15 +3,33 @@
|
|||
|
||||
#include "controller_api.h"
|
||||
#include "pc/gfx/gfx_pc.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
extern int gMouseXPos;
|
||||
extern int gMouseYPos;
|
||||
extern int gOldMouseXPos;
|
||||
extern int gOldMouseYPos;
|
||||
extern int gMouseHasFreeControl;
|
||||
extern int gMouseHasCenterControl;
|
||||
extern bool mouse_init_ok;
|
||||
|
||||
extern u32 mouse_buttons;
|
||||
extern s32 mouse_x;
|
||||
extern s32 mouse_y;
|
||||
|
||||
extern u32 mouse_window_buttons;
|
||||
extern s32 mouse_window_x;
|
||||
extern s32 mouse_window_y;
|
||||
|
||||
extern bool mouse_relative_enabled;
|
||||
|
||||
extern int mouse_prev_window_x;
|
||||
extern int mouse_prev_window_y;
|
||||
extern int mouse_has_current_control;
|
||||
extern int mouse_has_center_control;
|
||||
|
||||
void controller_mouse_set_visible(void);
|
||||
int controller_mouse_set_position(void *cursorX, void *cursorY, f32 mPosX, f32 mPosY, int hasControlCondition, int isInteger);
|
||||
void controller_mouse_read_window(void);
|
||||
void controller_mouse_read_relative(void);
|
||||
|
||||
void controller_mouse_enter_relative(void);
|
||||
void controller_mouse_leave_relative(void);
|
||||
|
||||
#define VK_BASE_MOUSE 0x2000
|
||||
|
||||
extern struct ControllerAPI controller_mouse;
|
||||
|
||||
|
|
|
@ -38,15 +38,6 @@ enum {
|
|||
MAX_AXES,
|
||||
};
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
int gMouseXPos;
|
||||
int gMouseYPos;
|
||||
int gOldMouseXPos;
|
||||
int gOldMouseYPos;
|
||||
int gMouseHasFreeControl;
|
||||
int gMouseHasCenterControl;
|
||||
#endif
|
||||
|
||||
static bool init_ok;
|
||||
static SDL_Joystick *sdl_joy;
|
||||
|
||||
|
@ -128,9 +119,17 @@ static void controller_sdl_init(void) {
|
|||
joy_axis_binds[i] = -1;
|
||||
}
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
if (mouse_has_center_control && sCurrPlayMode != 2) {
|
||||
controller_mouse_enter_relative();
|
||||
}
|
||||
controller_mouse_leave_relative();
|
||||
#endif
|
||||
|
||||
controller_sdl_bind();
|
||||
|
||||
init_ok = true;
|
||||
mouse_init_ok = true;
|
||||
}
|
||||
|
||||
static inline void update_button(const int i, const bool new) {
|
||||
|
@ -147,39 +146,27 @@ static inline int16_t get_axis(const int i) {
|
|||
}
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
void set_cursor_visibility(bool newVisibility) {
|
||||
if (last_cursor_status != newVisibility) {
|
||||
SDL_ShowCursor(newVisibility ? SDL_DISABLE : SDL_ENABLE);
|
||||
last_cursor_status = newVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_control_handler(OSContPad *pad) {
|
||||
u32 mouse;
|
||||
|
||||
if (configMouse) {
|
||||
set_cursor_visibility(gMouseHasFreeControl || configWindow.fullscreen);
|
||||
|
||||
if (gMouseHasCenterControl && sCurrPlayMode != 2) {
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
mouse = SDL_GetRelativeMouseState(&gMouseXPos, &gMouseYPos);
|
||||
} else {
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
mouse = SDL_GetMouseState(&gMouseXPos, &gMouseYPos);
|
||||
}
|
||||
} else {
|
||||
set_cursor_visibility(false);
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
mouse = SDL_GetMouseState(&gMouseXPos, &gMouseYPos);
|
||||
if (!configMouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse_has_center_control && sCurrPlayMode != 2) {
|
||||
controller_mouse_enter_relative();
|
||||
} else {
|
||||
controller_mouse_leave_relative();
|
||||
}
|
||||
|
||||
u32 mouse_prev = mouse_buttons;
|
||||
controller_mouse_read_relative();
|
||||
u32 mouse = mouse_buttons;
|
||||
|
||||
for (u32 i = 0; i < num_mouse_binds; ++i)
|
||||
if (mouse & SDL_BUTTON(mouse_binds[i][0]))
|
||||
pad->button |= mouse_binds[i][1];
|
||||
|
||||
// remember buttons that changed from 0 to 1
|
||||
last_mouse = (mouse_buttons ^ mouse) & mouse;
|
||||
mouse_buttons = mouse;
|
||||
last_mouse = (mouse_prev ^ mouse) & mouse;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -307,6 +294,7 @@ static void controller_sdl_shutdown(void) {
|
|||
}
|
||||
|
||||
init_ok = false;
|
||||
mouse_init_ok = false;
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_sdl = {
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
#include "controller_touchscreen.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
#include "controller_mouse.h"
|
||||
#endif
|
||||
|
||||
#include "game/level_update.h"
|
||||
|
||||
// mouse buttons are also in the controller namespace (why), just offset 0x100
|
||||
|
@ -31,15 +35,6 @@
|
|||
#define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers
|
||||
#define AXIS_THRESHOLD (30 * 256)
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
int gMouseXPos;
|
||||
int gMouseYPos;
|
||||
int gOldMouseXPos;
|
||||
int gOldMouseYPos;
|
||||
int gMouseHasFreeControl;
|
||||
int gMouseHasCenterControl;
|
||||
#endif
|
||||
|
||||
static bool init_ok;
|
||||
static bool haptics_enabled;
|
||||
static SDL_GameController *sdl_cntrl;
|
||||
|
@ -53,9 +48,7 @@ static u32 last_joybutton = VK_INVALID;
|
|||
#ifdef MOUSE_ACTIONS
|
||||
static u32 mouse_binds[MAX_JOYBINDS][2];
|
||||
static u32 num_mouse_binds = 0;
|
||||
static u32 mouse_buttons = 0;
|
||||
static u32 last_mouse = VK_INVALID;
|
||||
bool last_cursor_status = false;
|
||||
#endif
|
||||
|
||||
static inline void controller_add_binds(const u32 mask, const u32 *btns) {
|
||||
|
@ -124,9 +117,17 @@ static void controller_sdl_init(void) {
|
|||
|
||||
haptics_enabled = (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
if (mouse_has_center_control && sCurrPlayMode != 2) {
|
||||
controller_mouse_enter_relative();
|
||||
}
|
||||
controller_mouse_leave_relative();
|
||||
#endif
|
||||
|
||||
controller_sdl_bind();
|
||||
|
||||
init_ok = true;
|
||||
mouse_init_ok = true;
|
||||
}
|
||||
|
||||
static SDL_Haptic *controller_sdl_init_haptics(const int joy) {
|
||||
|
@ -156,39 +157,27 @@ static inline void update_button(const int i, const bool new) {
|
|||
}
|
||||
|
||||
#ifdef MOUSE_ACTIONS
|
||||
void set_cursor_visibility(bool newVisibility) {
|
||||
if (last_cursor_status != newVisibility) {
|
||||
SDL_ShowCursor(newVisibility ? SDL_DISABLE : SDL_ENABLE);
|
||||
last_cursor_status = newVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_control_handler(OSContPad *pad) {
|
||||
u32 mouse;
|
||||
|
||||
if (configMouse) {
|
||||
set_cursor_visibility(gMouseHasFreeControl || configWindow.fullscreen);
|
||||
|
||||
if (gMouseHasCenterControl && sCurrPlayMode != 2) {
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
mouse = SDL_GetRelativeMouseState(&gMouseXPos, &gMouseYPos);
|
||||
} else {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
mouse = SDL_GetMouseState(&gMouseXPos, &gMouseYPos);
|
||||
}
|
||||
} else {
|
||||
set_cursor_visibility(false);
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
mouse = SDL_GetMouseState(&gMouseXPos, &gMouseYPos);
|
||||
if (!configMouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse_has_center_control && sCurrPlayMode != 2) {
|
||||
controller_mouse_enter_relative();
|
||||
} else {
|
||||
controller_mouse_leave_relative();
|
||||
}
|
||||
|
||||
u32 mouse_prev = mouse_buttons;
|
||||
controller_mouse_read_relative();
|
||||
u32 mouse = mouse_buttons;
|
||||
|
||||
for (u32 i = 0; i < num_mouse_binds; ++i)
|
||||
if (mouse & SDL_BUTTON(mouse_binds[i][0]))
|
||||
pad->button |= mouse_binds[i][1];
|
||||
|
||||
// remember buttons that changed from 0 to 1
|
||||
last_mouse = (mouse_buttons ^ mouse) & mouse;
|
||||
mouse_buttons = mouse;
|
||||
last_mouse = (mouse_prev ^ mouse) & mouse;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -350,6 +339,7 @@ static void controller_sdl_shutdown(void) {
|
|||
|
||||
haptics_enabled = false;
|
||||
init_ok = false;
|
||||
mouse_init_ok = false;
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_sdl = {
|
||||
|
|
|
@ -157,6 +157,32 @@ static bool gfx_dxgi_is_window_maximized(void) {
|
|||
return window_placement.showCmd == SW_SHOWMAXIMIZED;
|
||||
}
|
||||
|
||||
extern "C" void gfx_dxgi_set_cursor_visibility(bool visible) {
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showcursor
|
||||
// https://devblogs.microsoft.com/oldnewthing/20091217-00/?p=15643
|
||||
// ShowCursor uses a counter, not a boolean value, and increments or decrements that value when called
|
||||
// This means we need to keep calling it until we get the value we want
|
||||
|
||||
//
|
||||
// NOTE: If you continue calling until you "get the value you want" and there is no mouse attached,
|
||||
// it will lock the software up. Windows always returns -1 if there is no mouse!
|
||||
//
|
||||
|
||||
const int _MAX_TRIES = 15; // Prevent spinning infinitely if no mouse is plugged in
|
||||
|
||||
int cursorVisibilityTries = 0;
|
||||
int cursorVisibilityCounter;
|
||||
if (visible) {
|
||||
do {
|
||||
cursorVisibilityCounter = ShowCursor(true);
|
||||
} while (cursorVisibilityCounter < 0 && ++cursorVisibilityTries < _MAX_TRIES);
|
||||
} else {
|
||||
do {
|
||||
cursorVisibilityCounter = ShowCursor(false);
|
||||
} while (cursorVisibilityCounter >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void toggle_borderless_window_full_screen(bool enable) {
|
||||
// Windows 7 + flip mode + waitable object can't go to exclusive fullscreen,
|
||||
// so do borderless instead. If DWM is enabled, this means we get one monitor
|
||||
|
@ -183,7 +209,6 @@ static void toggle_borderless_window_full_screen(bool enable) {
|
|||
ShowWindow(dxgi.h_wnd, SW_RESTORE);
|
||||
}
|
||||
configWindow.exiting_fullscreen = false;
|
||||
//ShowCursor(TRUE);
|
||||
} else {
|
||||
dxgi.is_full_screen = true; // Call this early so it doesn't get called twice
|
||||
|
||||
|
@ -207,8 +232,6 @@ static void toggle_borderless_window_full_screen(bool enable) {
|
|||
// Set borderless full screen to that monitor
|
||||
SetWindowLongPtr(dxgi.h_wnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
SetWindowPos(dxgi.h_wnd, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED);
|
||||
|
||||
//ShowCursor(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,8 +258,10 @@ static void gfx_dxgi_set_fullscreen(void) {
|
|||
return;
|
||||
if (configWindow.fullscreen) {
|
||||
toggle_borderless_window_full_screen(true);
|
||||
gfx_dxgi_set_cursor_visibility(false);
|
||||
} else {
|
||||
toggle_borderless_window_full_screen(false);
|
||||
gfx_dxgi_set_cursor_visibility(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,7 +682,7 @@ ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
|
|||
return dxgi.swap_chain;
|
||||
}
|
||||
|
||||
HWND gfx_dxgi_get_h_wnd(void) {
|
||||
extern "C" HWND gfx_dxgi_get_h_wnd(void) {
|
||||
return dxgi.h_wnd;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#ifdef DECLARE_GFX_DXGI_FUNCTIONS
|
||||
void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only));
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device);
|
||||
HWND gfx_dxgi_get_h_wnd(void);
|
||||
extern "C" void gfx_dxgi_set_cursor_visibility(bool visible);
|
||||
extern "C" HWND gfx_dxgi_get_h_wnd(void);
|
||||
void ThrowIfFailed(HRESULT res);
|
||||
void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue