Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
OptionsNavigationPlayback.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <memory>
5#include <utility>
6#include <variant>
7#include <vector>
8
10{
11 namespace
12 {
13 [[nodiscard]] std::optional<MenuButton> menuForScreen(Screen screen) noexcept
14 {
15 if (screen == Screen::LoadBoard || screen == Screen::LoadGame)
16 return MenuButton::File;
17 const auto value = static_cast<std::uint8_t>(screen);
18 if (value >= static_cast<std::uint8_t>(MenuButton::Count))
19 return std::nullopt;
20 return static_cast<MenuButton>(value);
21 }
22
23 [[nodiscard]] bool anyVisible(
24 const std::array<NavigationVisual, 4>& visual) noexcept
25 {
26 return std::any_of(visual.begin(), visual.end(),
27 [](NavigationVisual value) { return value != NavigationVisual::Off; });
28 }
29 }
30
31 std::expected<void, std::string> NavigationPlayback::sync(
32 const State& state,
35 {
36 const bool visible = desiredView == display::Screen2D::Options && state.active;
37 const bool wasVisible = anyVisible(visual_);
38 const auto desiredSelected = visible ? menuForScreen(state.currentScreen)
39 : std::optional<MenuButton>{};
40
41 auto next = visual_;
42 if (!visible)
43 {
45 }
46 else if (!wasVisible)
47 {
48 for (std::size_t index = 0; index < next.size(); ++index)
50 index == static_cast<std::size_t>(*desiredSelected)
53 }
54 else if (desiredSelected != selected_)
55 {
56 if (selected_)
57 next[static_cast<std::size_t>(*selected_)] = NavigationVisual::Return;
59 next[static_cast<std::size_t>(*desiredSelected)] = NavigationVisual::Press;
60 }
61
62 if (next == visual_)
63 {
64 selected_ = desiredSelected;
65 return {};
66 }
67
68 std::array<std::shared_ptr<const sequence::SequenceProgram>, 4> programs{};
69 for (std::size_t index = 0; index < next.size(); ++index)
70 {
71 if (next[index] == visual_[index] || next[index] == NavigationVisual::Off)
72 continue;
73 const auto button = static_cast<MenuButton>(index);
76 if (!loaded)
77 return std::unexpected(loaded.error().detail);
78 programs[index] = std::move(*loaded);
79 }
80
81 std::vector<sequence::SequenceCommand> commands;
82 for (std::size_t index = 0; index < next.size(); ++index)
83 {
84 if (next[index] == visual_[index])
85 continue;
86
87 const auto button = static_cast<MenuButton>(index);
88 if (visual_[index] != NavigationVisual::Off)
89 {
90 commands.push_back(sequence::StopSequenceCommand{
92 navigationPriority(button, visual_[index]), false});
93 }
94
96 {
97 const auto id = navigationSequence(button, next[index]);
99 commands.push_back(sequence::StartSequenceCommand{
100 programs[index], priority, {}});
101 if (wasVisible &&
104 {
107 }
108 }
109 }
110
111 if (commands.size() > sequence::SequenceCommandQueue::Capacity -
112 playback.commands().pendingCount())
113 {
114 return std::unexpected(
115 "sequence command queue cannot fit Options navigation transition");
116 }
117
118 for (auto& command : commands)
119 {
120 const auto queued = std::visit(
121 [&](auto value)
122 {
123 return playback.commands().enqueue(std::move(value));
124 },
125 std::move(command));
126 if (!queued)
127 return std::unexpected(
128 "validated Options navigation command rejected");
129 }
130
131 visual_ = next;
132 selected_ = desiredSelected;
133 return {};
134 }
135}
data::DataId id
std::uint16_t priority
unsigned state
unsigned index
Button button
std::uint16_t value
Definition Timers.cpp:16
std::expected< void, std::string > sync(const State &state, display::Screen2D desiredView, engine::SequencePlayback &playback)
static std::expected< std::shared_ptr< const SequenceProgram >, RuntimeError > load(const data::DataSource &source, data::DataId id, std::size_t offset=0, DescriptionLimits limits={})
constexpr std::uint8_t NavigationStayAtEnd
constexpr std::uint16_t navigationPriority(MenuButton button, NavigationVisual visual) noexcept
constexpr data::DataId navigationSequence(MenuButton button, NavigationVisual visual) noexcept