Added state event.
This commit is contained in:
@ -5,5 +5,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "StateEvent.hpp"
|
||||||
#include "StateOwner.hpp"
|
#include "StateOwner.hpp"
|
||||||
#include "StateProperty.hpp"
|
#include "StateProperty.hpp"
|
33
src/dawn/state/StateEvent.hpp
Normal file
33
src/dawn/state/StateEvent.hpp
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
// https://opensource.org/licenses/MIT
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "assert/assert.hpp"
|
#include "StateEvent.hpp"
|
||||||
|
|
||||||
namespace Dawn {
|
namespace Dawn {
|
||||||
template<class V>
|
template<class V>
|
||||||
@ -12,15 +12,10 @@ namespace Dawn {
|
|||||||
|
|
||||||
class StateOwner {
|
class StateOwner {
|
||||||
private:
|
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:
|
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.
|
* Creates a new state property and listens for its change.
|
||||||
*
|
*
|
||||||
@ -46,7 +41,32 @@ namespace Dawn {
|
|||||||
*/
|
*/
|
||||||
template<class V>
|
template<class V>
|
||||||
void useEffect(StateProperty<V> &property, const std::function<void()> &fn) {
|
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>
|
template<class V>
|
||||||
void _statePropertyUpdated(StateProperty<V> *prop, V n, V o) {
|
void _statePropertyUpdated(StateProperty<V> *prop, V n, V o) {
|
||||||
this->onStateUpdate();
|
auto eff = &this->effectListeners[prop];
|
||||||
|
|
||||||
auto eff = &this->effects[prop];
|
|
||||||
auto itEff = eff->begin();
|
auto itEff = eff->begin();
|
||||||
while(itEff != eff->end()) {
|
while(itEff != eff->end()) {
|
||||||
(*itEff)();
|
(*itEff)();
|
||||||
++itEff;
|
++itEff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto itUpdate = this->stateUpdateListeners.begin();
|
||||||
|
while(itUpdate != this->stateUpdateListeners.end()) {
|
||||||
|
(*itUpdate)();
|
||||||
|
++itUpdate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +104,11 @@ namespace Dawn {
|
|||||||
*/
|
*/
|
||||||
template<class V>
|
template<class V>
|
||||||
void _statePropertyDestroyed(StateProperty<V> *prop) {
|
void _statePropertyDestroyed(StateProperty<V> *prop) {
|
||||||
this->effects.erase((void*)prop);
|
this->effectListeners.erase((void*)prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~StateOwner() {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -4,15 +4,23 @@
|
|||||||
// https://opensource.org/licenses/MIT
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "StateOwner.hpp"
|
#include "assert/assert.hpp"
|
||||||
|
|
||||||
namespace Dawn {
|
namespace Dawn {
|
||||||
|
class StateOwner;
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
class StateProperty {
|
class StateProperty {
|
||||||
private:
|
private:
|
||||||
StateOwner *owner;
|
StateOwner *owner;
|
||||||
V value;
|
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) {
|
void setInternal(V val) {
|
||||||
if(val == this->value) return;// TODO: can I omit this? kinda bad tbh.
|
if(val == this->value) return;// TODO: can I omit this? kinda bad tbh.
|
||||||
assertNotNull(this->owner);
|
assertNotNull(this->owner);
|
||||||
@ -44,6 +52,9 @@ namespace Dawn {
|
|||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor for StateProperty.
|
||||||
|
*/
|
||||||
~StateProperty() {
|
~StateProperty() {
|
||||||
this->owner->_statePropertyDestroyed(this);
|
this->owner->_statePropertyDestroyed(this);
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,6 @@ namespace Dawn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStateUpdate() override {
|
|
||||||
std::cout << "State Update Invoked" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Asset*> getRequiredAssets() override {
|
std::vector<Asset*> getRequiredAssets() override {
|
||||||
auto assMan = &this->game->assetManager;
|
auto assMan = &this->game->assetManager;
|
||||||
|
Reference in New Issue
Block a user