You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.5 KiB

#pragma once
#include <SFML/Graphics.hpp>
class SfEventPublisher;
class SfEventSubscriber {
public:
virtual ~SfEventSubscriber() {};
virtual void update(SfEventPublisher* p, sf::Event e) = 0;
};
class SfEventPublisher {
public:
// Allows the subscription to classes of events
enum Event_Class {
JoystickButtonEvent,
JoystickConnectEvent,
JoystickMoveEvent,
KeyEvent,
MouseButtonEvent,
MouseMoveEvent,
MouseWheelEvent,
MouseWheelScrollEvent,
SensorEvent,
SizeEvent,
TextEvent,
TouchEvent,
WindowEvent
};
virtual ~SfEventPublisher() {};
virtual void subscribe(SfEventSubscriber *s, Event_Class c) {
subscribers[c].push_back(s);
};
virtual void unsubscribe(SfEventSubscriber *s, Event_Class c) {
std::remove(subscribers[c].begin(), subscribers[c].end(), s);
};
virtual void notify(sf::Event e) {
// I don't quite like that some event classes contained multiple types of events:
// KeyPressed, and KeyReleased under KeyEvent for example.
// While others are not represented by classes:
// Closed, LostFocus, and GainedFocus have no representing class.
// So, we'll add another "class", WindowEvent which contains those previously mentioned,
// and use those new identifiers to group our events
// This will also make it a bit easier when subscribing to certain events
Event_Class event_class;
if (e.type == sf::Event::Closed ||
e.type == sf::Event::LostFocus ||
e.type == sf::Event::GainedFocus ){
event_class = Event_Class::WindowEvent;
}
// Preserve a little of sfml's default behavior and separate resized event
else if (e.type == sf::Event::Resized) {
event_class = Event_Class::SizeEvent;
}
else if (e.type == sf::Event::TextEntered) {
event_class = Event_Class::TextEvent;
}
else if (e.type == sf::Event::KeyPressed ||
e.type == sf::Event::KeyReleased ){
event_class = Event_Class::KeyEvent;
}
else if (e.type == sf::Event::MouseWheelMoved ||
e.type == sf::Event::MouseWheelScrolled ){
event_class = Event_Class::MouseWheelScrollEvent;
}
else if (e.type == sf::Event::MouseButtonPressed ||
e.type == sf::Event::MouseButtonReleased ){
event_class = Event_Class::MouseButtonEvent;
}
// Is this a good idea, mixing events that contain data, and don't contain data?
else if (e.type == sf::Event::MouseMoved ||
e.type == sf::Event::MouseEntered ||
e.type == sf::Event::MouseLeft ){
event_class = Event_Class::MouseMoveEvent;
}
else if (e.type == sf::Event::JoystickButtonPressed ||
e.type == sf::Event::JoystickButtonReleased ){
event_class = Event_Class::JoystickButtonEvent;
}
else if (e.type == sf::Event::JoystickMoved) {
event_class = Event_Class::JoystickMoveEvent;
}
else if (e.type == sf::Event::JoystickConnected ||
e.type == sf::Event::JoystickDisconnected ){
event_class = Event_Class::JoystickConnectEvent;
}
else if (e.type == sf::Event::TouchBegan ||
e.type == sf::Event::TouchEnded ||
e.type == sf::Event::TouchMoved ){
event_class = Event_Class::TouchEvent;
}
else if (e.type == sf::Event::SensorChanged) {
event_class = Event_Class::SensorEvent;
}
else {
std::cout << "Unable to classify sf::Event into Event_Class";
abort();
}
// get the bucket containing subscribers to that Event_Class
std::vector<SfEventSubscriber*> *event_type_bucket = &subscribers[event_class];
// Send them the event
for (auto s : *event_type_bucket) {
s->update(this, e);
}
};
private:
std::map<Event_Class, std::vector<SfEventSubscriber*>> subscribers;
};