Skip to content

Commit

Permalink
Merge pull request #2675 from ivan-mogilko/362--mousegrabtorect
Browse files Browse the repository at this point in the history
When mouse is locked in window, confine its position to the game viewport
  • Loading branch information
ivan-mogilko authored Feb 6, 2025
2 parents 0bb5e7b + 5126a51 commit 6cdc6e4
Show file tree
Hide file tree
Showing 13 changed files with 48 additions and 45 deletions.
6 changes: 3 additions & 3 deletions Engine/ac/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extern int displayed_room;
extern CharacterInfo*playerchar;
extern int eip_guinum;
extern int cur_mode,cur_cursor;
extern int hotx,hoty;
extern int mouse_hotx, mouse_hoty;
extern int bg_just_changed;


Expand Down Expand Up @@ -2831,8 +2831,8 @@ void construct_game_screen_overlay(bool draw_mouse)
{
// Exclusive sub-batch for mouse cursor, to let filter it out (CHECKME later?)
gfxDriver->BeginSpriteBatch(Rect(), SpriteTransform(), kFlip_None, nullptr, RENDER_BATCH_MOUSE_CURSOR);
gfxDriver->DrawSprite(mousex - hotx, mousey - hoty, cursor_tx.Ddb);
invalidate_sprite(mousex - hotx, mousey - hoty, cursor_tx.Ddb, false);
gfxDriver->DrawSprite(mousex - mouse_hotx, mousey - mouse_hoty, cursor_tx.Ddb);
invalidate_sprite(mousex - mouse_hotx, mousey - mouse_hoty, cursor_tx.Ddb, false);
gfxDriver->EndSpriteBatch();
}
}
Expand Down
4 changes: 2 additions & 2 deletions Engine/ac/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1520,8 +1520,8 @@ void display_switch_in()
{
Debug::Printf("Switching back into the game");
ags_clear_input_state();
// If auto lock option is set, lock mouse to the game window
if (usetup.MouseAutoLock && scsystem.windowed)
// If fullscreen, or auto lock option is set, lock mouse to the game window
if ((scsystem.windowed == 0) || usetup.MouseAutoLock)
Mouse::TryLockToWindow();
switched_away = false;
}
Expand Down
4 changes: 3 additions & 1 deletion Engine/ac/mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ extern IGraphicsDriver *gfxDriver;

ScriptMouse scmouse;
int cur_mode,cur_cursor;
int mouse_hotx = 0, mouse_hoty = 0; // in game cursor hotspot offset
int mouse_frame=0,mouse_delay=0;
int lastmx=-1,lastmy=-1;

