Skip to main content

StateManager.ixx File

Generic state manager and transition orchestrator. More...

Included Headers

Namespaces Index

namespacehelios
namespaceengine
namespacestate

Classes Index

classStateManager<StateType>

Manages state transitions using a rule-based system. More...

Description

Generic state manager and transition orchestrator.

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <memory>
8#include <span>
9#include <vector>
10
11
12export module helios.engine.state.StateManager;
13
14
15import helios.engine.state.TypedStateCommandHandler;
16import helios.engine.state.StateTransitionListener;
17import helios.engine.state.types.StateTransitionRule;
18
19import helios.engine.state.components;
20import helios.engine.state.commands;
21import helios.engine.state.types;
22
23import helios.engine.runtime.world.GameObject;
24
25
26import helios.engine.runtime.world.UpdateContext;
27
28import helios.engine.runtime.messaging.command.CommandHandlerRegistry;
29import helios.engine.runtime.world.Session;
30
31import helios.engine.runtime.world.Session;
32
33import helios.engine.core.types;
34import helios.engine.util.Guid;
35import helios.engine.runtime.world.tags.ManagerRole;
36
42
43export namespace helios::engine::state {
44
45
69 template <typename StateType>
71
75 std::vector<StateCommand<StateType>> pending_;
76
80 std::vector<std::unique_ptr<StateTransitionListener<StateType>>> listeners_;
81
85 std::vector<StateTransitionRule<StateType>> rules_;
86
95 void signalExit(
96 const StateType from,
97 const StateType to,
98 const StateTransitionIdType<StateType> transitionId,
100
101 for (auto& listener : listeners_) {
102 listener->onStateExit(updateContext, from);
103 }
104 }
105
114 void signalTransition(
115 const StateType from,
116 const StateType to,
117 const StateTransitionIdType<StateType> transitionId,
119
120 for (auto& listener : listeners_) {
121 listener->onStateTransition(
123 StateTransitionContext<StateType>{from, to, transitionId}
124 );
125 }
126 }
127
136 void signalEnter(
137 const StateType from,
138 const StateType to,
139 const StateTransitionIdType<StateType> transitionId,
141
142 for (auto& listener : listeners_) {
143 listener->onStateEnter(updateContext, to);
144
145 }
146 }
147
148
149 public:
151
157 explicit StateManager(std::span<const StateTransitionRule<StateType>> rules)
158 : rules_(rules.begin(), rules.end()) {}
159
168 listeners_.push_back(std::move(listener));
169 return *this;
170 }
171
180 void flush(
182 ) noexcept {
183
184 if (pending_.empty()) {
185 return;
186 }
187
188 auto command = pending_.back();
189
190 auto transitionRequest = command.transitionRequest();
191
192 auto& session = updateContext.session();
193 auto currentFrom = session.state<StateType>();
194 auto from = transitionRequest.from();
195 auto transitionId = transitionRequest.transitionId();
196
197
198 if (currentFrom != from) {
199 pending_.clear();
200 return;
201 }
202
203
204 for (auto& rule : rules_) {
205 if (rule.from() == from && rule.transitionId() == transitionId) {
206
207 if (rule.guard()) {
208 if (!rule.guard()(updateContext, transitionRequest)) {
209 break;
210 }
211 }
212
213 signalExit(from, rule.to(), transitionId, updateContext);
214 signalTransition(from, rule.to(), transitionId, updateContext);
215 session.setStateFrom<StateType>(StateTransitionContext<StateType>{rule.from(), rule.to(), transitionId});
216 signalEnter(from, rule.to(), transitionId, updateContext);
217 }
218 }
219
220 pending_.clear();
221 }
222
230 bool submit(
232 ) noexcept {
233 pending_.push_back(stateCommand);
234 return true;
235 };
236
250 bool submit(
252 ) noexcept {
253 pending_.push_back(StateCommand<StateType>(stateCommand.transitionRequest()));
254 return true;
255 };
256
263 commandHandlerRegistry.registerHandler<StateCommand<StateType>>(*this);
264 commandHandlerRegistry.registerHandler<DelayedStateCommand<StateType>>(*this);
265 }
266
270 void reset() {
271 // intentionally left empty. Clearing the pending queue would also mean
272 // that any pending state transisions **required by the reset** are nuked.
273 }
274
275 };
276
277}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.