12#include <unordered_map>
107 template<
typename StateEnum>
116 std::function<
Core*()> factory;
117 std::unique_ptr<Core> owned;
119 bool isLazy()
const {
return static_cast<bool>(factory); }
120 bool isActive()
const {
return scene !=
nullptr; }
123 Core* get()
const {
return scene; }
129 inline static std::unordered_map<StateEnum, SceneEntry, EnumClassHash> _bindings;
130 inline static std::vector<StateEnum> _history;
131 inline static StateEnum _current{};
132 inline static bool _started =
false;
133 inline static bool _attached =
false;
136 inline static std::function<void(
Core&)> _add;
139 inline static std::function<void(
Core&)> _remove;
142 inline static std::function<void(StateEnum)> _setter;
160 _bindings[state] = SceneEntry{ &scene,
nullptr,
nullptr };
180 template<
typename SceneType,
typename... Args>
181 static void bindLazy(StateEnum state, Args&&... args)
183 static_assert(std::is_base_of_v<Core, SceneType>,
184 "[SceneManager] bindLazy: SceneType must derive from ml::Core.");
187 _bindings[state] = SceneEntry
190 [capturedArgs = std::make_tuple(std::forward<Args>(args)...)]()
mutable ->
Core*
192 return std::apply([](
auto&&... a) ->
Core*
194 return new SceneType(std::forward<
decltype(a)>(a)...);
222 template<
typename App>
228 _setter = [&app](StateEnum s) { app.setState(s); };
229 _add = [&app](
Core& s) { app.addComponent(s); };
233 _remove = [&app](
Core& s)
235 if constexpr (
requires { app.removeComponent(s); })
236 app.removeComponent(s);
242 app.onStateExit([](StateEnum leaving)
244 SceneManager::deactivate(leaving);
247 app.onStateEnter([](StateEnum entering)
249 SceneManager::activate(entering);
285 if (_history.empty())
return;
287 StateEnum previous = _history.back();
304 static StateEnum
current() {
return _current; }
310 static bool isActive(StateEnum state) {
return _started && _current == state; }
316 static bool has(StateEnum state) {
return _bindings.count(state) > 0; }
349 static void activate(StateEnum state)
351 auto it = _bindings.find(state);
352 if (it == _bindings.end())
return;
354 SceneEntry& entry = it->second;
361 entry.owned.reset(entry.factory());
362 entry.scene = entry.owned.get();
366 if (entry.scene && _add)
378 static void deactivate(StateEnum state)
380 auto it = _bindings.find(state);
381 if (it == _bindings.end())
return;
383 SceneEntry& entry = it->second;
385 if (entry.scene && _remove)
386 _remove(*entry.scene);
389 _history.push_back(state);
395 entry.scene =
nullptr;
Virtual base class for all Malena framework objects.
static bool removeComponent(T &component)
Unregister a T object by reference.
State-driven scene router for Malena applications.
static void bind(StateEnum state, Core &scene)
Bind an existing scene instance to a state (eager).
static void attach(App &app)
Wire SceneManager into the application's state machine.
static void back()
Navigate to the previously visited state.
static void clear()
Clear all bindings and history.
static bool isActive(StateEnum state)
Return true if state is currently the active scene.
static StateEnum current()
Return the currently active state.
static void bindLazy(StateEnum state, Args &&... args)
Bind a lazily-constructed scene type to a state.
static void start(StateEnum state)
Activate the initial scene without recording a history entry.
static bool has(StateEnum state)
Return true if a scene has been bound to state.