More work on State System

This commit is contained in:
2023-03-01 08:03:03 -08:00
parent dfcc14f2a7
commit c658fdd08f
6 changed files with 167 additions and 48 deletions

View File

@ -8,12 +8,12 @@
#include "assert/assert.hpp" #include "assert/assert.hpp"
namespace Dawn { namespace Dawn {
template<typename... A> template<typename... A>
struct IEventListener { struct IEventListener {
/** /**
* Abstracted method for C++ template reasons. Invokes the listener. * Abstracted method for C++ template reasons. Invokes the listener.
* *
* @deprecated
* @param args Arguments to pass to the listener. * @param args Arguments to pass to the listener.
*/ */
virtual void invoke(A... args) = 0; virtual void invoke(A... args) = 0;
@ -27,6 +27,7 @@ namespace Dawn {
/** /**
* Construct a new event listener structure. * Construct a new event listener structure.
* *
* @deprecated
* @param instance Instance that the callback belongs to. * @param instance Instance that the callback belongs to.
* @param callback Callback method that invokes back. * @param callback Callback method that invokes back.
*/ */
@ -42,6 +43,7 @@ namespace Dawn {
} }
}; };
/** @deprecated */
template<typename...A> template<typename...A>
class Event { class Event {
private: private:
@ -51,6 +53,7 @@ namespace Dawn {
/** /**
* Add a listener to this event. * Add a listener to this event.
* *
* @deprecated
* @tparam T The class that will receive the event. * @tparam T The class that will receive the event.
* @param instance Instance of type T that will receive the callback. * @param instance Instance of type T that will receive the callback.
* @param callback Callback method attached to T to receive the event. * @param callback Callback method attached to T to receive the event.
@ -72,6 +75,7 @@ namespace Dawn {
/** /**
* Removes an event listener from this event. * Removes an event listener from this event.
* *
* @deprecated
* @tparam T The class that was once receiving the event. * @tparam T The class that was once receiving the event.
* @param instance Instance of type T that did receive the callback. * @param instance Instance of type T that did receive the callback.
* @param callback Callback method attached to T for the event. * @param callback Callback method attached to T for the event.
@ -99,6 +103,7 @@ namespace Dawn {
/** /**
* Invokes the event and emits to all of the listeners. * Invokes the event and emits to all of the listeners.
* *
* @deprecated
* @param args Arguments for this event to pass to the listeners. * @param args Arguments for this event to pass to the listeners.
*/ */
void invoke(A... args) { void invoke(A... args) {

View File

@ -8,10 +8,44 @@
#include "StateProperty.hpp" #include "StateProperty.hpp"
namespace Dawn { namespace Dawn {
template<typename ...A>
class StateOwnerEventLegacy : public IStateOwnerEventLegacy {
public:
IStateOwner *owner;
Event<A...> *event;
std::function<void(A...)> fn;
/**
* Function used to simply remove the event listener from the legacy
* event, does not deal with the state owner.
*/
void removeListener() override {
event->removeListener(this, &StateOwnerEventLegacy::callback);
}
/**
* Function that can be used to tear down this legacy event.
*/
void teardown() override {
this->removeListener();
owner->_stateLegacyEventDisposed(this);
}
/**
* Callbaack method that is invoked by the legacy event.
* @param args Arguments received by legacy event.
*/
void callback(A... args) {
this->fn(args...);
}
};
class StateOwner : public IStateOwner { class StateOwner : public IStateOwner {
private: private:
std::vector<IStateEvent*> eventsSubscribed; std::vector<IStateEvent*> eventsSubscribed;
std::vector<IStateOwnerEventLegacy*> eventLegacyBridge;
public:
/** /**
* Called by the state event when it is disposing (before the StateOwner * Called by the state event when it is disposing (before the StateOwner
* itself is). * itself is).
@ -28,8 +62,25 @@ namespace Dawn {
} }
} }
} }
public: /**
* Called by legacy events when they are being disposed in a way that was
* not called by this state owner disposing.
*
* @param evt Event that is being disposed.
*/
void _stateLegacyEventDisposed(IStateOwnerEventLegacy *evt) override {
auto it = this->eventLegacyBridge.begin();
while(it != this->eventLegacyBridge.end()) {
if(*it == evt) {
this->eventLegacyBridge.erase(it);
break;
} else {
++it;
}
}
}
/** /**
* Listen for changes to a state property and invoke the provided func * Listen for changes to a state property and invoke the provided func
* when the value is changed. * when the value is changed.
@ -126,15 +177,55 @@ namespace Dawn {
return listener.unsub; return listener.unsub;
} }
/**
* Listen for callback of a legacy styled event. This will be removed in
* the future in favour of everything using State Events. This uses a lot
* more memory than the new state event listener.
*
* @deprecated In favour of StateEvent<>
* @tparam F The type of the callback function.
* @tparam A Argument types for the event.
* @param fn Callback function to be invoked when the event is triggered.
* @param event Event that will be listened to.
*/
template<typename F, typename... A>
std::function<void()> useEventLegacy(
F fn,
Event<A...> &event
) {
// This is a legacy feature to make upgrading to the new useEffect a bit
// easier for me. For the time being I am just bodging this together to
// do what I need here.
auto bridge = new StateOwnerEventLegacy<A...>();
bridge->owner = this;
bridge->event = &event;
bridge->fn = fn;
event.addListener(bridge, &StateOwnerEventLegacy<A...>::callback);
eventLegacyBridge.push_back(bridge);
return std::bind([&](IStateOwnerEventLegacy *evt){
evt->teardown();
}, bridge);
}
/**
* State Owner teardown function. Mostly just used to remove any lingering
* useEffects or useEvents.
*/
virtual ~StateOwner() { virtual ~StateOwner() {
auto it = this->eventsSubscribed.begin(); auto it = this->eventsSubscribed.begin();
while(it != this->eventsSubscribed.end()) { while(it != this->eventsSubscribed.end()) {
(*it)->_stateOwnerDestroyed(this); (*it)->_stateOwnerDestroyed(this);
++it; ++it;
} }
auto itBridge = this->eventLegacyBridge.begin();
while(itBridge != this->eventLegacyBridge.end()) {
(*itBridge)->removeListener();
delete *itBridge;
++itBridge;
}
} }
}; };
} }

View File

@ -4,31 +4,14 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "assert/assert.hpp" #include "StateInterfaces.hpp"
#include "event/Event.hpp"
namespace Dawn { namespace Dawn {
/** Forwarders / Fake Virtuals for other methods. */
template<typename...A> template<typename...A>
class StateEvent; class StateEvent : public IStateEvent {
class IStateEvent;
class IStateOwner {
public:
virtual void _stateEventDisposed(IStateEvent *evt) = 0;
};
template<typename...A>
struct StateEventListener {
uint32_t id;
IStateOwner *owner;
std::function<void(A...)> listener;
std::function<void(StateEventListener<A...>)> unsubWithParams;
std::function<void()> unsub;
StateEvent<A...> *event;
};
class IStateEvent {
protected: protected:
uint32_t stateEventId = 0;
/** /**
* Received notification from a state owner to let this state event know * Received notification from a state owner to let this state event know
* that it wishes to unsubscribe all the event listeners that it may have * that it wishes to unsubscribe all the event listeners that it may have
@ -36,17 +19,6 @@ namespace Dawn {
* *
* @param owner State owner that is being disposed. * @param owner State owner that is being disposed.
*/ */
virtual void _stateOwnerDestroyed(IStateOwner *owner) = 0;
friend class StateOwner;
};
template<typename...A>
class StateEvent : public IStateEvent {
protected:
uint32_t stateEventId = 0;
/** Refer to IStateEvent::_stateOwnerDestroyed */
void _stateOwnerDestroyed(IStateOwner *owner) override { void _stateOwnerDestroyed(IStateOwner *owner) override {
auto it = this->_eventListeners.begin(); auto it = this->_eventListeners.begin();
while(it != this->_eventListeners.end()) { while(it != this->_eventListeners.end()) {

View File

@ -0,0 +1,53 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "assert/assert.hpp"
#include "event/Event.hpp"
namespace Dawn {
class IStateEvent;
template<typename...A>
class StateEvent;
template<typename ...A>
class StateOwnerEventLegacy;
class IStateOwnerEventLegacy {
public:
virtual void removeListener() = 0;
virtual void teardown() = 0;
};
class IStateOwner {
public:
virtual void _stateEventDisposed(IStateEvent *evt) = 0;
virtual void _stateLegacyEventDisposed(IStateOwnerEventLegacy *evt) = 0;
};
template<typename...A>
struct StateEventListener {
uint32_t id;
IStateOwner *owner;
std::function<void(A...)> listener;
std::function<void(StateEventListener<A...>)> unsubWithParams;
std::function<void()> unsub;
StateEvent<A...> *event;
};
class IStateProperty {
public:
std::vector<std::function<void()>> _effectListners;
std::vector<std::function<std::function<void()>()>> _effectListnersWithTeardown;
std::vector<std::function<void()>> _effectTeardowns;
};
class IStateEvent {
protected:
virtual void _stateOwnerDestroyed(IStateOwner *owner) = 0;
friend class StateOwner;
};
}

View File

@ -4,16 +4,9 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "assert/assert.hpp" #include "StateInterfaces.hpp"
namespace Dawn { namespace Dawn {
class IStateProperty {
public:
std::vector<std::function<void()>> _effectListners;
std::vector<std::function<std::function<void()>()>> _effectListnersWithTeardown;
std::vector<std::function<void()>> _effectTeardowns;
};
template<class V> template<class V>
class StateProperty : public IStateProperty { class StateProperty : public IStateProperty {
private: private:

View File

@ -17,8 +17,8 @@ namespace Dawn {
class TicTacToeScene : public Scene { class TicTacToeScene : public Scene {
protected: protected:
Camera *camera; Camera *camera;
StateProperty<int32_t> age; int32_t age = 0;
StateEvent<int32_t> ageEvent; std::function<void()> evtUnsub;
void stage() override { void stage() override {
camera = Camera::create(this); camera = Camera::create(this);
@ -43,6 +43,11 @@ namespace Dawn {
tile->ticTacToe->tile = i++; tile->ticTacToe->tile = i++;
} }
} }
evtUnsub = useEventLegacy([&]{
std::cout << "Legacy Event Invoked " << age << std::endl;
evtUnsub();
}, this->eventSceneUpdate);
} }
std::vector<Asset*> getRequiredAssets() override { std::vector<Asset*> getRequiredAssets() override {