spacebox/src/Delegate.hpp
Cocktail Frank bef0960109 Add support for storing and loading user preferences
A field is added to the configuration object for user preferences at
"storage" > "preferences file", corresponding to a
sb::progress::Progress object at sb::Game::preferences. If the file
exists, load and merge into the configuration at sb::Game construction
time. This allows the project to save user preferences using
sb::Game::preferences.

Update sb::Game constructor to merge CLI and constructor config
overrides into the configuration multiple times during the configuration
load phase to make sure the overrides apply to each configuration loaded
during the phase.

Add an overload to sb::progress::Progress::config for setting a single
field of the config section, using the same signature as
sb::progress::Progress::set.

Added a function to sb::Display for getting the fullscreen status of a
sb::Game object's window.
2024-11-01 19:09:55 -04:00

117 lines
4.5 KiB
C++

/* +=======================================================+
____/ \____ /: Open source game framework licensed to freely use, :
\ / / : copy, and modify - created for dank.game :
+==\ ^__^ /==+ : :
: ~/ \~ : : Download at https://open.shampoo.ooo/shampoo/spacebox :
: ~~~~~~~~~~~~ : +=======================================================+
: SPACE ~~~~~ : /
: ~~~~~~~ BOX :/
+=============*/
#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"