I have written a simple window event capture wrapper that gets events that happen to the window, and can be checked anywhere in the program through a global class. I wanted to be able to create a callback anywhere in the program with any event that I have asked to be checked. To hold the data that is returned from the events, I have used a pointer that is allocated whenever an event occurs, so I can grab the data returned later on in the program.
I don't want to use templates to hold the data since that would require a lot of objects to be created, or a lot of vectors for each specific event that I want. I find this to be too clunky, and I wanted a clean, simple solution.
Data that is captured
struct windowEventData
{
void *data = nullptr;
std::string id;
sf::Event::EventType event;
bool polled = false;
};
Window Event Manager
class windowEventManager
{
private:
std::vector<windowEventData> _subscribedEvents;
public:
void subscribe(const std::string &id, sf::Event::EventType event);
void pollEvent(sf::Event event);
void clearEvents();
template<typename T>
T* hasEventPolled(const std::string &id);
~windowEventManager();
};
Grabbing and setting the pointer
void windowEventManager::pollEvent(sf::Event event)
{
for (auto &eventCheck : _subscribedEvents)
{
if (eventCheck.event == event.type)
{
switch (event.type)
{
case sf::Event::KeyPressed:
case sf::Event::KeyReleased:
eventCheck.data = new sf::Event::KeyEvent(event.key);
break;
case sf::Event::MouseButtonPressed:
case sf::Event::MouseButtonReleased:
eventCheck.data = new sf::Mouse::Button(event.mouseButton.button);
break;
case sf::Event::MouseWheelMoved:
case sf::Event::MouseWheelScrolled:
eventCheck.data = new bool(true);
break;
case sf::Event::TextEntered:
eventCheck.data = new sf::String(event.text.unicode);
break;
default:
break;
}
eventCheck.polled = true;
}
}
}
I clear events before each poll, and in the destructor so I don't have memory leaks/too much on the heap
void windowEventManager::clearEvents()
{
for (auto &eventCheck : _subscribedEvents)
{
if (eventCheck.data)
{
delete eventCheck.data;
eventCheck.data = nullptr;
}
eventCheck.polled = false;
}
}
Finding out if an event has occured
template<typename T>
inline T *windowEventManager::hasEventPolled(const std::string &id)
{
auto it = std::find_if(_subscribedEvents.begin(), _subscribedEvents.end(), [id] (windowEventData &dat) { return dat.id == id && dat.polled; });
if (it != _subscribedEvents.end())
{
return static_cast<T*>((*it).data);
}
return nullptr;
}
Is my use of a void*
proper? I figured I could use a union as well for this, but I would rather see if using a pointer would be a good solution.
windowEventManager
, in particular what is the type of_subscribedEvents
? In case it'sstd::vector<windowEventData>
, I think you'll find thatdelete eventCheck.data;
doesn't even compile, does it? – Quuxplusone Oct 18 '16 at 5:21