I'm in the process of wrapping SDL into C++ objects. Basically, I'm just tired of seeing SDL_ in my code. I'd like at least namespaces... SDL::Window. I've done that, its going more or less fine.
Issue arises with events. I'd like it to be event driven (callbacks) rather than me having to poll an events queue. (the propagation routines you have to write to get SDL_Event fit the abstraction I've designed is painful).
Take for example, a Window class. Its constructor calls
SDL_AddEventWatch(window_events, this);
where window_events is a static member of the Window class. It catches anything of type 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 class also contains hook and unhook methods. Each takes a std::function. This is what mWindowCallbacks is a collection of. Any external routine interested in an event gets a copy forwarded to it.
//...
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);
}
}
Usage:
///...
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);
Close:
void Window::close()
{
SDL_DelEventWatch(window_events, this);
SDL_DestroyWindow(mWindow);
mWindowCallbacks.clear();
}
To me, this doesn't seem like terrible design. Once you press close on the window the cbk_close is invoked, it calls close, it sets the quit flag... Then it returns to the window_events loop. As expected... However that function doesn't seem to return control to the program.
This is what I need help with. I don't really understand why. I think its hijacking the main thread, as the program will exit once that function exits if you have one window, or... crash if you have two.
Am I on the right lines with that? I've been stuck on this for a week. Its really rather infuriating. To anyone willing to have a play about with it; here's the git repo for the full code.
Windows, Visual Studio 2015/VC solution.
https://bitbucket.org/andywm/sdl_oowrapper/