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

[core] SetMouseCursor() not working on PLATFORM_WEB #3368

Closed
danielchasehooper opened this issue Oct 2, 2023 · 7 comments · Fixed by #3414
Closed

[core] SetMouseCursor() not working on PLATFORM_WEB #3368

danielchasehooper opened this issue Oct 2, 2023 · 7 comments · Fixed by #3414
Labels
hacktoberfest Hacktoberfest recommended issues platform: Web Web platform

Comments

@danielchasehooper
Copy link

danielchasehooper commented Oct 2, 2023

Issue description

SetMouseCursor doesn't work on web

Environment

Web

@raysan5
Copy link
Owner

raysan5 commented Oct 2, 2023

You have void SetMouseCursor(int cursor); supporting the OS provided cursors:

// Mouse cursor
typedef enum {
    MOUSE_CURSOR_DEFAULT       = 0,     // Default pointer shape
    MOUSE_CURSOR_ARROW         = 1,     // Arrow shape
    MOUSE_CURSOR_IBEAM         = 2,     // Text writing cursor shape
    MOUSE_CURSOR_CROSSHAIR     = 3,     // Cross shape
    MOUSE_CURSOR_POINTING_HAND = 4,     // Pointing hand cursor
    MOUSE_CURSOR_RESIZE_EW     = 5,     // Horizontal resize/move arrow shape
    MOUSE_CURSOR_RESIZE_NS     = 6,     // Vertical resize/move arrow shape
    MOUSE_CURSOR_RESIZE_NWSE   = 7,     // Top-left to bottom-right diagonal resize/move arrow shape
    MOUSE_CURSOR_RESIZE_NESW   = 8,     // The top-right to bottom-left diagonal resize/move arrow shape
    MOUSE_CURSOR_RESIZE_ALL    = 9,     // The omnidirectional resize/move cursor shape
    MOUSE_CURSOR_NOT_ALLOWED   = 10     // The operation-not-allowed shape
} MouseCursor;

Afaik, it should work on macOS but not sure if it would work on Web, again, it depends on the library_glfw.js implementation.

@danielchasehooper
Copy link
Author

Just confirmed, it does not work on web. updating title

@danielchasehooper danielchasehooper changed the title Set Mouse Cursor Set Mouse Cursor on web Oct 3, 2023
@danielchasehooper
Copy link
Author

Side note, why is the parameter int cursor and not MouseCursor cursor?

@ghost
Copy link

ghost commented Oct 3, 2023

