繁体   English   中英

事件驱动的SDL2

[英]Event Driven SDL2

我正在将SDL包装到C ++对象中。 基本上,我只是厌倦了在我的代码中看到SDL_。 我至少想要名称空间...... SDL :: Window。 我做到了,它或多或少都好。

问题出现在事件中。 我希望它是事件驱动(回调)而不是我必须轮询事件队列。 (为了让SDL_Event符合我设计的抽象,你必须编写的传播例程很痛苦)。

举个例子,一个Window类。 它的构造函数调用

SDL_AddEventWatch(window_events, this);

其中window_events是Window类的静态成员。 它捕获任何类型的SDL_WINDOWEVENT。

int Window::window_events(void* data, SDL::Events::Event* ev)
{
    if (ev->type == SDL::Events::Window::Any)
    {
        auto win = static_cast<Window *>(data);
        if (ev->window.windowID == SDL_GetWindowID(win->mWindow))
        {
            std::vector<event_callback> callbacks = win->mWindowCallbacks;
            for (const auto cbk : callbacks)
            {
                cbk(*ev);
            }
        }
    }
    return 0;
}

My Window类还包含hook和unhook方法。 每个都采用std :: function。 这就是mWindowCallbacks的集合。 任何对事件感兴趣的外部例程都会将一个副本转发给它。

//...
using event_callback = std::function<void(SDL::Events::Event)>;
//...

template<typename T> bool 
find_func(const T & object, 
    const std::vector<T> & list,
    int * location=nullptr)
{
    int offset = 0;

    for (auto single : list)
    {
        if (single.target<T>() ==
            object.target<T>())
        {
            if (location != nullptr) *location = offset;
            return true;
        }
        offset++;
    }
    return false;
}

void
Window::hook(event_callback cbk)
{
    if (!find_func(cbk, mWindowCallbacks))
    {
        mWindowCallbacks.push_back(cbk);
    }
}

void
Window::unhook(event_callback cbk)
{
    int offset = 0;
    if (find_func(cbk, mWindowCallbacks, &offset))
    {
        mWindowCallbacks.erase(mWindowCallbacks.begin() + offset);
    }
}

用法:

///...
void cbk_close(SDL::Events::Event e)
{
    if (e.window.event == SDL::Events::Window::Close)
    {
        window.close();
        quit = true;
    }
}
///...
std::function<void(SDL::Events::Event)> handler = cbk_close;
SDL::Window window;
window.hook(handler);

关:

void Window::close()
{   
    SDL_DelEventWatch(window_events, this);
    SDL_DestroyWindow(mWindow);
    mWindowCallbacks.clear();       
}

对我来说,这看起来并不像是糟糕的设计。 一旦你按下窗口上的关闭,调用cbk_close,它调用close,它设置退出标志......然后它返回到window_events循环。 正如所料......但是,该功能似乎并未将控制权返回给程序。

这是我需要帮助的。 我真的不明白为什么。 我认为它劫持主线程,因为如果你有一个窗口,程序将退出该函数退出,或者如果你有两个窗口则崩溃...

我是否与之合适? 我已经坚持了一个星期。 它真的很令人气愤。 对任何愿意玩弄它的人; 这是完整代码的git repo。
Windows,Visual Studio 2015 / VC解决方案。 https://bitbucket.org/andywm/sdl_oowrapper/

好吧,所以我想我现在或多或少地了解这里发生了什么。

SDL_AddEventWatch(void (*)(void *, SDL_Event*), void *) 

如果您使用的是C ++,则应设置调用约定。

SDLCALL

就我而言;

int SDLCALL
Window::window_events(void* data, SDL::Events::Event* ev)

这似乎阻止了sdl事件系统抓住主线程。

至于为什么它会崩溃多个窗口...好吧,如果我删除这一行

SDL_DelEventWatch(window_events, this);

它不会崩溃...还不确定为什么,但如果我弄明白我会修改我的答案 - 如果有更多SDL经验的人可以填补我...这太棒了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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