Added state event.

This commit is contained in:
2023-02-27 12:46:02 -08:00
parent 3862a95332
commit 099d9a15c3
5 changed files with 88 additions and 18 deletions

View File

@ -5,5 +5,6 @@
#pragma once
#include "StateEvent.hpp"
#include "StateOwner.hpp"
#include "StateProperty.hpp"

View File

@ -0,0 +1,33 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "assert/assert.hpp"
namespace Dawn {
class StateOwner;
template<typename...A>
class StateEvent {
private:
std::vector<std::function<void(A...)>> listeners;
public:
/**
* Invokes the event and emits to all of the listeners.
*
* @param args Arguments for this event to pass to the listeners.
*/
void invoke(A... args) {
auto itListeners = this->listeners.begin();
while(itListeners != this->listeners.end()) {
(*itListeners)(args...);
++itListeners;
}
}
friend class StateOwner;
};
}

View File

@ -4,7 +4,7 @@
// https://opensource.org/licenses/MIT
#pragma once
#include "assert/assert.hpp"
#include "StateEvent.hpp"
namespace Dawn {
template<class V>
@ -12,15 +12,10 @@ namespace Dawn {
class StateOwner {
private:
std::map<void*, std::vector<std::function<void()>>> effects;
std::map<void*, std::vector<std::function<void()>>> effectListeners;
std::vector<std::function<void()>> stateUpdateListeners;
public:
/**
* Invoked event listener for the subclass that listens for all changes
* to any part of this state updated.
*/
virtual void onStateUpdate() = 0;
/**
* Creates a new state property and listens for its change.
*
@ -46,7 +41,32 @@ namespace Dawn {
*/
template<class V>
void useEffect(StateProperty<V> &property, const std::function<void()> &fn) {
this->effects[(void*)&property].push_back(fn);
assertFalse(property.owner == this);
this->effectListeners[(void*)&property].push_back(fn);
}
/**
* Listen for changes to any single state property managed by this state
* owner.
*
* @param fn Function to be invoked when any state property is updated.
*/
void useStateUpdated(const std::function<void()> &fn) {
this->stateUpdateListeners.push_back(fn);
}
/**
* Listen for when an event is invoked by a state event. This is intended
* to allow for cross-state-owner communication in a simple and effective
* way.
*
* @tparam A The arguments from the state event that are calledback.
* @param event The event that is being subscribed to.
* @param fn The function to be inokved on event trigger.
*/
template<typename...A>
void useEvent(StateEvent<A...> &event, const std::function<void(A...)> &fn) {
event.listeners.push_back(fn);
}
/**
@ -60,14 +80,19 @@ namespace Dawn {
*/
template<class V>
void _statePropertyUpdated(StateProperty<V> *prop, V n, V o) {
this->onStateUpdate();
auto eff = &this->effects[prop];
auto eff = &this->effectListeners[prop];
auto itEff = eff->begin();
while(itEff != eff->end()) {
(*itEff)();
++itEff;
}
auto itUpdate = this->stateUpdateListeners.begin();
while(itUpdate != this->stateUpdateListeners.end()) {
(*itUpdate)();
++itUpdate;
}
}
/**
@ -79,7 +104,11 @@ namespace Dawn {
*/
template<class V>
void _statePropertyDestroyed(StateProperty<V> *prop) {
this->effects.erase((void*)prop);
this->effectListeners.erase((void*)prop);
}
virtual ~StateOwner() {
}
};
}

View File

@ -4,15 +4,23 @@
// https://opensource.org/licenses/MIT
#pragma once
#include "StateOwner.hpp"
#include "assert/assert.hpp"
namespace Dawn {
class StateOwner;
template<class V>
class StateProperty {
private:
StateOwner *owner;
V value;
/**
* Method that is invoked every time that the value of this state property
* is updated.
*
* @param val Value that is to be used for this property.
*/
void setInternal(V val) {
if(val == this->value) return;// TODO: can I omit this? kinda bad tbh.
assertNotNull(this->owner);
@ -44,6 +52,9 @@ namespace Dawn {
return this->value;
}
/**
* Destructor for StateProperty.
*/
~StateProperty() {
this->owner->_statePropertyDestroyed(this);
}

View File

@ -42,10 +42,6 @@ namespace Dawn {
}
}
}
void onStateUpdate() override {
std::cout << "State Update Invoked" << std::endl;
}
std::vector<Asset*> getRequiredAssets() override {
auto assMan = &this->game->assetManager;