glfw 输入回调以使用成员函数修改对象

Posted

技术标签:

【中文标题】glfw 输入回调以使用成员函数修改对象【英文标题】:glfw input callback to modify an object with a member function 【发布时间】:2017-12-21 12:43:08 【问题描述】:

如您所知,glfw 与输入回调一起使用,并且回调函数具有用户需要匹配的某些签名。这是文档中的一个示例:

void key_callback(GLFWwindow* window, int key, int scancode, int action, int 
mods)

    if (key == GLFW_KEY_E && action == GLFW_PRESS)
        activate_airship();

现在,激活飞艇似乎是这里的全局功能。我真正想做的是,可能在每个输入阶段修改一些对象。所以我想要类似的东西:

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();

如您所见,我想在这里传递我要修改的对象Airship。但这一次,回调签名被打乱了。我不能再使用它了。实现这一目标的最佳方法是什么?我正在尝试提出一些想法,但在未来,我可能想改变它以不仅适用于飞艇,还适用于我添加的新对象。这里的设计应该是什么?

问题是,能够为整个程序设置一个回调,我不知道如何实现以下。假设我有两个对象AirshipBattlesip。我希望他们都有自己的输入处理机制。如果Airship 是场景中的拾取对象,按下W 应该会做一些事情,如果Battleship 是拾取的对象会做其他事情。

所以我想最后有类似的东西;

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();
    

在我的主循环中,我有一个SceneObject 的向量,我在每个帧上为每个对象调用input_handle。我不知道如何使用 glfw 的单个回调方案来处理这样的事情。即使我匹配了签名,我也无法将这些东西作为回调函数传递给窗口,因为它们是类成员。好吧,如果我可以传递类成员,什么都不会改变,因为我只能设置一个回调。

【问题讨论】:

【参考方案1】:

这是我最终以简化方式解决此问题的方法。我不确定这是否是正确的设计,但它可能对未来的观众有所帮助。我有一个类似对象的场景图,比如SceneGraph,它包含问题中提到的所有SceneObjects。我最终使这个SceneGraph 对象成为一个单例。每次运行我都有一个场景图,所以将其设为单例对我来说似乎是合乎逻辑的。

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;

当然,您可以将按钮状态等传递给您的输入例程。我只是想展示我所采用的最低限度的设计。我在原始问题中谈到的对象选择示例现在也可以处理。

【讨论】:

以上是关于glfw 输入回调以使用成员函数修改对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调

类内定义线程的回调函数问题

JavaScript:如何将多个参数传递给对象成员内的回调函数?

C++中类成员函数作为回调函数

是否可以制作仅具有函数成员属性的回调接口?

将成员函数用于 C 样式回调时固定委托