Работа с мышью в 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 шт):
да, все колбеки возвращают 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 описано почти такое же.