Работа с мышью в glfw

Начал работать с C++ и библиотекой glfw и не знаю, как мне из функции, получающей положение мыши на экране данные перенести в функцию которая обрабатывает нажатие на кнопку мыши. То есть, если я кликаю, то я хочу знать, в какую часть экрана я кликнул

//window.cpp

GLFWwindow* Window::init()
{
    if(!glfwInit())
        exit(1);

    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
    glfwWindowHint(GLFW_DECORATED, false);
    GLFWwindow* window = glfwCreateWindow(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), "Program", NULL, NULL);

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    set_callbacks(window);
    set_icon(window);

    return window;
}

void Window::set_callbacks(GLFWwindow* window)
{
    Input_Processing input;
    glfwSetKeyCallback(window, input.Key_Callback);
    glfwSetCursorPosCallback(window, input.Cursor_Position_Callback);
    glfwSetMouseButtonCallback(window, input.Mouse_Button_Callback);
}

...
//input_processing.cpp

void Input_Processing::Cursor_Position_Callback(GLFWwindow* window, double xPos, double yPos)
{
    //Данные по положению мыши тут
}

void Input_Processing::Mouse_Button_Callback(GLFWwindow* window, int button, int action, int mods)
{
    //а нужны они мне тут
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
    {
        
    }
    if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
    {

    }
}

В гайде на сайте glfw все примеры функций для callback'ов типа void т.е. невозвращаемые


Ответы (1 шт):

Автор решения: KoVadim

да, все колбеки возвращают void, потому что их вызывает сама библиотека. Но даже если бы они что то и возвращали, воспользоваться этим было бы сложно. Проблема, которую Вы описываете, известна создателям библиотеки и они ее решили.

Если присмотреться к колбекам, то они все (или почти все?) получают первым параметром указатель на GLWFWindow. А у этого класса есть внутри переменная указатель (обычно называют такое user data - пользовательские данные), содержимое которой отдано полностью пользователю. Для доступа к этой переменной есть две функции glfwSetWindowUserPointer (установка) и glfwGetWindowUserPointer (получение).

Как этим воспользоваться. Заводите себе класс, который будет хранить всякую нужную информацию (что именно - Вам виднее). Пусть это будет class MyWordlData.

Теперь, после строки

GLFWwindow* window = glfwCreateWindow(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), "Program", NULL, NULL);

можно написать так

MyWorldData data;
glfwSetWindowUserPointer(window, &data);

Но так можно сделать, если этот код вызывается в main. Если такой код оставить в простой функции, то легко получить висящий указатель.

Но можно пойти простым путем - этот код вызывается внутри функции класса. А значит, мы можем передать туда this. B это в корне меняет дело.

glfwSetWindowUserPointer(window, this);

Ок, а что теперь с этим делать?

void Input_Processing::Cursor_Position_Callback(GLFWwindow* window, double xPos, double yPos)
{
    //Данные по положению мыши тут
    Window* w = static_cast<Window*>(glfwGetWindowUserPointer(window));
    assert(w != nullptr); // ну мало чего
    // все, теперь можно пользоваться w как указателем на Window*!!!
    w->MoveMyHeroe(xPos, yPos); // Ну или Ваша функция.
}

Если туда записывали указатель на другой класс - тогда делайте аккуратно каст в свое.

Вот здесь https://stackoverflow.com/questions/27596861/give-static-function-access-to-data-without-passing-the-data-as-a-parameter описано почти такое же.

→ Ссылка