¿Cómo puedo reenviar la entrada de teclado de GLFW a otro objeto?

9

Tengo problemas para intentar ejecutar eventos de teclado en otra clase con GLFW3. El problema que tengo es que GLFW3 usa una función estática para la entrada como se muestra:

static UI u;
...
...
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    u.controls(window, key, action);
}

utambién es estático y los controles contienen la entrada para las claves WSAD (la única forma en que podría obtener eventos clave). Desde aquí, presionar una tecla funciona mostrando qué tecla se presiona en la ventana de la consola. El problema que estoy teniendo es tratar de usar la tecla presionada para manipular una variable en otra clase.

Tengo otra clase llamada MainMenu que tiene la función update().¿Hay alguna manera de usar mi clase de interfaz de usuario dentro de esta función?

ChocoMan
fuente

Respuestas:

16

Estás tomando el enfoque equivocado con una clase de IU estática. La forma habitual de "rebotar" desde una devolución de llamada estática a una función de instancia es almacenar algo capaz de hacer el salto en un lugar al que se pueda acceder desde la devolución de llamada estática.

La mayoría de las API, como GLFW y Win32 nativo, que requieren este tipo de devoluciones de llamada estáticas proporcionan una forma de hacer la asociación anterior. Las ventanas GLFW tienen un bloque de almacenamiento del tamaño de un puntero que puede asignar a: el puntero del usuario . Puede obtener o configurar este puntero de usuario según sea necesario.

Un patrón muy común es tener algún tipo de Gameclase que tenga métodos como "HandleKeyPress (Key key)" o cualquier otra cosa. Cuando inicia el programa, crea el Gameobjeto y realiza toda su inicialización GLFW, luego inserta el Gamepuntero en el almacenamiento de datos del usuario:

int main () {
  GLFWindow * window = ... create GLFW window ...
  Game game(... game constructor parameters ...);

  glfwSetWindowUserPointer(window, &game);

  ... main game loop ...
}

Luego, la devolución de llamada del teclado (y todas las demás devoluciones de llamada estáticas) pueden descomprimir el Game *almacenamiento del puntero del usuario y reenviarlo:

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
  Game * game = reinterpret_cast<Game *>(glfwGetWindowUserPointer(window);
  game->HandleKeyDown(...);
}

El HandleKeyDownmétodo en la Gameinstancia puede reenviarlo a su objeto de interfaz de usuario si es necesario (o, si realmente solo necesita la entrada del teclado para el objeto de interfaz de usuario, podría simplemente colocar un puntero a su objeto de interfaz de usuario en el almacenamiento del usuario, sin embargo, rellenar algo como el juego o algo de nivel superior generalmente es mejor ya que solo tiene un puntero por ventana para usar).


fuente
0

La forma en que evité eso por ahora fue usando un objeto singleton, cuando necesitaba acceder a la clase, podía recuperar el puntero al singleton:

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    InputManager * in_manager = InputManager::get_instance();
    in_manager->handle_key_press( params)
}

Algo así.

usuario1777995
fuente