Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When mouse is locked in window, confine its position to the game viewport #2675

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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