Unravel Engine C++ Reference
Loading...
Searching...
No Matches
seq_manager.cpp
Go to the documentation of this file.
1#include <stdexcept>
2
3#include "seq_manager.h"
4#include "seq_private.h"
5
6namespace seq
7{
8
9auto seq_manager::start(seq_action action, const seq_scope_policy& scope_policy, bool force_queue) -> seq_id_t
10{
11 const auto id = action.get_id();
12
13 if(is_running(action))
14 {
15 return id;
16 }
17
18 if(is_paused(action))
19 {
20 resume(action);
21 return id;
22 }
23
24 auto fill_info = [this, &scope_policy](seq_info& info, seq_action&& action)
25 {
26 info.action = std::move(action);
27 if(scope_policy.scope.empty())
28 {
29 info.scopes.insert(info.scopes.end(), scopes_.begin(), scopes_.end());
30 }
31 else
32 {
33 if(scope_policy.policy == seq_scope_policy::policy_t::independent)
34 {
35 info.scopes.emplace_back(scope_policy.scope);
36 }
37 else if(scope_policy.policy == seq_scope_policy::policy_t::stacked)
38 {
39 info.scopes.insert(info.scopes.end(), scopes_.begin(), scopes_.end());
40 info.scopes.emplace_back(scope_policy.scope);
41 }
42 }
43 };
44
45 if(force_queue)
46 {
47 auto& info = pending_actions_[id];
48 fill_info(info, std::move(action));
49 return id;
50 }
51
52 auto iter = actions_.find(id);
53 if(iter == actions_.end())
54 {
55 auto& info = actions_[id];
56 fill_info(info, std::move(action));
57
58 start_action(info);
59 }
60 else
61 {
62 // Occurs when start yourself from your own callback or start yourself from previous action process
63 auto& info = pending_actions_[id];
64 fill_info(info, std::move(action));
65 }
66
67 return id;
68}
69
71{
72 auto iter = actions_.find(id);
73 if(iter != std::end(actions_))
74 {
75 seq_private::stop(iter->second.action);
76 }
77
78 auto pending_iter = pending_actions_.find(id);
79 if(pending_iter != std::end(pending_actions_))
80 {
81 pending_actions_.erase(pending_iter);
82 }
83}
84
85void seq_manager::stop_all(const std::string& scope)
86{
87 for(auto& info : actions_)
88 {
89 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
90 {
91 seq_private::stop(info.second.action);
92 }
93 }
94}
95
97{
98 auto iter = actions_.find(id);
99 if(iter != std::end(actions_))
100 {
101 seq_private::pause(iter->second.action);
102 }
103}
104
105void seq_manager::pause_all(const std::string& scope, const std::string& key)
106{
107 paused_scopes_.insert(std::make_pair(scope, key));
108
109 for(auto& info : actions_)
110 {
111 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
112 {
113 seq_private::pause(info.second.action, key);
114 }
115 }
116}
117
119{
120 auto iter = actions_.find(action);
121 if(iter != std::end(actions_))
122 {
123 seq_private::resume(iter->second.action);
124 }
125}
126
127void seq_manager::resume_all(const std::string& scope, const std::string& key)
128{
129 paused_scopes_.erase(std::make_pair(scope, key));
130
131 for(auto& info : actions_)
132 {
133 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
134 {
135 seq_private::resume(info.second.action, key);
136 }
137 }
138}
139
141{
142 auto iter = actions_.find(id);
143 if(iter != std::end(actions_))
144 {
145 seq_private::stop_when_finished(iter->second.action);
146 }
147}
148
149void seq_manager::stop_when_finished_all(const std::string& scope)
150{
151 for(auto& info : actions_)
152 {
153 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
154 {
155 seq_private::stop_when_finished(info.second.action);
156 }
157 }
158}
159
161{
162 auto iter = actions_.find(id);
163 if(iter == std::end(actions_))
164 {
165 return;
166 }
167 auto& action = iter->second.action;
168
170 {
171 return;
172 }
173 auto& depth = iter->second.depth;
174
175 if(depth > 0)
176 {
177 stop(action);
178 throw std::runtime_error("Cannot call stop_and_finish from callbacks.");
179 }
180
183 while(true)
184 {
185 const bool force = true;
186 seq_private::resume(action, force);
187
188 ++depth;
189 bool finished = state_t::finished == seq_private::update(action, 99h);
190 --depth;
191
192 if(finished)
193 {
194 break;
195 }
196 }
197}
198
199void seq_manager::stop_and_finish_all(const std::string& scope)
200{
201 for(auto& info : actions_)
202 {
203 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
204 {
205 stop_and_finish(info.second.action);
206 }
207 }
208}
209
210auto seq_manager::is_stopping(seq_id_t id) const -> bool
211{
212 auto iter = actions_.find(id);
213 if(iter != std::end(actions_))
214 {
215 return seq_private::is_stop_when_finished_requested(iter->second.action);
216 }
217 return false;
218}
219
220auto seq_manager::is_running(seq_id_t id) const -> bool
221{
222 auto iter = actions_.find(id);
223 if(iter != std::end(actions_))
224 {
225 return seq_private::is_running(iter->second.action);
226 }
227 return false;
228}
229
230auto seq_manager::is_paused(seq_id_t id) const -> bool
231{
232 auto iter = actions_.find(id);
233 if(iter != std::end(actions_))
234 {
235 return seq_private::is_paused(iter->second.action);
236 }
237 return false;
238}
239
240auto seq_manager::is_finished(seq_id_t id) const -> bool
241{
242 auto iter = actions_.find(id);
243 if(iter != std::end(actions_))
244 {
245 return seq_private::is_finished(iter->second.action);
246 }
247 return true;
248}
249
250void seq_manager::set_speed_multiplier(seq_id_t id, float speed_multiplier)
251{
252 auto iter = actions_.find(id);
253 if(iter != std::end(actions_))
254 {
255 seq_private::set_speed_multiplier(iter->second.action, speed_multiplier);
256 }
257}
258
260{
261 auto iter = actions_.find(id);
262 if(iter != std::end(actions_))
263 {
264 return seq_private::get_speed_multiplier(iter->second.action);
265 }
266 return 1.0f;
267}
268
270{
271 auto iter = actions_.find(id);
272 if(iter != std::end(actions_))
273 {
274 return seq_private::get_elapsed(iter->second.action);
275 }
276 return {};
277}
278
280{
281 auto iter = actions_.find(id);
282 if(iter != std::end(actions_))
283 {
284 return seq_private::get_duration(iter->second.action);
285 }
286 return {};
287}
288
290{
291 auto iter = actions_.find(id);
292 if(iter != std::end(actions_))
293 {
294 return seq_private::get_overflow(iter->second.action);
295 }
296 return {};
297}
298
300{
301 auto iter = actions_.find(id);
302 if(iter != std::end(actions_))
303 {
304 seq_private::update(iter->second.action, delta);
305 }
306}
307
309{
310 auto iter = actions_.find(id);
311 if(iter == std::end(actions_))
312 {
313 return;
314 }
315
316 seq_private::set_elapsed(iter->second.action, elapsed);
317}
318
320{
321 if(delta < duration_t::zero())
322 {
323 delta = duration_t::zero();
324 }
325
326 std::vector<seq_id_t> actions_to_start;
327 actions_to_start.reserve(pending_actions_.size());
328
329 for(auto& kvp : pending_actions_)
330 {
331 actions_to_start.emplace_back(kvp.first);
332
333 actions_[kvp.first] = std::move(kvp.second);
334 }
335 pending_actions_.clear();
336
337 for(auto id : actions_to_start)
338 {
339 start_action(actions_.at(id));
340 }
341
342 for(auto id : get_ids())
343 {
344 auto& action = actions_[id];
345
346 if(action.depth > 0)
347 {
348 continue;
349 }
350
351 action.depth++;
352
353 auto state = seq_private::update(action.action, delta);
354
355 action.depth--;
356
357 if(state == state_t::finished)
358 {
359 actions_.erase(action.action.get_id());
360 }
361 }
362}
363
364void seq_manager::push_scope(const std::string& scope)
365{
366 if(scope.empty())
367 {
368 return;
369 }
370
371 auto iter = std::find(scopes_.begin(), scopes_.end(), scope);
372 if(iter != scopes_.end())
373 {
374 throw std::logic_error("push_scope that is already pushed.");
375 }
376
377 scopes_.emplace_back(scope);
378 current_scope_idx_ = static_cast<int32_t>(scopes_.size()) - 1;
379}
380
382{
383 if(current_scope_idx_ < int32_t(scopes_.size()))
384 {
385 close_scope(scopes_.at(current_scope_idx_));
386 }
387}
388
389void seq_manager::close_scope(const std::string& scope)
390{
391 auto iter = std::find(scopes_.begin(), scopes_.end(), scope);
392 scopes_.erase(iter, scopes_.end());
393
394 current_scope_idx_ = static_cast<int32_t>(scopes_.size()) - 1;
395}
396
398{
399 scopes_.clear();
400 current_scope_idx_ = (-1);
401}
402
403void seq_manager::start_action(seq_info& info)
404{
405 auto& action = info.action;
406
407 bool paused_by_scope = false;
408 // First force pause the action before it was started
409 for(const auto& scope : info.scopes)
410 {
411 auto it = std::find_if(paused_scopes_.begin(),
412 paused_scopes_.end(),
413 [&](const auto& sc)
414 {
415 return sc.first == scope;
416 });
417 if(it != paused_scopes_.end())
418 {
419 const auto& scope_pause_key = it->second;
420 seq_private::pause_forced(action, scope_pause_key);
421 paused_by_scope = true;
422 break;
423 }
424 }
425
426 seq_private::start(action);
427
428 if(paused_by_scope)
429 {
431 }
432}
433
434auto seq_manager::get_current_scope() const -> const std::string&
435{
436 static const std::string default_scope{};
437 if(scopes_.empty())
438 {
439 return default_scope;
440 }
441 return scopes_.at(current_scope_idx_);
442}
443
444auto seq_manager::get_scopes() const -> const std::vector<std::string>&
445{
446 return scopes_;
447}
448
450{
451 return actions_;
452}
453
454auto seq_manager::get_ids() const -> std::vector<seq_id_t>
455{
456 std::vector<seq_id_t> result;
457 result.reserve(actions_.size());
458 for(const auto& kvp : actions_)
459 {
460 result.emplace_back(kvp.first);
461 }
462 return result;
463}
464
465auto seq_manager::has_action_with_scope(const std::string& scope_id) -> bool
466{
467 for(const auto& kvp : actions_)
468 {
469 if(std::find(kvp.second.scopes.begin(), kvp.second.scopes.end(), scope_id) != kvp.second.scopes.end())
470 {
471 return true;
472 }
473 };
474 return false;
475}
476
477} // namespace seq
float elapsed
const char * id
Provides a sequence-based action management system for controlling and scheduling actions.
size_t seq_id_t
Represents a unique identifier for sequence actions.
Definition seq_common.h:53
@ finished
The action has finished.
auto is_paused(seq_id_t id) -> bool
Checks if the action is paused.
Definition seq.cpp:55
void resume(const seq_id_t id)
Resumes the action associated with the given ID.
Definition seq.cpp:30
auto is_running(seq_id_t id) -> bool
Checks if the action is running.
Definition seq.cpp:50
std::chrono::nanoseconds duration_t
Represents a duration in nanoseconds.
Definition seq_common.h:41
Hash specialization for batch_key to enable use in std::unordered_map.
Represents an action within the sequence management system. Contains lifecycle events and management ...
Definition seq_action.h:18
Stores information about an action, including its state, depth, and associated scopes.
Definition seq_manager.h:24
seq_action action
The action being managed.
Definition seq_manager.h:28
std::vector< std::string > scopes
The scopes associated with the action.
Definition seq_manager.h:38
void resume(seq_id_t id)
Resumes the action associated with the specified ID.
void close_scope(const std::string &scope)
Closes a scope, removing it from the stack.
auto get_elapsed(seq_id_t id) const -> duration_t
Gets the elapsed time of an action.
auto get_duration(seq_id_t id) const -> duration_t
Gets the total duration of an action.
void stop_and_finish(seq_id_t id, duration_t finish_after=0ms)
Stops an action and ensures it completes after the specified duration.
void resume_all(const std::string &scope={}, const std::string &key={})
Resumes all actions within the specified scope and key.
seq_id_t start(seq_action action, const seq_scope_policy &scope_policy={}, bool force_queue=false)
Starts a new action and associates it with the specified scope policy.
auto is_stopping(seq_id_t id) const -> bool
Checks if an action is stopping.
void push_scope(const std::string &scope)
Pushes a scope onto the scope stack.
auto is_finished(seq_id_t id) const -> bool
Checks if an action has finished.
auto get_overflow(seq_id_t id) const -> duration_t
Gets the overflow time of an action.
void stop_and_finish_all(const std::string &scope={})
Stops all actions in the specified scope and ensures they complete.
auto get_current_scope() const -> const std::string &
Gets the current scope from the scope stack.
void clear_scopes()
Clears all scopes from the scope stack.
void stop_all(const std::string &scope={})
Stops all actions within the specified scope.
auto get_speed_multiplier(seq_id_t id) -> float
Gets the speed multiplier of an action.
auto get_scopes() const -> const std::vector< std::string > &
Gets the list of all active scopes.
auto is_paused(seq_id_t id) const -> bool
Checks if an action is paused.
void set_elapsed(seq_id_t id, duration_t elapsed)
Sets the elapsed time of an action (use with caution).
void set_speed_multiplier(seq_id_t id, float speed_multiplier=1.0f)
Sets the speed multiplier for an action.
void pause_all(const std::string &scope={}, const std::string &key={})
Pauses all actions within the specified scope and key.
void pause(seq_id_t id)
Pauses the action associated with the specified ID.
void update(seq_id_t id, duration_t delta)
Updates the elapsed time of a specific action.
void stop_when_finished_all(const std::string &scope={})
Marks all actions in the specified scope to stop when they finish.
auto get_actions() const -> const action_collection_t &
Gets the collection of all managed actions.
std::map< seq_id_t, seq_info > action_collection_t
Alias for the collection of actions managed by the seq_manager.
Definition seq_manager.h:44
void stop_when_finished(seq_id_t id)
Marks an action to stop when it finishes.
bool has_action_with_scope(const std::string &scope_id)
Checks if there is any action associated with the specified scope ID.
void pop_scope()
Pops the current scope from the scope stack.
void stop(seq_id_t id)
Stops the action associated with the specified ID.
auto is_running(seq_id_t id) const -> bool
Checks if an action is running.
static void pause_forced(seq_action &action)
Forcibly pauses a given action.
Definition seq_private.h:97
static auto get_duration(const seq_action &self) -> duration_t
Gets the total duration of a given action.
static void pause(seq_action &action)
Pauses a given action.
Definition seq_private.h:78
static void start(seq_action &action)
Starts a given action.
Definition seq_private.h:22
static void stop(seq_action &action)
Stops a given action.
Definition seq_private.h:31
static auto update(seq_action &action, duration_t delta) -> state_t
Updates a given action with a time delta.
static auto is_running(const seq_action &action) -> bool
Checks if the action is currently running.
static void set_elapsed(seq_action &self, duration_t elapsed)
Sets the elapsed time of a given action.
static void stop_and_finished(seq_action &action)
Marks a given action as stopped and finished.
Definition seq_private.h:40
static void stop_when_finished(seq_action &action)
Marks a given action to stop when finished.
Definition seq_private.h:49
static void set_speed_multiplier(seq_action &action, float speed_multiplier)
Sets the speed multiplier for a given action.
static auto get_speed_multiplier(const seq_action &action) -> float
Gets the speed multiplier of a given action.
static auto is_finished(const seq_action &action) -> bool
Checks if the action is finished.
static auto is_paused(const seq_action &action) -> bool
Checks if the action is currently paused.
static auto get_overflow(const seq_action &self) -> duration_t
Computes the overflow duration of a given action if it exceeds its total duration.
static auto get_state(const seq_action &action) -> state_t
Gets the current state of a given action.
static auto is_stop_when_finished_requested(const seq_action &action) -> bool
Checks if the action is requested to stop when finished.
static void resume(seq_action &action, bool force=false)
Resumes a given action, optionally forcing the resume.
Definition seq_private.h:59
static auto get_elapsed(const seq_action &self) -> duration_t
Gets the elapsed time of a given action.
Defines policies for scoping actions in a sequence.
Definition seq_common.h:92
@ stacked
Actions share the same scope and stack behavior.
@ independent
Actions operate independently within their scope.