raysan5 / raygui

A simple and easy-to-use immediate-mode gui library
zlib License
3.26k stars 280 forks source link

`GuiButton()` not considering mouse state as exclusive mode #379

Open itsYakub opened 5 months ago

itsYakub commented 5 months ago

The basic behaviour of the GuiButton works as follow:

There is a problem with the last point though. It seems that the button only check if the mouse key is released on the button's body. What happen is that if we press the mouse button before we position it on the widget, then we move to the button, and at the end we release the mouse input, the button gets selected.

https://github.com/raysan5/raygui/assets/80039680/7ebcce52-0c45-4835-af9b-c92a3e36bc36

Worth mentioning is that the behaviour that prevents the inputing while the slider is held: if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) ...work fine.

https://github.com/raysan5/raygui/assets/80039680/6050116f-5ea5-48ad-90ba-8e90834e598d

Code from the example:

// gcc -g main.c -Lraylib/src -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -Iraylib/src -Iraygui/src

#include "raylib.h"

#define RAYGUI_IMPLEMENTATION
#include "raygui.h"

int main(int, char**) {
    InitWindow(600, 400, TextFormat("Raylib %s - Raygui %s - Raylib & Raygui Issue", RAYLIB_VERSION, RAYGUI_VERSION));

    SetTargetFPS(60);

    Rectangle label_rect = { 0, 0, 296, 48 };
    Rectangle button_rect = { 144, 176, 312, 56 };
    Rectangle slider_rect = { 144, 288, 312, 56 };

    float f = 0.0f;

    while(!WindowShouldClose()) {
        BeginDrawing();

        ClearBackground(RAYWHITE);

        GuiSetStyle(DEFAULT, TEXT_SIZE, 20);

        if(GuiButton(button_rect, "Click me!")) {
            TraceLog(LOG_INFO, "Button pressed!");
        }

        GuiSlider(slider_rect, NULL, NULL, &f, 0.0f, 1.0f);

        GuiLabel(label_rect, IsMouseButtonDown(MOUSE_BUTTON_LEFT) ? "Input state: PRESSED" : "Input state: RELEASED");

        GuiSetStyle(DEFAULT, TEXT_SIZE, DEFAULT);

        EndDrawing();
    }

    CloseWindow();

    return(0);
}

It can be quite problematic, for example: in my game I use state machine for the current state of the game. When we move further in it (or pause) the state is switched, and if the mouse was pressed at that moment and it was positioned when the button will be rendered, when we release the mouse the button gets selected by accident, causing some problems (resuming the game, quitting etc.)

The problem occurs in the latest raylib's and raygui's branch versions. Tested on the Linux platform. If needed, I can provide more info about the situation on Windows.

raysan5 commented 5 months ago

Two new globals have been added to raygui that could be used to address this kind of issues:

static bool guiControlExclusiveMode = false;    // Gui control exclusive mode (no inputs processed except current control)
static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier

This issue is probably also related to https://github.com/raysan5/raygui/issues/339

itsYakub commented 5 months ago

Yes, indeed they're related Didn't notice it at first I'll test it soon!