简体   繁体   中英

glfw input callback to modify an object with a member function

As you know, glfw works with callbacks for inputs and callback functions have certain signatures that users need to match. Here is an example from the documentation:

void key_callback(GLFWwindow* window, int key, int scancode, int action, int 
mods)
{
    if (key == GLFW_KEY_E && action == GLFW_PRESS)
        activate_airship();
}

Now, activate airship seems to be a global function here. What I really want to do is, to modify some object, possibly, at each input stage. So I want something like:

void key_callback(Airship a, GLFWwindow* window, int key, int scancode, int 
                  action, int mods)
{
    if (key == GLFW_KEY_W && action == GLFW_PRESS)
        a.render_Wireframe();
}

As you can see, I want to pass the object I am trying to modify, Airship here. But this time, callback signature is distrupted. I can't use it anymore. What is the best way to achieve this? I am trying to come up with ideas but in the future, I might want to change this to work with not just airships but a new object I add as well. What should be the design here?

The thing is, with the ability to set one callback for whole program, I don't know how to achieve the following. Let's say I have two objects Airship and Battlesip . I want both of them to have their own input handling mechanism. Pressing W should do something if Airship is the picked object in the scene and something else if Battleship is the picked object.

So I want to have something like following in the end;

class Airship : public SceneObject
{
    ...
    void input_handle(){
        if(is_picked && pressed == GLFW_KEY_W)
            launch_missile();
    }
}

class Battleship : public SceneObject
{
    ...
    void input_handle(){
        if(is_picked && pressed == GLFW_KEY_W)
            do_something_else();
    }
}

And in my main loop, I have a vector of SceneObject and I call input_handle on each frame, for each object. I don't know how can I handle something like this with a single callback scheme of glfw. I can't pass those things as callback functions to a window even if I matched the signature because they are class members. Well nothing would change if I could pass class members, since I can only set one callback.

Here is how I ended up solving this issue in a simplified manner. I am not sure if this is the correct design but it might be of help to a future viewer. I have a scene graph like object, say SceneGraph that holds all the SceneObjects mentioned in the question. I ended up making this SceneGraph object a singleton. I have one scene graph per run so it seemed logical to me to make it a singleton.

class SceneGraph
{  
    // ...
    // many more code
    friend void key_callback(GLFWwindow* window, int key, int scancode,
                             int action, int mods)
    {
        // get the singleton instance, singleton is static and this is
        // a friend function, so I can register this as a callback 
        SceneGraph* d = SceneGraph::handle();
        d->input_handle();
    } 

    void input_handle()
    {
         for(auto& s : objs)
             s.input_handle()
    }
private:
    std::vector<SceneObject> objs;
}

Of course, you can pass button state etc. to your input routines. I just wanted show the bare minimum design that I went with. Object picking example that I talked about in the original question can also be handled now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM