spacebox/src/Delegate.hpp

115 lines
4.5 KiB
C++

/* ✨ +------------------------------------------------------+
____/ \____ ✨/| Open source game framework licensed to freely use, |
✨\ / / | copy, and modify. Created for 🌠dank.game🌠 |
+--\ . . /--+ | |
| ~/ ︶ \👍| | 🌐 https://open.shampoo.ooo/shampoo/spacebox |
| ~~~🌊~~~~🌊~ | +------------------------------------------------------+
| SPACE 🪐🅱 OX | /
| 🌊 ~ ~~~~ ~~ |/
+-------------*/
#pragma once
#include <string>
#include <map>
#include <list>
#include <functional>
#include <typeinfo>
#include <typeindex>
#include "SDL.h"
#include "Node.hpp"
namespace sb
{
struct Subscriber
{
std::function<void(SDL_Event&)> func;
Node* obj;
};
class Delegate : public Node
{
private:
std::map<std::uint32_t, std::vector<Subscriber>> subscribers;
bool cancelling_propagation = false;
public:
inline static std::uint32_t command_event_type = SDL_RegisterEvents(1);
Delegate(Node*);
void add_subscriber(Subscriber, std::uint32_t);
void dispatch();
static bool compare(SDL_Event&, const std::vector<std::string>&, bool = false, bool = false);
static bool compare(SDL_Event&, const std::string& = "", bool = false, bool = false);
static bool compare_cancel(SDL_Event&, const std::string& = "");
static bool compare_neutral(SDL_Event&, const std::string& = "");
void cancel_propagation();
static const std::string& event_command(SDL_Event&);
static bool event_cancel_state(SDL_Event&);
/*!
* Post a custom command to the queue. There is not currently support for passing custom data along with the command. The string
* and bool arguments will be copied onto the heap and deleted when the event is retrieved from the queue.
*
* @param command name of the custom command
* @param cancel whether or not the event is a cancellation
*/
static void post(const std::string& command, bool cancel = false);
/*!
* Subscribe a sb::Node or extention of sb::Node object's member function to receive a reference to an SDL_Event whenever
* an event of the specified type is triggered. The type can be an SDL event type from https://wiki.libsdl.org/SDL2/SDL_EventType,
* or if no type is specified, the type will be the custom user event used by this framework, sb::Delegate::command_event_type.
*
* The function submitted must accept a single argument of type SDL_Event&.
*
* sb::Delegate::command_event_type is an SDL_EventType used by this framework to automatically send framework and user created
* events that are mapped to keys in an sb::Configuration object's "keys" field. For example, by default `ALT+enter` is configured
* to send an event named `fullscreen`. Using a JSON file, `z` could be mapped to an event named `jump`.
*
* The subscribing object must be unsubscribed with Delegate::unsubscribe(const Type*) before it is destroyed, otherwise it will
* be null referenced.
*
* @param func a sb::Node or child of sb::Node object's member class function pointer
* @param obj a pointer to the object
* @param type the SDL_EventType to receive events for
*/
template<typename Type>
void subscribe(void(Type::*func)(SDL_Event&), Type* obj, std::uint32_t type = command_event_type)
{
add_subscriber({std::bind(func, obj, std::placeholders::_1), static_cast<Node*>(obj)}, type);
}
/*!
* Unsubscribe all subscribers in list associated with the submitted object.
*
* @param obj pointer to object to search for in subscriber list for removal
*/
template<typename Type>
void unsubscribe(const Type* obj)
{
for (auto type = subscribers.begin(); type != subscribers.end(); type++)
{
for (auto subscriber = type->second.begin(); subscriber != type->second.end();)
{
if (obj == subscriber->obj)
{
subscriber = type->second.erase(subscriber);
}
else
{
subscriber++;
}
}
}
}
};
}
#include "Input.hpp"
#include "Game.hpp"