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) -> 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 auto iter = actions_.find(id);
46 if(iter == actions_.end())
47 {
48 auto& info = actions_[id];
49 fill_info(info, std::move(action));
50
51 start_action(info);
52 }
53 else
54 {
55 // Occurs when start yourself from your own callback or start yourself from previous action process
56 auto& info = pending_actions_[id];
57 fill_info(info, std::move(action));
58 }
59
60 return id;
61}
62
64{
65 auto iter = actions_.find(id);
66 if(iter != std::end(actions_))
67 {
68 seq_private::stop(iter->second.action);
69 }
70
71 auto pending_iter = pending_actions_.find(id);
72 if(pending_iter != std::end(pending_actions_))
73 {
74 pending_actions_.erase(pending_iter);
75 }
76}
77
78void seq_manager::stop_all(const std::string& scope)
79{
80 for(auto& info : actions_)
81 {
82 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
83 {
84 seq_private::stop(info.second.action);
85 }
86 }
87}
88
90{
91 auto iter = actions_.find(id);
92 if(iter != std::end(actions_))
93 {
94 seq_private::pause(iter->second.action);
95 }
96}
97
98void seq_manager::pause_all(const std::string& scope, const std::string& key)
99{
100 paused_scopes_.insert(std::make_pair(scope, key));
101
102 for(auto& info : actions_)
103 {
104 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
105 {
106 seq_private::pause(info.second.action, key);
107 }
108 }
109}
110
112{
113 auto iter = actions_.find(action);
114 if(iter != std::end(actions_))
115 {
116 seq_private::resume(iter->second.action);
117 }
118}
119
120void seq_manager::resume_all(const std::string& scope, const std::string& key)
121{
122 paused_scopes_.erase(std::make_pair(scope, key));
123
124 for(auto& info : actions_)
125 {
126 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
127 {
128 seq_private::resume(info.second.action, key);
129 }
130 }
131}
132
134{
135 auto iter = actions_.find(id);
136 if(iter != std::end(actions_))
137 {
138 seq_private::stop_when_finished(iter->second.action);
139 }
140}
141
142void seq_manager::stop_when_finished_all(const std::string& scope)
143{
144 for(auto& info : actions_)
145 {
146 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
147 {
148 seq_private::stop_when_finished(info.second.action);
149 }
150 }
151}
152
154{
155 auto iter = actions_.find(id);
156 if(iter == std::end(actions_))
157 {
158 return;
159 }
160 auto& action = iter->second.action;
161
163 {
164 return;
165 }
166 auto& depth = iter->second.depth;
167
168 if(depth > 0)
169 {
170 stop(action);
171 throw std::runtime_error("Cannot call stop_and_finish from callbacks.");
172 }
173
176 while(true)
177 {
178 const bool force = true;
179 seq_private::resume(action, force);
180
181 ++depth;
182 bool finished = state_t::finished == seq_private::update(action, 99h);
183 --depth;
184
185 if(finished)
186 {
187 break;
188 }
189 }
190}
191
192void seq_manager::stop_and_finish_all(const std::string& scope)
193{
194 for(auto& info : actions_)
195 {
196 if(std::find(info.second.scopes.begin(), info.second.scopes.end(), scope) != info.second.scopes.end())
197 {
198 stop_and_finish(info.second.action);
199 }
200 }
201}
202
203auto seq_manager::is_stopping(seq_id_t id) const -> bool
204{
205 auto iter = actions_.find(id);
206 if(iter != std::end(actions_))
207 {
208 return seq_private::is_stop_when_finished_requested(iter->second.action);
209 }
210 return false;
211}
212
213auto seq_manager::is_running(seq_id_t id) const -> bool
214{
215 auto iter = actions_.find(id);
216 if(iter != std::end(actions_))
217 {
218 return seq_private::is_running(iter->second.action);
219 }
220 return false;
221}
222
223auto seq_manager::is_paused(seq_id_t id) const -> bool
224{
225 auto iter = actions_.find(id);
226 if(iter != std::end(actions_))
227 {
228 return seq_private::is_paused(iter->second.action);
229 }
230 return false;
231}
232
233auto seq_manager::is_finished(seq_id_t id) const -> bool
234{
235 auto iter = actions_.find(id);
236 if(iter != std::end(actions_))
237 {
238 return seq_private::is_finished(iter->second.action);
239 }
240 return true;
241}
242
243void seq_manager::set_speed_multiplier(seq_id_t id, float speed_multiplier)
244{
245 auto iter = actions_.find(id);
246 if(iter != std::end(actions_))
247 {
248 seq_private::set_speed_multiplier(iter->second.action, speed_multiplier);
249 }
250}
251
253{
254 auto iter = actions_.find(id);
255 if(iter != std::end(actions_))
256 {
257 return seq_private::get_speed_multiplier(iter->second.action);
258 }
259 return 1.0f;
260}
261
263{
264 auto iter = actions_.find(id);
265 if(iter != std::end(actions_))
266 {
267 return seq_private::get_elapsed(iter->second.action);
268 }
269 return {};
270}
271
273{
274 auto iter = actions_.find(id);
275 if(iter != std::end(actions_))
276 {
277 return seq_private::get_duration(iter->second.action);
278 }
279 return {};
280}
281
283{
284 auto iter = actions_.find(id);
285 if(iter != std::end(actions_))
286 {
287 return seq_private::get_overflow(iter->second.action);
288 }
289 return {};
290}
291
293{
294 auto iter = actions_.find(id);
295 if(iter != std::end(actions_))
296 {
297 seq_private::update(iter->second.action, delta);
298 }
299}
300
302{
303 auto iter = actions_.find(id);
304 if(iter == std::end(actions_))
305 {
306 return;
307 }
308
309 seq_private::set_elapsed(iter->second.action, elapsed);
310}
311
313{
314 if(delta < duration_t::zero())
315 {
316 delta = duration_t::zero();
317 }
318
319 std::vector<seq_id_t> actions_to_start;
320 actions_to_start.reserve(pending_actions_.size());
321
322 for(auto& kvp : pending_actions_)
323 {
324 actions_to_start.emplace_back(kvp.first);
325
326 actions_[kvp.first] = std::move(kvp.second);
327 }
328 pending_actions_.clear();
329
330 for(auto id : actions_to_start)
331 {
332 start_action(actions_.at(id));
333 }
334
335 for(auto id : get_ids())
336 {
337 auto& action = actions_[id];
338
339 if(action.depth > 0)
340 {
341 continue;
342 }
343
344 action.depth++;
345
346 auto state = seq_private::update(action.action, delta);
347
348 action.depth--;
349
350 if(state == state_t::finished)
351 {
352 actions_.erase(action.action.get_id());
353 }
354 }
355}
356
357void seq_manager::push_scope(const std::string& scope)
358{
359 if(scope.empty())
360 {
361 return;
362 }
363
364 auto iter = std::find(scopes_.begin(), scopes_.end(), scope);
365 if(iter != scopes_.end())
366 {
367 throw std::logic_error("push_scope that is already pushed.");
368 }
369
370 scopes_.emplace_back(scope);
371 current_scope_idx_ = static_cast<int32_t>(scopes_.size()) - 1;
372}
373
375{
376 if(current_scope_idx_ < int32_t(scopes_.size()))
377 {
378 close_scope(scopes_.at(current_scope_idx_));
379 }
380}
381
382void seq_manager::close_scope(const std::string& scope)
383{
384 auto iter = std::find(scopes_.begin(), scopes_.end(), scope);
385 scopes_.erase(iter, scopes_.end());
386
387 current_scope_idx_ = static_cast<int32_t>(scopes_.size()) - 1;
388}
389
391{
392 scopes_.clear();
393 current_scope_idx_ = (-1);
394}
395
396void seq_manager::start_action(seq_info& info)
397{
398 auto& action = info.action;
399
400 bool paused_by_scope = false;
401 // First force pause the action before it was started
402 for(const auto& scope : info.scopes)
403 {
404 auto it = std::find_if(paused_scopes_.begin(),
405 paused_scopes_.end(),
406 [&](const auto& sc)
407 {
408 return sc.first == scope;
409 });
410 if(it != paused_scopes_.end())
411 {
412 const auto& scope_pause_key = it->second;
413 seq_private::pause_forced(action, scope_pause_key);
414 paused_by_scope = true;
415 break;
416 }
417 }
418
419 seq_private::start(action);
420
421 if(paused_by_scope)
422 {
424 }
425}
426
427auto seq_manager::get_current_scope() const -> const std::string&
428{
429 static const std::string default_scope{};
430 if(scopes_.empty())
431 {
432 return default_scope;
433 }
434 return scopes_.at(current_scope_idx_);
435}
436
437auto seq_manager::get_scopes() const -> const std::vector<std::string>&
438{
439 return scopes_;
440}
441
443{
444 return actions_;
445}
446
447auto seq_manager::get_ids() const -> std::vector<seq_id_t>
448{
449 std::vector<seq_id_t> result;
450 result.reserve(actions_.size());
451 for(const auto& kvp : actions_)
452 {
453 result.emplace_back(kvp.first);
454 }
455 return result;
456}
457
458auto seq_manager::has_action_with_scope(const std::string& scope_id) -> bool
459{
460 for(const auto& kvp : actions_)
461 {
462 if(std::find(kvp.second.scopes.begin(), kvp.second.scopes.end(), scope_id) != kvp.second.scopes.end())
463 {
464 return true;
465 }
466 };
467 return false;
468}
469
470} // namespace seq
float elapsed
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:49
void resume(const seq_id_t id)
Resumes the action associated with the given ID.
Definition seq.cpp:24
auto is_running(seq_id_t id) -> bool
Checks if the action is running.
Definition seq.cpp:44
std::chrono::nanoseconds duration_t
Represents a duration in nanoseconds.
Definition seq_common.h:41
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.
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.
seq_id_t start(seq_action action, const seq_scope_policy &scope_policy={})
Starts a new action and associates it with the specified scope policy.
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.