Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
StatsCalculatorPlayback.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
9namespace monopoly::statsui
10{
11 namespace
12 {
13 [[nodiscard]] constexpr data::DataId mainId(data::DataTag tag) noexcept
14 {
16 }
17
18 [[nodiscard]] constexpr data::DataId languageId(data::DataTag tag) noexcept
19 {
21 }
22
23 [[nodiscard]] std::expected<
24 std::pair<data::DataId, std::shared_ptr<const sequence::SequenceProgram>>,
25 std::string> loadEnter(engine::SequencePlayback& playback)
26 {
27 for (const auto tag : {CalculatorEnterIdleTag,
29 {
30 const auto id = languageId(tag);
31 auto loaded = sequence::SequenceProgram::load(playback.resources(), id);
32 if (loaded)
33 return std::pair{id, std::move(*loaded)};
34 }
35 return std::unexpected(
36 "UDStats calculator Enter sequence missing from language bank");
37 }
38 }
39
41 {
42 published_.fill(std::nullopt);
43 visible_ = false;
44 }
45
46 std::expected<void, std::string> CalculatorPlayback::sync(
50 {
52 std::array<std::optional<Published>, SlotCount> desired{};
53 std::array<std::optional<sequence::SequenceTransform>, SlotCount>
55 std::optional<std::pair<data::DataId,
56 std::shared_ptr<const sequence::SequenceProgram>>> enterProgram;
58 {
61 desired[1] = Published{mainId(CalculatorTextBoxTag),
63
64 const bool numberButtonsVisible =
67 {
68 for (std::size_t index = 0; index < 10; ++index)
69 {
70 const auto base = ui.pressedNumber && *ui.pressedNumber == index
73 desired[2 + index] = Published{mainId(
74 static_cast<data::DataTag>(base + index)),
76 }
77
79 if (published_[12])
80 enterId = published_[12]->id;
81 else
82 {
84 if (!loaded) return std::unexpected(loaded.error());
85 enterProgram = std::move(*loaded);
86 enterId = enterProgram->first;
87 }
89 }
90
91 for (std::size_t index = 0; index < 8; ++index)
92 {
93 const bool pressed = ui.activeFunction &&
94 static_cast<std::uint8_t>(*ui.activeFunction) == index;
95 const auto base = pressed
98 desired[13 + index] = Published{mainId(
99 static_cast<data::DataTag>(base + index)),
101 }
102
104 {
105 const auto count = std::min<std::size_t>(
106 gameState.numberOfPlayers, rules::MaxPlayers);
107 for (std::size_t index = 0; index < count; ++index)
108 {
109 const auto token = gameState.players[index].token;
110 if (token >= rules::MaxTokens)
111 return std::unexpected(
112 "UDStats calculator token index is out of range");
113 const auto slot = 21 + index;
114 desired[slot] = Published{mainId(static_cast<data::DataTag>(
116 const auto rect = calculatorTokenRect(
117 static_cast<rules::PlayerNumber>(index));
120 rect.left, rect.top, CalculatorTokenScale, 0.0F)};
121 }
122 }
123 }
124
125 std::array<std::shared_ptr<const sequence::SequenceProgram>, SlotCount> programs{};
126 std::size_t commandCount{};
127 for (std::size_t slot = 0; slot < SlotCount; ++slot)
128 {
129 if (published_[slot] == desired[slot]) continue;
130 if (published_[slot]) ++commandCount;
131 if (!desired[slot]) continue;
132
133 if (slot == 12 && enterProgram)
134 programs[slot] = enterProgram->second;
135 else
136 {
138 playback.resources(), desired[slot]->id);
139 if (!loaded)
140 return std::unexpected(
141 "UDStats calculator sequence failed: " + loaded.error().detail);
142 programs[slot] = std::move(*loaded);
143 }
144 ++commandCount;
145 }
146
148 playback.commands().pendingCount())
149 {
150 return std::unexpected(
151 "sequence command queue cannot fit UDStats calculator transition");
152 }
153
154 std::vector<sequence::SequenceCommand> commands;
155 commands.reserve(commandCount);
156 for (std::size_t slot = 0; slot < SlotCount; ++slot)
157 {
158 if (published_[slot] == desired[slot]) continue;
159 if (published_[slot])
160 commands.push_back(sequence::StopSequenceCommand{
161 published_[slot]->id, published_[slot]->priority, false});
162 if (desired[slot])
163 commands.push_back(sequence::StartSequenceCommand{
166 }
167
168 for (auto& command : commands)
169 {
170 const auto queued = std::visit(
171 [&](auto value)
172 {
173 return playback.commands().enqueue(std::move(value));
174 }, std::move(command));
175 if (!queued)
176 return std::unexpected(
177 "validated UDStats calculator command rejected");
178 }
179
180 published_ = desired;
181 visible_ = desiredVisible;
182 return {};
183 }
184}
std::size_t count
data::DataId id
PlayerNumber slot
unsigned index
int token
Rect rect
std::uint16_t value
Definition Timers.cpp:16
static std::expected< std::shared_ptr< const SequenceProgram >, RuntimeError > load(const data::DataSource &source, data::DataId id, std::size_t offset=0, DescriptionLimits limits={})
std::expected< void, std::string > sync(display::Screen2D desiredView, const CalculatorUIState &ui, const rules::GameState &gameState, engine::SequencePlayback &playback)
std::uint32_t DataId
Definition DataBanks.hpp:10
std::uint16_t DataTag
Definition DataBanks.hpp:11
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept
Definition DataBanks.hpp:39
std::uint8_t PlayerNumber
Definition RuleTypes.hpp:12
constexpr std::size_t MaxTokens
Definition RuleTypes.hpp:30
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
std::variant< std::monostate, Matrix2D, Matrix3D > SequenceTransform
Matrix2D moveXYSRTransform(std::int32_t x, std::int32_t y, float scale, float rotate) noexcept
constexpr std::uint16_t CalculatorBackgroundPriority
constexpr data::DataTag CalculatorNumberPressBaseTag
constexpr std::uint16_t CalculatorButtonPriority
constexpr data::DataTag CalculatorTokenBaseTag
constexpr Rect calculatorTokenRect(rules::PlayerNumber player) noexcept
constexpr data::DataTag CalculatorFunctionPressBaseTag
constexpr data::DataTag CalculatorEnterIdleAlternateTag
constexpr data::DataTag CalculatorFunctionIdleBaseTag
constexpr data::DataTag CalculatorBackgroundTag
constexpr data::DataTag CalculatorEnterIdleTag
constexpr float CalculatorTokenScale
constexpr data::DataTag CalculatorNumberIdleBaseTag
constexpr data::DataTag CalculatorTextBoxTag
std::optional< std::uint8_t > pressedNumber
std::optional< CalculatorFunction > activeFunction