Commit d0f90394 authored by Florian Oetke's avatar Florian Oetke
Browse files

deferred actions [#36]

parent 2af1b035
......@@ -7,6 +7,9 @@
#pragma once
#include <mirrage/asset/asset_manager.hpp>
#include <mirrage/utils/defer.hpp>
#include <mirrage/utils/maybe.hpp>
#include <mirrage/utils/units.hpp>
......@@ -19,13 +22,15 @@ namespace mirrage {
enum class Prev_screen_policy { discard, stack, draw, update };
class Screen {
class Screen : private util::Deferred_action_container {
public:
Screen(Engine& engine) : _engine(engine) {}
Screen(const Screen&) = delete;
Screen& operator=(const Screen&) = delete;
virtual ~Screen() noexcept = default;
virtual ~Screen() noexcept;
using Deferred_action_container::defer;
protected:
friend class Screen_manager;
......@@ -37,6 +42,9 @@ namespace mirrage {
virtual auto _prev_screen_policy() const noexcept -> Prev_screen_policy = 0;
Engine& _engine;
private:
void _actual_update(util::Time delta_time);
};
class Screen_manager {
......
......@@ -5,6 +5,15 @@
namespace mirrage {
Screen::~Screen() noexcept = default;
void Screen::_actual_update(util::Time delta_time)
{
Deferred_action_container::update(delta_time);
_update(delta_time);
}
Screen_manager::Screen_manager(Engine& engine) : _engine(engine) {}
Screen_manager::~Screen_manager() noexcept { clear(); }
......@@ -45,7 +54,7 @@ namespace mirrage {
for(; screen_index >= 0; screen_index--) {
auto& s = screen_stack.at(size_t(screen_index));
s->_update(delta_time);
s->_actual_update(delta_time);
if(s->_prev_screen_policy() != Prev_screen_policy::update)
break;
......
......@@ -10,6 +10,7 @@ file(GLOB_RECURSE HEADER_FILES
add_library(mirrage_utils STATIC
src/command.cpp
src/defer.cpp
src/log.cpp
src/md5.cpp
src/pool.cpp
......
/** container to defer action until later without multithreading *************
* *
* Copyright (c) 2018 Florian Oetke *
* This file is distributed under the MIT License *
* See LICENSE file for details. *
\*****************************************************************************/
#pragma once
#include <mirrage/utils/units.hpp>
#include <functional>
#include <vector>
namespace mirrage::util {
class Deferred_action_container {
public:
void defer(util::Time, std::function<void()> callback);
template <class Future, class F, typename = std::enable_if_t<!std::is_same_v<Future, util::Time>>>
void defer(Future f, F&& callback)
{
_defered_actions.emplace_back([f] { return f.ready(); },
[f, callback = std::move(callback)] { callback(*f); });
}
void update(util::Time dt);
private:
struct Defered_action {
std::function<bool()> ready;
std::function<void()> callback;
Defered_action(std::function<bool()> ready, std::function<void()> callback)
: ready(std::move(ready)), callback(std::move(callback))
{
}
};
float _time_since_start = 0;
std::vector<Defered_action> _defered_actions;
};
} // namespace mirrage::util
#include <mirrage/utils/defer.hpp>
namespace mirrage::util {
void Deferred_action_container::defer(util::Time time, std::function<void()> callback)
{
_defered_actions.emplace_back(
[t = _time_since_start + time.value(), this] { return t <= _time_since_start; }, callback);
}
void Deferred_action_container::update(util::Time delta_time)
{
_time_since_start += delta_time.value();
auto new_end = std::partition(
_defered_actions.begin(), _defered_actions.end(), [](auto& a) { return !a.ready(); });
if(new_end != _defered_actions.end()) {
auto saved = std::vector(new_end, _defered_actions.end());
_defered_actions.erase(new_end, _defered_actions.end());
for(auto& a : saved) {
a.callback();
}
}
}
} // namespace mirrage::util
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment