101 lines
2.1 KiB
C++
101 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "assert.hpp"
|
|
#include "step_function.hpp"
|
|
#include "types.hpp"
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <type_traits>
|
|
#include "time.hpp"
|
|
|
|
enum class ReturnTag {
|
|
Repeat,
|
|
Next,
|
|
Previous,
|
|
Goto,
|
|
};
|
|
|
|
struct Return {
|
|
ReturnTag tag;
|
|
union {
|
|
isize index;
|
|
};
|
|
};
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
class Stepped {
|
|
|
|
using duration_type = std::chrono::system_clock::duration;
|
|
using step_return_type = std::pair<Return, duration_type>;
|
|
using step_type = std::function<step_return_type()>;
|
|
|
|
std::vector<step_type> m_steps;
|
|
|
|
isize m_current_step;
|
|
duration_type m_current_wait_duration;
|
|
util::Delta m_delta;
|
|
|
|
auto inc_step() -> void;
|
|
auto dec_step() -> void;
|
|
|
|
public:
|
|
Stepped() : m_current_step(0), m_steps(), m_delta(), m_current_wait_duration(0ms) {}
|
|
|
|
auto add_step(const step_type& step) -> void;
|
|
auto run() -> void;
|
|
auto reset() -> void;
|
|
|
|
|
|
};
|
|
|
|
/// IMPLEMENTATION
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
auto Stepped::inc_step() -> void {
|
|
if (++m_current_step >= m_steps.size()) {
|
|
m_current_step = 0;
|
|
}
|
|
}
|
|
|
|
auto Stepped::dec_step() -> void {
|
|
if (--m_current_step < 0) {
|
|
m_current_step = m_steps.size() - 1;
|
|
}
|
|
}
|
|
|
|
auto Stepped::add_step(const step_type &step) -> void {
|
|
m_steps.push_back(step);
|
|
}
|
|
|
|
auto Stepped::reset() -> void {
|
|
m_current_step = 0;
|
|
m_current_wait_duration = 0ms;
|
|
}
|
|
|
|
auto Stepped::run() -> void {
|
|
if (m_delta.has_elapsed(m_current_wait_duration)) {
|
|
util::assert(m_current_step < m_steps.size());
|
|
|
|
auto&& [result, next_wait_duration] = m_steps[m_current_step]();
|
|
|
|
switch (result.tag) {
|
|
case ReturnTag::Repeat:
|
|
break;
|
|
case ReturnTag::Next:
|
|
inc_step();
|
|
break;
|
|
case ReturnTag::Previous:
|
|
dec_step();
|
|
break;
|
|
case ReturnTag::Goto: {
|
|
util::assert(result.index < m_steps.size() && result.index >= 0);
|
|
m_current_step = result.index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_current_wait_duration = next_wait_duration;
|
|
}
|
|
} |