Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
TradeNamePlayback.cpp
Go to the documentation of this file.
2
3#include "FontRuntime.hpp"
6
7#include <string_view>
8#include <utility>
9
10namespace monopoly::tradeui
11{
12 namespace
13 {
14 constexpr std::uint32_t NameWidth = 135;
15 constexpr std::uint32_t NameHeight = 35;
16 // LEG_MCR(220,220,220): COLORREF byte order is R,G,B.
17 constexpr std::uint32_t NameColour = 0x00DCDCDCU;
18
19 [[nodiscard]] data::LegacyBitmapRGBA8 blankImage(int scale)
20 {
21 data::LegacyBitmapRGBA8 image{NameWidth * scale, NameHeight * scale, {}};
22 image.pixels.assign(std::size_t(image.width) * image.height * 4U, 0U);
23 return image;
24 }
25
26 struct RestoreDefaultFont final
27 {
28 fonts::Runtime* runtime{};
29 std::optional<fonts::Settings> caller;
31 {
32 if (runtime != nullptr)
33 {
34 if (!caller) (void)runtime->restoreSettings(0);
35 else
36 {
37 (void)runtime->setSize(caller->size); runtime->setWeight(caller->weight);
38 runtime->setItalic(caller->italic); runtime->setUnderline(caller->underline);
39 runtime->setStrikeOut(caller->strikeOut);
40 }
41 }
42 }
43 };
44 }
45
46 std::expected<void, std::string> NamePlayback::sync(
47 const State& state,
52 {
53 const std::array<rules::PlayerNumber, 2> players{{state.playerA, state.playerB}};
54 std::array<bool, 2> desiredVisible{};
55 for (std::size_t side = 0; side < 2; ++side)
57 players[side] < gameState.numberOfPlayers &&
59
60 const bool anyVisible = desiredVisible[0] || desiredVisible[1];
61 if (anyVisible && (fontRuntime == nullptr || !fontRuntime->ready()))
62 return std::unexpected("Trade name font runtime is unavailable");
63
64 for (std::size_t side = 0; side < 2; ++side)
65 {
66 if (!desiredVisible[side] || surfaces_[side]) continue;
67 const auto created = playback.runtimeBitmaps().create(
68 NameWidth, NameHeight, true);
69 if (!created) return std::unexpected(created.error());
70 surfaces_[side] = *created;
71 }
72
73 std::size_t transitionCount{};
74 for (std::size_t side = 0; side < 2; ++side)
75 if (visible_[side] != desiredVisible[side]) ++transitionCount;
77 playback.commands().pendingCount())
78 return std::unexpected(
79 "sequence command queue cannot fit Trade name transition");
80
81 std::array<bool, 2> contentChanged{};
82 if (anyVisible)
83 {
84 RestoreDefaultFont restore{fontRuntime, modernAA ? std::optional{fontRuntime->settings()} : std::nullopt};
85 const auto sized = fontRuntime->setSize(12);
86 if (!sized) return std::unexpected(sized.error().detail);
87 fontRuntime->setWeight(700);
88 fontRuntime->setUnderline(false);
89 const auto selectedSettings = fontRuntime->settings();
90 const int scale = modernAA ? 3 : 1;
91
92 for (std::size_t side = 0; side < 2; ++side)
93 {
94 if (!desiredVisible[side]) continue;
95 const auto encoded = fonts::transcodeUtf8(
96 std::wstring_view(gameState.players[players[side]].name));
97 if (!encoded) return std::unexpected(encoded.error().detail);
98 const auto& text = *encoded;
99 if (textCache_[side] && *textCache_[side] == text && modernAA_[side] == modernAA &&
100 fontSettings_[side] && *fontSettings_[side] == selectedSettings) continue;
101 auto image = blankImage(scale);
102 if (!text.empty())
103 {
104 if (!modernAA)
105 {
106 const auto blitted = fontRuntime->blitText(image, text, 8, 9, NameColour);
107 if (!blitted) return std::unexpected(blitted.error().detail);
108 }
109 else
110 {
111 const auto enlarged = fontRuntime->setSize(12 * scale);
112 if (!enlarged) return std::unexpected(enlarged.error().detail);
113 const auto raster = fontRuntime->render(text, NameColour, true);
114 const auto native = fontRuntime->setSize(12);
115 if (!native) return std::unexpected(native.error().detail);
116 if (!raster) return std::unexpected(raster.error().detail);
117 const auto blitted = data::blitStraightRGBA8(image, *raster, 8 * scale, 9 * scale, data::BitmapBlitMode::SourceOver);
118 if (!blitted) return std::unexpected(blitted.error());
119 }
120 }
121 const auto updated = playback.runtimeBitmaps().update(
122 *surfaces_[side], std::move(image), modernAA ? std::optional<std::array<float,4>>{{0,0,float(NameWidth),float(NameHeight)}} : std::nullopt, modernAA);
123 if (!updated) return std::unexpected(updated.error());
124 textCache_[side] = text;
125 modernAA_[side] = modernAA;
126 fontSettings_[side] = selectedSettings;
127 contentChanged[side] = true;
128 }
129 }
130
131 for (std::size_t side = 0; side < 2; ++side)
132 {
133 if (visible_[side] == desiredVisible[side])
134 {
135 if (visible_[side] && contentChanged[side])
136 {
137 const auto forced = playback.forceRedraw(
138 *surfaces_[side], TradeNamePriority);
139 if (!forced) return forced;
140 }
141 continue;
142 }
143 if (visible_[side])
144 {
145 if (!playback.commands().enqueue(sequence::StopSequenceCommand{
146 *surfaces_[side], TradeNamePriority, false}))
147 return std::unexpected("validated Trade name stop rejected");
148 }
149 else
150 {
152 *surfaces_[side], data::LegacyDataType::Native);
153 if (!program) return std::unexpected(program.error().detail);
154 if (!playback.commands().enqueue(sequence::StartSequenceCommand{
155 *program, TradeNamePriority, {},
157 return std::unexpected("validated Trade name start rejected");
158 }
159 visible_[side] = desiredVisible[side];
160 }
161 return {};
162 }
163
164 void NamePlayback::reset() noexcept
165 {
166 surfaces_.fill(std::nullopt);
167 textCache_.fill(std::nullopt);
168 visible_.fill(false);
169 modernAA_.fill(false); fontSettings_.fill(std::nullopt);
170 }
171}
std::array< rules::PlayerNumber, rules::MaxPlayers > players
std::string_view text
LegacyBitmapRGBA8 image
fonts::Runtime & runtime
unsigned state
unsigned index
std::optional< fonts::Settings > caller
CardTag native
static std::expected< std::shared_ptr< const SequenceProgram >, RuntimeError > rawBitmap(data::DataId id, data::LegacyDataType sourceType, DescriptionLimits limits={})
std::expected< void, std::string > sync(const State &state, const rules::GameState &gameState, display::Screen2D desiredView, fonts::Runtime *fontRuntime, engine::SequencePlayback &playback, bool modernAA=false)
std::expected< void, std::string > blitStraightRGBA8(LegacyBitmapRGBA8 &destination, const LegacyBitmapRGBA8 &source, std::int32_t destinationX, std::int32_t destinationY, BitmapBlitMode mode)
std::expected< std::string, Error > transcodeUtf8(std::u16string_view text)
constexpr PlayerNumber MaxPlayers
Definition RuleTypes.hpp:14
SequenceTransform moveXYTransform(std::int32_t x, std::int32_t y) noexcept
constexpr std::array< std::int32_t, 2 > TradeNameY
constexpr std::array< std::int32_t, 2 > TradeNameX
constexpr std::uint16_t TradeNamePriority