From 1fe000a8be14dbcbc2d9a37761659d4fd0f6f98e Mon Sep 17 00:00:00 2001 From: Eliandro <153942958+Eliandro4@users.noreply.github.com> Date: Sat, 6 Jun 2026 13:03:50 -0300 Subject: [PATCH 1/3] set and get cursor --- src/desktop/backends/glfw2.c | 11 +++++++++++ src/desktop/backends/glfw3.c | 31 +++++++++++++++++++++++++++++++ src/desktop/backends/sdl1.c | 7 +++++++ src/desktop/backends/sdl2.c | 31 +++++++++++++++++++++++++++++++ src/desktop/platformdefs.h | 1 + src/runner.h | 2 ++ src/vm_builtins.c | 20 ++++++++++++++++++++ 7 files changed, 103 insertions(+) diff --git a/src/desktop/backends/glfw2.c b/src/desktop/backends/glfw2.c index ad870252..b455738b 100644 --- a/src/desktop/backends/glfw2.c +++ b/src/desktop/backends/glfw2.c @@ -221,9 +221,20 @@ void platformExit(void) { glfwTerminate(); } +static void platformSetCursor(int32_t cursorType) { + // GLFW2 only supports showing/hiding + if (cursorType == -1) { + glfwDisable(GLFW_MOUSE_CURSOR); + } else { + glfwEnable(GLFW_MOUSE_CURSOR); + } +} + void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; + runner->setCursor = platformSetCursor; + runner->currentCursor = 0; // cr_default #ifdef ENABLE_SW_RENDERER if (gfx == SOFTWARE) glfwSetWindowSizeCallback(resizeCallback); diff --git a/src/desktop/backends/glfw3.c b/src/desktop/backends/glfw3.c index 9bf1db82..f78fbdfe 100644 --- a/src/desktop/backends/glfw3.c +++ b/src/desktop/backends/glfw3.c @@ -252,9 +252,40 @@ void platformExit(void) { glfwTerminate(); } +static void platformSetCursor(int32_t cursorType) { + if (cursorType == -1) { + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + return; + } + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + + int glfwShape; + switch (cursorType) { + case -3: glfwShape = GLFW_CROSSHAIR_CURSOR; break; + case -4: glfwShape = GLFW_IBEAM_CURSOR; break; + case -7: glfwShape = GLFW_VRESIZE_CURSOR; break; + case -9: glfwShape = GLFW_HRESIZE_CURSOR; break; + case -12: glfwShape = GLFW_HAND_CURSOR; break; + case -21: glfwShape = GLFW_HAND_CURSOR; break; + #if (GLFW_VERSION_MINOR >= 4) + case -22: glfwShape = GLFW_RESIZE_ALL_CURSOR; break; + case -8: glfwShape = GLFW_RESIZE_NWSE_CURSOR; break; + case -6: glfwShape = GLFW_RESIZE_NESW_CURSOR; break; + #endif + default: glfwShape = GLFW_ARROW_CURSOR; break; + } + + GLFWcursor* cursor = glfwCreateStandardCursor(glfwShape); + if (cursor) { + glfwSetCursor(window, cursor); + } +} + void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; + runner->setCursor = platformSetCursor; + runner->currentCursor = 0; // cr_default #ifdef ENABLE_SW_RENDERER if (gfx == SOFTWARE) glfwSetWindowSizeCallback(window, resizeCallback); diff --git a/src/desktop/backends/sdl1.c b/src/desktop/backends/sdl1.c index 369952da..0eea5d4e 100644 --- a/src/desktop/backends/sdl1.c +++ b/src/desktop/backends/sdl1.c @@ -101,9 +101,16 @@ void platformExit(void) { SDL_Quit(); } +static void platformSetCursor(int32_t cursorType) { + // SDL1.2 only supports showing/hiding + SDL_ShowCursor(cursorType == -1 ? SDL_DISABLE : SDL_ENABLE); +} + void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; + runner->setCursor = platformSetCursor; + runner->currentCursor = 0; // cr_default } #ifdef ENABLE_SW_RENDERER diff --git a/src/desktop/backends/sdl2.c b/src/desktop/backends/sdl2.c index 481b8f49..1ef91a69 100644 --- a/src/desktop/backends/sdl2.c +++ b/src/desktop/backends/sdl2.c @@ -159,9 +159,40 @@ void platformExit(void) { SDL_Quit(); } +static void platformSetCursor(int32_t cursorType) { + if (cursorType == -1) { + SDL_ShowCursor(SDL_DISABLE); + return; + } + SDL_ShowCursor(SDL_ENABLE); + + SDL_SystemCursor sdlCursor; + switch (cursorType) { + case -3: sdlCursor = SDL_SYSTEM_CURSOR_CROSSHAIR; break; + case -4: sdlCursor = SDL_SYSTEM_CURSOR_IBEAM; break; + case -6: sdlCursor = SDL_SYSTEM_CURSOR_SIZENESW; break; + case -7: sdlCursor = SDL_SYSTEM_CURSOR_SIZENS; break; + case -8: sdlCursor = SDL_SYSTEM_CURSOR_SIZENWSE; break; + case -9: sdlCursor = SDL_SYSTEM_CURSOR_SIZEWE; break; + case -11: sdlCursor = SDL_SYSTEM_CURSOR_WAIT; break; + case -12: sdlCursor = SDL_SYSTEM_CURSOR_SIZEALL; break; + case -19: sdlCursor = SDL_SYSTEM_CURSOR_WAITARROW; break; + case -21: sdlCursor = SDL_SYSTEM_CURSOR_HAND; break; + case -22: sdlCursor = SDL_SYSTEM_CURSOR_SIZEALL; break; + default: sdlCursor = SDL_SYSTEM_CURSOR_ARROW; break; + } + + SDL_Cursor* cursor = SDL_CreateSystemCursor(sdlCursor); + if (cursor) { + SDL_SetCursor(cursor); + } +} + void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; + runner->setCursor = platformSetCursor; + runner->currentCursor = 0; // cr_default } #ifdef ENABLE_SW_RENDERER diff --git a/src/desktop/platformdefs.h b/src/desktop/platformdefs.h index e45b5c49..70df71ab 100644 --- a/src/desktop/platformdefs.h +++ b/src/desktop/platformdefs.h @@ -18,6 +18,7 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH); void platformSetWindowSize(int32_t width, int32_t height); void platformSetWindowTitle(const char* title); void platformSleepUntil(uint64_t time); +void platformSetCursor(int32_t cursorType); enum GraphicsAPI { SOFTWARE, diff --git a/src/runner.h b/src/runner.h index bd3d21f7..129fa2f9 100644 --- a/src/runner.h +++ b/src/runner.h @@ -491,6 +491,8 @@ struct Runner { bool (*getWindowSize)(int32_t* outW, int32_t* outH); void (*setWindowSize)(int32_t width, int32_t height); bool (*windowHasFocus)(void); + void (*setCursor)(int32_t cursorType); + int32_t currentCursor; // last value passed to window_set_cursor TileLayerMapEntry* tileLayerMap; // stb_ds hashmap: depth -> tile layer state RuntimeLayer* runtimeLayers; // stb_ds array, index-parallel to currentRoom->layers for parsed entries; dynamic entries appended uint32_t nextLayerId; // counter for IDs of layers/elements created at runtime diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 2b72f36b..5c3d07d8 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -7257,6 +7257,24 @@ static RValue builtin_window_has_focus(VMContext* ctx, MAYBE_UNUSED RValue* args return RValue_makeBool(true); } +static RValue builtin_window_set_cursor(VMContext* ctx, RValue* args, int32_t argCount) { + if (argCount < 1) return RValue_makeUndefined(); + Runner* runner = ctx->runner; + if (runner == nullptr) return RValue_makeUndefined(); + int32_t cursorType = RValue_toInt32(args[0]); + runner->currentCursor = cursorType; + if (runner->setCursor != nullptr) { + runner->setCursor(cursorType); + } + return RValue_makeUndefined(); +} + +static RValue builtin_window_get_cursor(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + Runner* runner = ctx->runner; + if (runner == nullptr) return RValue_makeReal(0); + return RValue_makeReal(runner->currentCursor); +} + // ===[ Game State Functions ]=== static RValue builtin_game_restart(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { ctx->runner->pendingRoom = ROOM_RESTARTGAME; @@ -15108,6 +15126,8 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "window_set_size", builtin_window_set_size); VM_registerBuiltin(ctx, "window_center", builtin_window_center); VM_registerBuiltin(ctx, "window_has_focus", builtin_window_has_focus); + VM_registerBuiltin(ctx, "window_set_cursor", builtin_window_set_cursor); + VM_registerBuiltin(ctx, "window_get_cursor", builtin_window_get_cursor); // Game VM_registerBuiltin(ctx, "game_restart", builtin_game_restart); From 3257ed8af2d45f3cbc99abf0c05d5a76060f0a50 Mon Sep 17 00:00:00 2001 From: Eliandro <153942958+Eliandro4@users.noreply.github.com> Date: Sat, 13 Jun 2026 07:25:33 -0300 Subject: [PATCH 2/3] defining cursor magic values --- src/desktop/backends/glfw2.c | 5 +++-- src/desktop/backends/glfw3.c | 23 ++++++++++++----------- src/desktop/backends/sdl1.c | 5 +++-- src/desktop/backends/sdl2.c | 27 ++++++++++++++------------- src/desktop/platformdefs.h | 1 - src/runner_mouse.h | 17 +++++++++++++++++ 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/desktop/backends/glfw2.c b/src/desktop/backends/glfw2.c index b455738b..f42269da 100644 --- a/src/desktop/backends/glfw2.c +++ b/src/desktop/backends/glfw2.c @@ -14,6 +14,7 @@ #include "input_recording.h" #include "desktop/platformdefs.h" #include "gettime.h" +#include "runner_mouse.h" static Runner *g_runner; @@ -223,7 +224,7 @@ void platformExit(void) { static void platformSetCursor(int32_t cursorType) { // GLFW2 only supports showing/hiding - if (cursorType == -1) { + if (cursorType == GML_CR_NONE) { glfwDisable(GLFW_MOUSE_CURSOR); } else { glfwEnable(GLFW_MOUSE_CURSOR); @@ -234,7 +235,7 @@ void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; runner->setCursor = platformSetCursor; - runner->currentCursor = 0; // cr_default + runner->currentCursor = GML_CR_DEFAULT; #ifdef ENABLE_SW_RENDERER if (gfx == SOFTWARE) glfwSetWindowSizeCallback(resizeCallback); diff --git a/src/desktop/backends/glfw3.c b/src/desktop/backends/glfw3.c index f78fbdfe..9eb69764 100644 --- a/src/desktop/backends/glfw3.c +++ b/src/desktop/backends/glfw3.c @@ -16,6 +16,7 @@ #include "input_recording.h" #include "desktop/platformdefs.h" #include "gettime.h" +#include "runner_mouse.h" static GLFWwindow *window; static Runner *g_runner; @@ -253,7 +254,7 @@ void platformExit(void) { } static void platformSetCursor(int32_t cursorType) { - if (cursorType == -1) { + if (cursorType == GML_CR_NONE) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); return; } @@ -261,16 +262,16 @@ static void platformSetCursor(int32_t cursorType) { int glfwShape; switch (cursorType) { - case -3: glfwShape = GLFW_CROSSHAIR_CURSOR; break; - case -4: glfwShape = GLFW_IBEAM_CURSOR; break; - case -7: glfwShape = GLFW_VRESIZE_CURSOR; break; - case -9: glfwShape = GLFW_HRESIZE_CURSOR; break; - case -12: glfwShape = GLFW_HAND_CURSOR; break; - case -21: glfwShape = GLFW_HAND_CURSOR; break; + case GML_CR_CROSS: glfwShape = GLFW_CROSSHAIR_CURSOR; break; + case GML_CR_BEAM: glfwShape = GLFW_IBEAM_CURSOR; break; + case GML_CR_SIZE_NS: glfwShape = GLFW_VRESIZE_CURSOR; break; + case GML_CR_SIZE_WE: glfwShape = GLFW_HRESIZE_CURSOR; break; + case GML_CR_DRAG: glfwShape = GLFW_HAND_CURSOR; break; + case GML_CR_HANDPOINT: glfwShape = GLFW_HAND_CURSOR; break; #if (GLFW_VERSION_MINOR >= 4) - case -22: glfwShape = GLFW_RESIZE_ALL_CURSOR; break; - case -8: glfwShape = GLFW_RESIZE_NWSE_CURSOR; break; - case -6: glfwShape = GLFW_RESIZE_NESW_CURSOR; break; + case GML_CR_SIZE_ALL: glfwShape = GLFW_RESIZE_ALL_CURSOR; break; + case GML_CR_SIZE_NWSE: glfwShape = GLFW_RESIZE_NWSE_CURSOR; break; + case GML_CR_SIZE_NESW: glfwShape = GLFW_RESIZE_NESW_CURSOR; break; #endif default: glfwShape = GLFW_ARROW_CURSOR; break; } @@ -285,7 +286,7 @@ void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; runner->setCursor = platformSetCursor; - runner->currentCursor = 0; // cr_default + runner->currentCursor = GML_CR_DEFAULT; #ifdef ENABLE_SW_RENDERER if (gfx == SOFTWARE) glfwSetWindowSizeCallback(window, resizeCallback); diff --git a/src/desktop/backends/sdl1.c b/src/desktop/backends/sdl1.c index 0eea5d4e..30b04b54 100644 --- a/src/desktop/backends/sdl1.c +++ b/src/desktop/backends/sdl1.c @@ -16,6 +16,7 @@ #ifndef SDL_BUTTON_WHEELDOWN #define SDL_BUTTON_WHEELDOWN 5 #endif +#include "runner_mouse.h" static Runner *g_runner; static int32_t fbWidth, fbHeight; @@ -103,14 +104,14 @@ void platformExit(void) { static void platformSetCursor(int32_t cursorType) { // SDL1.2 only supports showing/hiding - SDL_ShowCursor(cursorType == -1 ? SDL_DISABLE : SDL_ENABLE); + SDL_ShowCursor(cursorType == GML_CR_NONE ? SDL_DISABLE : SDL_ENABLE); } void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; runner->setCursor = platformSetCursor; - runner->currentCursor = 0; // cr_default + runner->currentCursor = GML_CR_DEFAULT; } #ifdef ENABLE_SW_RENDERER diff --git a/src/desktop/backends/sdl2.c b/src/desktop/backends/sdl2.c index 1ef91a69..91029a63 100644 --- a/src/desktop/backends/sdl2.c +++ b/src/desktop/backends/sdl2.c @@ -8,6 +8,7 @@ #include "input_recording.h" #include "desktop/platformdefs.h" #include "gettime.h" +#include "runner_mouse.h" static Runner *g_runner; static SDL_Surface* scr; @@ -160,7 +161,7 @@ void platformExit(void) { } static void platformSetCursor(int32_t cursorType) { - if (cursorType == -1) { + if (cursorType == GML_CR_NONE) { SDL_ShowCursor(SDL_DISABLE); return; } @@ -168,17 +169,17 @@ static void platformSetCursor(int32_t cursorType) { SDL_SystemCursor sdlCursor; switch (cursorType) { - case -3: sdlCursor = SDL_SYSTEM_CURSOR_CROSSHAIR; break; - case -4: sdlCursor = SDL_SYSTEM_CURSOR_IBEAM; break; - case -6: sdlCursor = SDL_SYSTEM_CURSOR_SIZENESW; break; - case -7: sdlCursor = SDL_SYSTEM_CURSOR_SIZENS; break; - case -8: sdlCursor = SDL_SYSTEM_CURSOR_SIZENWSE; break; - case -9: sdlCursor = SDL_SYSTEM_CURSOR_SIZEWE; break; - case -11: sdlCursor = SDL_SYSTEM_CURSOR_WAIT; break; - case -12: sdlCursor = SDL_SYSTEM_CURSOR_SIZEALL; break; - case -19: sdlCursor = SDL_SYSTEM_CURSOR_WAITARROW; break; - case -21: sdlCursor = SDL_SYSTEM_CURSOR_HAND; break; - case -22: sdlCursor = SDL_SYSTEM_CURSOR_SIZEALL; break; + case GML_CR_CROSS: sdlCursor = SDL_SYSTEM_CURSOR_CROSSHAIR; break; + case GML_CR_BEAM: sdlCursor = SDL_SYSTEM_CURSOR_IBEAM; break; + case GML_CR_SIZE_NESW: sdlCursor = SDL_SYSTEM_CURSOR_SIZENESW; break; + case GML_CR_SIZE_NS: sdlCursor = SDL_SYSTEM_CURSOR_SIZENS; break; + case GML_CR_SIZE_NWSE: sdlCursor = SDL_SYSTEM_CURSOR_SIZENWSE; break; + case GML_CR_SIZE_WE: sdlCursor = SDL_SYSTEM_CURSOR_SIZEWE; break; + case GML_CR_HOURGLASS: sdlCursor = SDL_SYSTEM_CURSOR_WAIT; break; + case GML_CR_DRAG: sdlCursor = SDL_SYSTEM_CURSOR_HAND; break; + case GML_CR_APPSTART: sdlCursor = SDL_SYSTEM_CURSOR_WAITARROW; break; + case GML_CR_HANDPOINT: sdlCursor = SDL_SYSTEM_CURSOR_HAND; break; + case GML_CR_SIZE_ALL: sdlCursor = SDL_SYSTEM_CURSOR_SIZEALL; break; default: sdlCursor = SDL_SYSTEM_CURSOR_ARROW; break; } @@ -192,7 +193,7 @@ void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; runner->setCursor = platformSetCursor; - runner->currentCursor = 0; // cr_default + runner->currentCursor = GML_CR_DEFAULT; } #ifdef ENABLE_SW_RENDERER diff --git a/src/desktop/platformdefs.h b/src/desktop/platformdefs.h index 70df71ab..e45b5c49 100644 --- a/src/desktop/platformdefs.h +++ b/src/desktop/platformdefs.h @@ -18,7 +18,6 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH); void platformSetWindowSize(int32_t width, int32_t height); void platformSetWindowTitle(const char* title); void platformSleepUntil(uint64_t time); -void platformSetCursor(int32_t cursorType); enum GraphicsAPI { SOFTWARE, diff --git a/src/runner_mouse.h b/src/runner_mouse.h index 18db1d90..d28d3101 100644 --- a/src/runner_mouse.h +++ b/src/runner_mouse.h @@ -16,6 +16,23 @@ #define GML_MOUSE_BUTTON_COUNT 5 +// Cursor constants +#define GML_CR_SIZE_ALL -22 +#define GML_CR_HANDPOINT -21 +#define GML_CR_APPSTART -19 +#define GML_CR_DRAG -12 +#define GML_CR_HOURGLASS -11 +#define GML_CR_UPARROW -10 +#define GML_CR_SIZE_WE -9 +#define GML_CR_SIZE_NWSE -8 +#define GML_CR_SIZE_NS -7 +#define GML_CR_SIZE_NESW -6 +#define GML_CR_BEAM -4 +#define GML_CR_CROSS -3 +#define GML_CR_ARROW -2 +#define GML_CR_NONE -1 +#define GML_CR_DEFAULT 0 + typedef struct RunnerMouseState { // Cursor cached in app-surface (FBO) pixel space double screenX, screenY; From b57295ff27f46696b4b4a484d4e32eb39671facb Mon Sep 17 00:00:00 2001 From: Eliandro <153942958+Eliandro4@users.noreply.github.com> Date: Sat, 13 Jun 2026 12:05:51 -0300 Subject: [PATCH 3/3] sdl3 platformsetcursor --- src/desktop/backends/sdl3.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/desktop/backends/sdl3.c b/src/desktop/backends/sdl3.c index fadca998..eea805e2 100644 --- a/src/desktop/backends/sdl3.c +++ b/src/desktop/backends/sdl3.c @@ -4,12 +4,14 @@ #include #include #include +#include #include "common.h" #include "input_recording.h" #include "desktop/platformdefs.h" #include "gettime.h" #include +#include "runner_mouse.h" static Runner *g_runner; static int32_t fbWidth, fbHeight; @@ -147,9 +149,40 @@ void platformExit(void) { SDL_Quit(); } +static void platformSetCursor(int32_t cursorType) { + if (cursorType == GML_CR_NONE) { + SDL_HideCursor(); + return; + } + SDL_ShowCursor(); + + SDL_SystemCursor sdlCursor; + switch (cursorType) { + case GML_CR_CROSS: sdlCursor = SDL_SYSTEM_CURSOR_CROSSHAIR; break; + case GML_CR_BEAM: sdlCursor = SDL_SYSTEM_CURSOR_TEXT; break; + case GML_CR_SIZE_NESW: sdlCursor = SDL_SYSTEM_CURSOR_NESW_RESIZE; break; + case GML_CR_SIZE_NS: sdlCursor = SDL_SYSTEM_CURSOR_NS_RESIZE; break; + case GML_CR_SIZE_NWSE: sdlCursor = SDL_SYSTEM_CURSOR_NWSE_RESIZE; break; + case GML_CR_SIZE_WE: sdlCursor = SDL_SYSTEM_CURSOR_EW_RESIZE; break; + case GML_CR_HOURGLASS: sdlCursor = SDL_SYSTEM_CURSOR_WAIT; break; + case GML_CR_DRAG: sdlCursor = SDL_SYSTEM_CURSOR_POINTER; break; + case GML_CR_APPSTART: sdlCursor = SDL_SYSTEM_CURSOR_PROGRESS; break; + case GML_CR_HANDPOINT: sdlCursor = SDL_SYSTEM_CURSOR_POINTER; break; + case GML_CR_SIZE_ALL: sdlCursor = SDL_SYSTEM_CURSOR_MOVE; break; + default: sdlCursor = SDL_SYSTEM_CURSOR_DEFAULT; break; + } + + SDL_Cursor* cursor = SDL_CreateSystemCursor(sdlCursor); + if (cursor) { + SDL_SetCursor(cursor); + } +} + void platformInitFunctions(Runner *runner) { g_runner = runner; runner->windowHasFocus = platformGetWindowFocus; + runner->setCursor = platformSetCursor; + runner->currentCursor = GML_CR_DEFAULT; } #ifdef ENABLE_SW_RENDERER