c++mathwindowsld

How deep is mouse in Rectangle C++ & SDL2 (Position flickers between two positions)


I am creating a program, and I have a rectangle. Basically, I am creating a custom window inside the SDL2 window, which is a Rect, with another Rect being its toolbar. I am struggling for hours trying to figure how to detect how deep is the mouse within the Rect, but I am failing every time. The most obvious equation for me was int deep = mousePos.x - x, but it flickers between two positions every time I move my mouse. I then have tried a LOT of other calculations, but none of them worked. Either they flickered between two positions with descending values, or they were completely static and didn't move, or always moved a lot in a specific direction. I have visually represented the calculations, which were mostly correct, but the flickering between two positions is always ruining it. Thanks for any help. I am providing source code, too.

SOURCE:

//
//  main.cpp
//  Open
//
//  Created by Fildom on 28.12.2021.
//

// Library includes
#include <SDL2/SDL.h>
#include <stdio.h>

bool isdown = false;

// Screen rendering helper
void on_render(SDL_Window* window, SDL_Renderer* renderer);

// Concatenation (probably not spelt correctly but idrc) for easier use
const char * concat(const char * one, const char * two) {
    char * buffer = new char[strlen(one) + strlen(two) + 1];
    strcpy(buffer, one);
    strcat(buffer, two);
    return buffer;
}

// Main method, required for performing application run
int main(int argc, const char * argv[]) {
    SDL_Renderer    *renderer = NULL;   // Initialize the renderer
    SDL_Event       event = { 0 };      // Create a null event
    SDL_Window      *win = NULL;        // Initialize a window
    int             exit = 0;           // If exit is 1, win closes
    
    // Window pre-modifiers
    const char * appName = "test";

    // SDL VIDEO mode initialization and error check
    if(SDL_Init(SDL_INIT_VIDEO) == -1) {
        printf("SDL_Init() failed with \"%s.\"", SDL_GetError());
        return 1;
    }
    
    // Create the window and load it into a previously defined variable
    win = SDL_CreateWindow(concat(appName, " - Initialization in progress"), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
    
    // Window creation was unsuccessfull
    if(!win) {
        printf("SDL_CreateWindow() failed with \"%s.\"", SDL_GetError());
        return -1;
    }

    // Creating renderer
    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
    
    // If renderer failed to load...
    if(!renderer) {
        printf("SDL_CreateRenderer() failed with \"%s.\"", SDL_GetError());
        return -1;
    }
    // Everything has gone OK, thus the window can be renamed
    SDL_SetWindowTitle(win, appName);

    // Game loop, as said previously, false = 0, true = 1.
    // while !exit                |
    // while not exit            <- |
    // while exit is 0 (false)     <-
    while (!exit) {
        // Event loop
        if (SDL_WaitEvent(&event)) {
            // Event types
            switch(event.type) {
            case SDL_QUIT:
                exit = 1; // Exit = 1, thus app is being exitted
                break;
            case SDL_KEYDOWN:
                if(event.key.keysym.sym == SDLK_ESCAPE) exit = 1; // If ESC is pressed
                break;
            case SDL_MOUSEBUTTONUP:
                isdown = false;
                break;
            case SDL_MOUSEBUTTONDOWN:
                isdown = true;
                break;
            case SDL_MOUSEMOTION:
                break;
            case SDL_WINDOWEVENT:
                switch(event.window.event) {
                case SDL_WINDOWEVENT_CLOSE: // macOS and/or other OSes rely on right click + Quit to fully exit out of an application. This makes it easier by just hitting the close button.
                    exit = 1;
                    break;
                }
                break;
            default: break;
            }
        }
        // Render the screen
        on_render(win, renderer);

        // Swap buffers to display
        SDL_RenderPresent(renderer);
    }

    // Cleanup
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);
    SDL_Quit();

    return 0;
}

class Window {
public:
    int x, y, w, h;
    SDL_Color winc, wintc;
    bool draggable;
    int titleh;
    Window(int wx, int wy, int ww, int wh, SDL_Color window_color = {255, 255, 255, 255}, SDL_Color window_title_color = {200, 200, 200, 255}) {
        x = wx;
        y = wy;
        w = ww;
        h = wh;
        winc = window_color;
        wintc = window_title_color;
        draggable = true;
        titleh = 50;
    }
    int tx, ty = 0;
    void Render(SDL_Renderer* renderer) {
        SDL_Rect _t;
        _t.x = x;
        _t.y = y;
        _t.w = w;
        _t.h = h;
        SDL_Rect title;
        title.x = x;
        title.y = y;
        title.w = w;
        title.h = titleh;
        SDL_SetRenderDrawColor(renderer, winc.r, winc.g, winc.b, winc.a);
        SDL_RenderFillRect(renderer, &_t);
        SDL_SetRenderDrawColor(renderer, wintc.r, wintc.g, wintc.b, wintc.a);
        SDL_RenderFillRect(renderer, &title);
        int mx, my;
        SDL_PumpEvents();
        SDL_GetMouseState(&mx, &my);
        SDL_Point ms;
        ms.x = mx;
        ms.y = my;
        if (SDL_PointInRect(&ms, &title) and isdown) {
            x = mx - tx;
            y = my - ty;
            tx = x;
            ty = y;
        }
    }
};

Window test1 = Window(200, 100, 300, 200);

void on_render(SDL_Window* window, SDL_Renderer* renderer) {
    SDL_Rect wind = { 0 };
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    SDL_GetWindowSize(window, &wind.w, &wind.h);
    test1.Render(renderer);
}


Solution

  • I ended up doing it in a different way. Instead of using mousePosition.x and y, I used relative X and Y which worked out perfectly.

    code for that is

    mousePosition.relX and mousePosition.relY;