mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-01 09:10:18 -06:00
Add the ability to list, enable, and disable events based on a numerical identifier (closes #1992)
This commit is contained in:
@@ -56,7 +56,7 @@ struct Event {
|
||||
// return a dictionary with these parameters. This dictionary is passed to actions
|
||||
// if they are triggered by events
|
||||
// 6. Add the new enum entry into the `toString` and `fromString` methods
|
||||
enum class Type {
|
||||
enum class Type : uint8_t {
|
||||
SceneGraphNodeAdded,
|
||||
SceneGraphNodeRemoved,
|
||||
ParallelConnection,
|
||||
|
||||
@@ -36,6 +36,14 @@ namespace events { struct Event; }
|
||||
|
||||
class EventEngine {
|
||||
public:
|
||||
struct ActionInfo {
|
||||
events::Event::Type type;
|
||||
uint32_t id = std::numeric_limits<uint32_t>::max();
|
||||
bool isEnabled = true;
|
||||
std::string action;
|
||||
std::optional<ghoul::Dictionary> filter;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns the first event stored in the EventEngine, or \c nullptr if
|
||||
* no event exists. To navigate the full list of events, you can access the returned
|
||||
@@ -90,6 +98,36 @@ public:
|
||||
const std::string& identifier,
|
||||
std::optional<ghoul::Dictionary> filter = std::nullopt);
|
||||
|
||||
/**
|
||||
* Removing registration for a specific event identified by the \p identifier.
|
||||
*
|
||||
* \param identifier The unique identifier of the event that should be removed.
|
||||
*/
|
||||
void unregisterEventAction(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* Returns the list of all registered actions, sorted by their identifiers.
|
||||
*
|
||||
* \return The list of all registered actions
|
||||
*/
|
||||
std::vector<ActionInfo> registeredActions() const;
|
||||
|
||||
/**
|
||||
* Enables the event identified by the \p identifier. If the event is already enabled,
|
||||
* this function does nothing.
|
||||
*
|
||||
* \param identifier The identifier of the event that should be enabled
|
||||
*/
|
||||
void enableEvent(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* Disables the event identified by the \p identifier. If the event is already
|
||||
* disabled, this function does nothing.
|
||||
*
|
||||
* \param identifier The identifier of the event that should be disabled
|
||||
*/
|
||||
void disableEvent(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* Triggers all actions that are registered for events that are in the current event
|
||||
* queue
|
||||
@@ -106,12 +144,14 @@ private:
|
||||
/// The last event in the chain of events stored in the memory pool
|
||||
events::Event* _lastEvent = nullptr;
|
||||
|
||||
struct ActionInfo {
|
||||
std::string action;
|
||||
std::optional<ghoul::Dictionary> filter;
|
||||
};
|
||||
|
||||
// The type is duplicated in the ActionInfo as well, but we want it in the ActionInfo
|
||||
// to be able to return them to a caller and we want it in this unordered_map to make
|
||||
// the lookup really fast. So having this extra wasted memory is probably worth it
|
||||
std::unordered_map<events::Event::Type, std::vector<ActionInfo>> _eventActions;
|
||||
|
||||
static uint32_t nextRegisteredEventId;
|
||||
|
||||
#ifdef _DEBUG
|
||||
/// Stores the total number of events during this frame for debugging purposes
|
||||
static uint64_t nEvents;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
uint32_t EventEngine::nextRegisteredEventId = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
uint64_t EventEngine::nEvents = 0;
|
||||
#endif // _DEBUG
|
||||
@@ -53,6 +55,9 @@ void EventEngine::registerEventAction(events::Event::Type type,
|
||||
std::optional<ghoul::Dictionary> filter)
|
||||
{
|
||||
ActionInfo ai;
|
||||
ai.id = nextRegisteredEventId;
|
||||
ai.isEnabled = true;
|
||||
ai.type = type;
|
||||
ai.action = std::move(identifier);
|
||||
ai.filter = std::move(filter);
|
||||
const auto it = _eventActions.find(type);
|
||||
@@ -62,6 +67,8 @@ void EventEngine::registerEventAction(events::Event::Type type,
|
||||
else {
|
||||
_eventActions[type] = { std::move(ai) };
|
||||
}
|
||||
|
||||
nextRegisteredEventId++;
|
||||
}
|
||||
|
||||
void EventEngine::unregisterEventAction(events::Event::Type type,
|
||||
@@ -84,6 +91,62 @@ void EventEngine::unregisterEventAction(events::Event::Type type,
|
||||
}
|
||||
}
|
||||
|
||||
void EventEngine::unregisterEventAction(uint32_t identifier) {
|
||||
for (auto it = _eventActions.begin(); it != _eventActions.end(); it++) {
|
||||
for (auto jt = it->second.begin(); jt != it->second.end(); jt++) {
|
||||
if (jt->id == identifier) {
|
||||
it->second.erase(jt);
|
||||
|
||||
// This might have been the last action so we might need to remove the
|
||||
// entry alltogether
|
||||
if (it->second.empty()) {
|
||||
_eventActions.erase(it);
|
||||
}
|
||||
|
||||
// The identifier is unique so we can stop after this
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get this far, we haven't found the identifier
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Could not find event with identifier {}", identifier
|
||||
));
|
||||
}
|
||||
|
||||
std::vector<EventEngine::ActionInfo> EventEngine::registeredActions() const {
|
||||
std::vector<EventEngine::ActionInfo> result;
|
||||
result.reserve(_eventActions.size());
|
||||
for (const std::pair<const events::Event::Type, std::vector<ActionInfo>>& p : _eventActions)
|
||||
{
|
||||
result.insert(result.end(), p.second.begin(), p.second.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void EventEngine::enableEvent(uint32_t identifier) {
|
||||
for (std::pair<const events::Event::Type, std::vector<ActionInfo>>& p : _eventActions) {
|
||||
for (ActionInfo& ai : p.second) {
|
||||
if (ai.id == identifier) {
|
||||
ai.isEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventEngine::disableEvent(uint32_t identifier) {
|
||||
for (std::pair<const events::Event::Type, std::vector<ActionInfo>>& p : _eventActions) {
|
||||
for (ActionInfo& ai : p.second) {
|
||||
if (ai.id == identifier) {
|
||||
ai.isEnabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventEngine::triggerActions() const {
|
||||
if (_eventActions.empty()) {
|
||||
// Nothing to do here
|
||||
@@ -96,7 +159,9 @@ void EventEngine::triggerActions() const {
|
||||
if (it != _eventActions.end()) {
|
||||
ghoul::Dictionary params = toParameter(*e);
|
||||
for (const ActionInfo& ai : it->second) {
|
||||
if (!ai.filter.has_value() || params.isSubset(*ai.filter)) {
|
||||
if (ai.isEnabled &&
|
||||
(!ai.filter.has_value() || params.isSubset(*ai.filter)))
|
||||
{
|
||||
global::actionManager->triggerAction(ai.action, params);
|
||||
}
|
||||
}
|
||||
@@ -111,7 +176,10 @@ scripting::LuaLibrary EventEngine::luaLibrary() {
|
||||
"event",
|
||||
{
|
||||
codegen::lua::RegisterEventAction,
|
||||
codegen::lua::UnregisterEventAction
|
||||
codegen::lua::UnregisterEventAction,
|
||||
codegen::lua::RegisteredEvents,
|
||||
codegen::lua::EnableEvent,
|
||||
codegen::lua::DisableEvent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,6 +48,46 @@ namespace {
|
||||
global::eventEngine->unregisterEventAction(type, action, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of registered events.
|
||||
*/
|
||||
[[codegen::luawrap]] std::vector<ghoul::Dictionary> registeredEvents() {
|
||||
using namespace openspace;
|
||||
|
||||
std::vector<EventEngine::ActionInfo> actions =
|
||||
global::eventEngine->registeredActions();
|
||||
|
||||
std::vector<ghoul::Dictionary> result;
|
||||
result.reserve(actions.size());
|
||||
for (const EventEngine::ActionInfo& ai : actions) {
|
||||
ghoul::Dictionary d;
|
||||
d.setValue("Identifier", static_cast<int>(ai.id));
|
||||
d.setValue("Type", std::string(events::toString(ai.type)));
|
||||
d.setValue("Enabled", ai.isEnabled);
|
||||
d.setValue("Action", ai.action);
|
||||
if (ai.filter.has_value()) {
|
||||
d.setValue("Filter", *ai.filter);
|
||||
}
|
||||
result.push_back(d);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the event with the provided identifier.
|
||||
*/
|
||||
[[codegen::luawrap]] void enableEvent(int identifier) {
|
||||
openspace::global::eventEngine->enableEvent(static_cast<uint32_t>(identifier));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the event with the provided identifier.
|
||||
*/
|
||||
[[codegen::luawrap]] void disableEvent(int identifier) {
|
||||
openspace::global::eventEngine->disableEvent(static_cast<uint32_t>(identifier));
|
||||
}
|
||||
|
||||
#include "eventengine_lua_codegen.cpp"
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user