Expand Down Expand Up @@ -122,7 +123,7 @@ void SetMouseBounds(int x1, int y1, int x2, int y2)
void set_mouse_cursor(int newcurs, bool force_update)
{
const int hotspotx = game.mcurs[newcurs].hotx, hotspoty = game.mcurs[newcurs].hoty;
Mouse::SetHotspot(hotspotx, hotspoty);
mouse_hotx = hotspotx, mouse_hoty = hotspoty;

// if it's same cursor and there's animation in progress, then don't assign a new pic just yet
if (!force_update &&
Expand Down Expand Up @@ -357,6 +358,7 @@ bool Mouse_GetAutoLock()
void Mouse_SetAutoLock(bool on)
{
usetup.MouseAutoLock = on;
// Only update when in windowed mode, as always locked in fullscreen
if (scsystem.windowed)
{
if (usetup.MouseAutoLock)
Expand Down
2 changes: 1 addition & 1 deletion Engine/ac/mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extern ScriptMouse scmouse;
extern CursorGraphicState cursor_gstate;

extern int mousex, mousey;
extern char ignore_bounds;
extern int ignore_bounds;
extern int cur_mode;
extern int cur_cursor;

Expand Down
36 changes: 11 additions & 25 deletions Engine/device/mousew32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,12 @@ using namespace AGS::Common;
using namespace AGS::Engine;


char currentcursor = 0;
// virtual mouse cursor coordinates
int mousex = 0, mousey = 0, numcurso = -1, hotx = 0, hoty = 0;
int mousex = 0, mousey = 0;
// real mouse coordinates and bounds (in window coords)
static int real_mouse_x = 0, real_mouse_y = 0;
static int boundx1 = 0, boundx2 = 99999, boundy1 = 0, boundy2 = 99999;
char ignore_bounds = 0;
extern char alpha_blend_cursor;
extern RGB palette[256];
static Rect mouse_bounds;
int ignore_bounds = 0; // NOTE: this works as a counter for some reason, review later
extern volatile bool switched_away;

namespace Mouse
Expand Down Expand Up @@ -71,10 +68,10 @@ Point Mouse::SysToGamePos(int sys_mx, int sys_my)
// Clamp to control rect, and optionally script bounds
int mx = Math::Clamp(sys_mx, Mouse::ControlRect.Left, Mouse::ControlRect.Right);
int my = Math::Clamp(sys_my, Mouse::ControlRect.Top, Mouse::ControlRect.Bottom);
if (!ignore_bounds)
if (ignore_bounds == 0)
{
mx = Math::Clamp(mx, boundx1, boundx2);
my = Math::Clamp(my, boundy1, boundy2);
mx = Math::Clamp(mx, mouse_bounds.Left, mouse_bounds.Right);
my = Math::Clamp(my, mouse_bounds.Top, mouse_bounds.Bottom);
}
// Convert to virtual coordinates
Mouse::WindowToGame(mx, my);
Expand All @@ -98,11 +95,10 @@ void Mouse::Poll()
mousex = real_mouse_x;
mousey = real_mouse_y;
// Optionally apply script bounds
if (!ignore_bounds &&
(mousex < boundx1 || mousey < boundy1 || mousex > boundx2 || mousey > boundy2))
if ((ignore_bounds == 0) && (!mouse_bounds.IsInside(mousex, mousey)))
{
mousex = Math::Clamp(mousex, boundx1, boundx2);
mousey = Math::Clamp(mousey, boundy1, boundy2);
mousex = Math::Clamp(mousex, mouse_bounds.Left, mouse_bounds.Right);
mousey = Math::Clamp(mousey, mouse_bounds.Top, mouse_bounds.Bottom);
Mouse::SetSysPosition(mousex, mousey);
}
// Convert to virtual coordinates
Expand All @@ -118,12 +114,6 @@ void Mouse::SetSysPosition(int x, int y)
sys_window_set_mouse(real_mouse_x, real_mouse_y);
}

void Mouse::SetHotspot(int x, int y)
{
hotx = x;
hoty = y;
}

int Mouse::GetButtonCount()
{
// TODO: can SDL tell number of available/supported buttons at all, or whether mouse is present?
Expand All @@ -148,11 +138,7 @@ void Mouse::UpdateGraphicArea()
void Mouse::SetMoveLimit(const Rect &r)
{
Rect src_r = OffsetRect(r, play.GetMainViewport().GetLT());
Rect dst_r = GameScaling.ScaleRange(src_r);
boundx1 = dst_r.Left;
boundy1 = dst_r.Top;
boundx2 = dst_r.Right;
boundy2 = dst_r.Bottom;
mouse_bounds = GameScaling.ScaleRange(src_r);
}

void Mouse::SetPosition(const Point &p)
Expand All @@ -170,7 +156,7 @@ bool Mouse::IsLockedToWindow()
bool Mouse::TryLockToWindow()
{
if (!LockedToWindow)
LockedToWindow = sys_window_lock_mouse(true);
LockedToWindow = sys_window_lock_mouse(true, Mouse::ControlRect);
return LockedToWindow;
}

Expand Down
4 changes: 0 additions & 4 deletions Engine/device/mousew32.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,7 @@ namespace Mouse
void Poll();
// Set actual OS cursor position on screen; in native game coordinates
void SetPosition(const Point &p);
// Sets the relative position of the cursor's hotspot, in native pixels
void SetHotspot(int x, int y);
}


extern int mousex, mousey;
extern int hotx, hoty;
extern char currentcursor;
6 changes: 3 additions & 3 deletions Engine/gfx/ali3dsw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static auto fix_alpha_blender = SDL_ComposeCustomBlendMode(
SDL_BLENDFACTOR_ZERO,
SDL_BLENDOPERATION_ADD
);
#endif
#endif // SDL_VERSION_ATLEAST(2, 0, 5)

SDLRendererGraphicsDriver::SDLRendererGraphicsDriver()
{
Expand Down Expand Up @@ -799,7 +799,7 @@ static uint32_t _trans_alpha_blender32(uint32_t x, uint32_t y, uint32_t n)

bool SDLRendererGraphicsDriver::SetVsyncImpl(bool enabled, bool &vsync_res)
{
#if SDL_VERSION_ATLEAST(2, 0, 18)
#if SDL_VERSION_ATLEAST(2, 0, 18)
if (SDL_RenderSetVSync(_renderer, enabled) == 0) // 0 on success
{
// gamma might be lost after changing vsync mode at fullscreen
Expand All @@ -810,7 +810,7 @@ bool SDLRendererGraphicsDriver::SetVsyncImpl(bool enabled, bool &vsync_res)
return true;
}
Debug::Printf(kDbgMsg_Warn, "SDLRenderer: SetVsync (%d) failed: %s", enabled, SDL_GetError());
#endif
#endif // SDL_VERSION_ATLEAST(2, 0, 18)
return false;
}

Expand Down
2 changes: 0 additions & 2 deletions Engine/gui/mylistbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

using namespace AGS::Common;

extern int numcurso, hotx, hoty;

extern int windowbackgroundcolor;
extern int cbuttfont;
extern int smcode;
Expand Down
1 change: 0 additions & 1 deletion Engine/main/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,6 @@ void engine_init_game_settings()
update_invorder();
displayed_room = -10;

currentcursor=0;
set_our_eip(-4);
mousey=100; // stop icon bar popping up

Expand Down
4 changes: 2 additions & 2 deletions Engine/main/engine_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ void engine_post_gfxmode_mouse_setup(const Size &init_desktop)

on_coordinates_scaling_changed();

// If auto lock option is set, lock mouse to the game window
if (usetup.MouseAutoLock && scsystem.windowed != 0)
// If fullscreen, or auto lock option is set, lock mouse to the game window
if ((scsystem.windowed == 0) || usetup.MouseAutoLock)
Mouse::TryLockToWindow();
}

Expand Down
4 changes: 3 additions & 1 deletion Engine/main/game_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,14 @@ static bool game_loop_check_ground_level_interactions()

static void lock_mouse_on_click()
{
if (usetup.MouseAutoLock && scsystem.windowed)
// Only update when in windowed mode, as always locked in fullscreen
if (usetup.MouseAutoLock && scsystem.windowed != 0)
Mouse::TryLockToWindow();
}

static void toggle_mouse_lock()
{
// Only update when in windowed mode, as always locked in fullscreen
if (scsystem.windowed)
{
if (Mouse::IsLockedToWindow())
Expand Down
19 changes: 19 additions & 0 deletions Engine/platform/base/sys_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,27 @@ void sys_window_show_cursor(bool on) {
}

bool sys_window_lock_mouse(bool on) {
return sys_window_lock_mouse(on, Rect());
}

bool sys_window_lock_mouse(bool on, const Rect &bounds) {
if (!window) return false;
SDL_SetWindowGrab(window, static_cast<SDL_bool>(on));
#if SDL_VERSION_ATLEAST(2, 0, 18)
if (on && !bounds.IsEmpty())
{
SDL_Rect rect;
rect.x = bounds.Left;
rect.y = bounds.Top;
rect.w = bounds.GetWidth();
rect.h = bounds.GetHeight();
SDL_SetWindowMouseRect(window, &rect);
}
else
{
SDL_SetWindowMouseRect(window, nullptr);
}
#endif // SDL_VERSION_ATLEAST(2, 0, 18)
return on; // TODO: test if successful?
}

Expand Down
1 change: 1 addition & 0 deletions Engine/platform/base/sys_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void sys_window_show_cursor(bool on);
// Locks on unlocks mouse inside the window.
// Returns new state of the mouse lock.
bool sys_window_lock_mouse(bool on);
bool sys_window_lock_mouse(bool on, const Rect &bounds);
// Sets mouse position within the game window
void sys_window_set_mouse(int x, int y);
// Destroy current game window, if one exists.
Expand Down

0 comments on commit 6cdc6e4

Please sign in to comment.