Jambo
Jambo

Reputation: 101

Prevent mouse event from being fired multiple times in nuklear

I have a basic test window in a renderer I'm working on in C using nuklear and SDL2:

void renderUI(){
    static struct nk_colorf color = {1.0f, 0.0f, 0.0f, 1.0f};
    
    if (nk_begin(ctx, "Debug Window", nk_rect(0, 0, 410, 500), NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_MINIMIZABLE)) {
        
        // Define row layout with two columns: label + value
        nk_layout_row_dynamic(ctx, 130, 2);
        // Display "Camera Position: "
        nk_label(ctx, "Camera Position:", NK_TEXT_LEFT);
        
        get_camera_position(&p);
        nk_labelf(ctx, NK_TEXT_LEFT, "(%.2f, %.2f, %.2f)", p[0], p[1], p[2]);

        nk_layout_row_dynamic(ctx, 130, 2);
        nk_label(ctx, "Light Colour:", NK_TEXT_LEFT);
        color = nk_color_picker(ctx, color, NK_RGBA); // RGB mode (or NK_RGBA for alpha)
        
        nk_layout_row_dynamic(ctx, 130, 2);
        nk_label(ctx,"Frame Rate: ",NK_TEXT_ALIGN_LEFT);
        nk_labelf(ctx, NK_TEXT_LEFT, "(%.2f)", fps);


        lightColor[0] = color.r;
        lightColor[1] = color.g;
        lightColor[2] = color.b;
    }
    nk_end(ctx);
}

As you can see I have the NK_WINDOW_MINIMIZABLE flag set so there is a minimize button on the top right hand corner of the window, my problem is when I press the mouse button, it causes many SDL_Events to fire, this causes the window to jitter constantly as it is minimized and maximized every frame.

void process_input(void) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        nk_sdl_handle_event(&event);
        
        switch (event.type) {
            case SDL_QUIT:
                is_running = false;
                break;
            case SDL_KEYDOWN:
                keyStates[event.key.keysym.scancode] = true;
                break;
            case SDL_KEYUP:
                keyStates[event.key.keysym.scancode] = false;
                break;
            case SDL_MOUSEBUTTONDOWN:
                if(event.button.button == SDL_BUTTON_RIGHT)mouse_button_down = true;
                break;
            case SDL_MOUSEBUTTONUP:
                if(event.button.button == SDL_BUTTON_RIGHT)mouse_button_down = false;
                break;
            case SDL_MOUSEMOTION:
                    if(mouse_button_down){
                        process_mouse_move((float)event.motion.xrel,(float)event.motion.yrel,1);
                    }
                break;
            case SDL_MOUSEWHEEL:
                fov -= (float) event.wheel.y;
                if (fov < 1.0f)
                    fov = 1.0f;
                if (fov > 45.0f)
                    fov = 45.0f;
        }
    }
}

As I'm creating the minimize button from a flag being set, I have no real control over the button, and I'm not sure how to handle this case as SDL will pass events to nuklear every frame. Ideally I just want it to register on click not on mouse press.

Upvotes: 0

Views: 23

Answers (1)

Jambo
Jambo

Reputation: 101

SDL_Event event;
    nk_input_begin(ctx);
    while (SDL_PollEvent(&event)) {
        nk_sdl_handle_event(&event);
        
        switch (event.type) {
            case SDL_QUIT:
                is_running = false;
                break;
            case SDL_KEYDOWN:
                keyStates[event.key.keysym.scancode] = true;
                break;
            case SDL_KEYUP:
                keyStates[event.key.keysym.scancode] = false;
                break;
            case SDL_MOUSEBUTTONDOWN:
                if(event.button.button == SDL_BUTTON_RIGHT)mouse_button_down = true;
                break;
            case SDL_MOUSEBUTTONUP:
                if(event.button.button == SDL_BUTTON_RIGHT)mouse_button_down = false;
                break;
            case SDL_MOUSEMOTION:
                    if(mouse_button_down){
                        process_mouse_move((float)event.motion.xrel,(float)event.motion.yrel,1);
                    }
                break;
            case SDL_MOUSEWHEEL:
                fov -= (float) event.wheel.y;
                if (fov < 1.0f)
                    fov = 1.0f;
                if (fov > 45.0f)
                    fov = 45.0f;
        }
    }
    nk_input_end(ctx);

Turns out my issue was the lack of nk_input_begin(ctx) and nk_input_end(ctx)

As stated from nuklears docs:

input state needs to be provided to nuklear by first calling nk_input_begin which resets internal state like delta mouse position and button transitions. After nk_input_begin all current input state needs to be provided. This includes mouse motion, button and key pressed and released, text input and scrolling. Both event- or state-based input handling are supported by this API and should work without problems. Finally after all input state has been mirrored nk_input_end needs to be called to finish input process.

I wasn't resetting my internal state each frame causing unintended behaviour!

Upvotes: 0

Related Questions