@danielchasehooper Probably because it's glfwCreateStandardCursor (L4177). glfwCreateCursor (reference) isn't implemented yet (coincidentally, that was also requested today #2952 (comment)) on the wishlist.

@raysan5 raysan5 added the platform: Web Web platform label Oct 3, 2023
@raysan5
Copy link
Owner

raysan5 commented Oct 3, 2023

Side note, why is the parameter int cursor and not MouseCursor cursor?

Actually it was a design decision, originally it confused my students when using enums as a data type when they are just int, also, most of those enums start being just defines, so, for simplicity I just kept the int for all enum types in raylib. It shouldn't be a problem.

@raysan5 raysan5 changed the title Set Mouse Cursor on web [core] SetMouseCursor() not working on PLATFORM_WEB Oct 3, 2023
@raysan5 raysan5 added the hacktoberfest Hacktoberfest recommended issues label Oct 3, 2023
@BeardedBread
Copy link
Contributor

I've implemented a SetMouseCursor function for PLATFORM_WEB. It simply sets the cursor element in CSS using EM_ASM. CSS cursor reference: link.
Idea adapted from: link

Would this be sufficient?

#include "raylib.h"
#include <stdio.h>


//-------------------- PROTOTYPE CURSOR FUNCTION ------------------
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>

void WebSetMouseCursor(MouseCursor cursor)
{
    const char *cursorName;
    switch (cursor)
    {
        case MOUSE_CURSOR_IBEAM: cursorName = "text"; break;
        case MOUSE_CURSOR_CROSSHAIR: cursorName = "crosshair"; break;
        case MOUSE_CURSOR_POINTING_HAND: cursorName = "pointer"; break;
        case MOUSE_CURSOR_RESIZE_EW: cursorName = "ew-resize"; break;
        case MOUSE_CURSOR_RESIZE_NS: cursorName = "ns-resize"; break;
        case MOUSE_CURSOR_RESIZE_NWSE: cursorName = "nwse-resize"; break;
        case MOUSE_CURSOR_RESIZE_NESW: cursorName = "nesw-resize"; break;
        case MOUSE_CURSOR_RESIZE_ALL: cursorName = "move"; break;
        case MOUSE_CURSOR_NOT_ALLOWED: cursorName = "not-allowed"; break;

        case MOUSE_CURSOR_ARROW: // can't find a name specifically for arrow cursor
        case MOUSE_CURSOR_DEFAULT:
        {
            cursorName = "default";
        } break;

        default:
        {
            // Just in case
            cursorName = "default";
        } break;
    }

    // Set the cursor element on the CSS
    EM_ASM({document.body.style.cursor = UTF8ToString($0);}, cursorName); // Apparently UTF8ToString is needed

}
#endif

#if defined(PLATFORM_WEB)
#define SetCursorFunc WebSetMouseCursor
#else
#define SetCursorFunc SetMouseCursor
#endif
//-------------------------------------------------------------------

// Window size
static const int width = 800;
static const int height = 600;

// Grid sizes
const float grid_width = 200.0f;
const float grid_height = 200.0f;
const int grid_w = 4;
// Display name for cursor
static const char* CURSOR_NAMES[11] = 
{
    "default", "arrow", "text", "crosshair",
    "pointer", "ew-resize", "ns-resize", "nwse-resize",
    "nesw-resize", "move", "not-allowed"
};

void update_step(void)
{
    // Set the cursor based on mouse position in the grid
    Vector2 mouse_pos = GetMousePosition();
    int mouse_idx = (int)(mouse_pos.x / grid_width) + (int)(mouse_pos.y / grid_height) * grid_w;
    mouse_idx = (mouse_idx < 0)  ? 0: mouse_idx;
    mouse_idx = (mouse_idx > 10) ? 10: mouse_idx;
    MouseCursor cursor = (MouseCursor)mouse_idx;
    SetCursorFunc(cursor);

    static char buffer[64];
    snprintf(buffer, 64, "x: %.2f, y: %.2f, idx: %d", mouse_pos.x, mouse_pos.y, mouse_idx);
    buffer[63] = '\0';

    BeginDrawing();
        ClearBackground(LIGHTGRAY);
        for (int i = 0; i < grid_width; ++i)
        {
            DrawLine(grid_width*i, 0, grid_width*i, height, BLACK);
        }
        for (int i = 0; i < grid_height; ++i)
        {
            DrawLine(0, grid_height*i, width, grid_height*i, BLACK);
        }
        for (int i = 0; i < 11; i++)
        {
            int x = (i % grid_w) * grid_width + grid_width / 2;
            int y = (i / grid_w) * grid_height + grid_height / 2;
            DrawText(CURSOR_NAMES[i], x, y, 12, BLACK);
        }
        DrawText(buffer, 20, 20, 12, BLACK);
    EndDrawing();
}

int main(void)
{
    InitWindow(width, height, "raylib");
    SetTargetFPS(60);

    #if defined(PLATFORM_WEB)
        puts("Setting emscripten main loop");
        emscripten_set_main_loop(update_step, 0, 1);
    #else
        puts("Regular main loop");
        while(true)
        {
            update_step();
            if (WindowShouldClose()) break;
        }
    #endif
    CloseWindow();

}

@raysan5
Copy link
Owner

raysan5 commented Oct 14, 2023

@BeardedBread It seems a good-enough solution to me, you can send a PR to be added to rcore_web.c module SetMouseCursor().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hacktoberfest Hacktoberfest recommended issues platform: Web Web platform
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants