You're taking the wrong approach with a static UI class. The usual way to "bounce" from a static callback to an instance function is to store something capable of making the jump in a place that is accessible from the static callback.
Most APIs, like GLFW and native Win32, that require these sorts of static callbacks provide a way to make the association above. GLFW windows have a pointer-sized block of storage that you can assign to: the user pointer. You can get or set this user pointer as needed.
A very common pattern is to have some kind of Game
class that has methods like "HandleKeyPress(Key key)" or whatnot. When you program starts, you create the Game
object and do all your GLFW initialization, then stuff the Game
pointer into the user data storage:
int main () {
GLFWindow * window = ... create GLFW window ...
Game game(... game constructor parameters ...);
glfwSetWindowUserPointer(window, &game);
... main game loop ...
}
Then, your keyboard callback (and all other static callbacks) can unpack the Game *
from user pointer storage and forward to it:
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
Game * game = reinterpret_cast<Game *>(glfwGetWindowUserPointer(window);
game->HandleKeyDown(...);
}
The HandleKeyDown
method on the Game
instance can forward along to your UI object if needed (or, if you really only need keyboard input for the UI object you could just stuff a pointer to your UI object in the user storage, however, stuffing something like the game or something higher-level is generally better since you only have one pointer per window to use).