1 /*****************************************************************************
2 * Copyright (c) 2014-2020 OpenRCT2 developers
3 *
4 * For a complete list of all authors, please refer to contributors.md
5 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6 *
7 * OpenRCT2 is licensed under the GNU General Public License version 3.
8 *****************************************************************************/
9
10 #include <openrct2-ui/interface/Dropdown.h>
11 #include <openrct2-ui/interface/Viewport.h>
12 #include <openrct2-ui/interface/Widget.h>
13 #include <openrct2-ui/windows/Window.h>
14 #include <openrct2/Game.h>
15 #include <openrct2/actions/BannerRemoveAction.h>
16 #include <openrct2/actions/BannerSetColourAction.h>
17 #include <openrct2/actions/BannerSetNameAction.h>
18 #include <openrct2/actions/BannerSetStyleAction.h>
19 #include <openrct2/config/Config.h>
20 #include <openrct2/localisation/Localisation.h>
21 #include <openrct2/sprites.h>
22 #include <openrct2/world/Banner.h>
23 #include <openrct2/world/Scenery.h>
24
25 static constexpr const int32_t WW = 113;
26 static constexpr const int32_t WH = 96;
27 static constexpr const rct_string_id WINDOW_TITLE = STR_BANNER_WINDOW_TITLE;
28
29 // clang-format off
30 enum WINDOW_BANNER_WIDGET_IDX {
31 WIDX_BACKGROUND,
32 WIDX_TITLE,
33 WIDX_CLOSE,
34 WIDX_VIEWPORT,
35 WIDX_BANNER_TEXT,
36 WIDX_BANNER_NO_ENTRY,
37 WIDX_BANNER_DEMOLISH,
38 WIDX_MAIN_COLOUR,
39 WIDX_TEXT_COLOUR_DROPDOWN,
40 WIDX_TEXT_COLOUR_DROPDOWN_BUTTON
41 };
42
43 static constexpr const rct_string_id BannerColouredTextFormats[] = {
44 STR_TEXT_COLOR_BLACK,
45 STR_TEXT_COLOR_GREY,
46 STR_TEXT_COLOR_WHITE,
47 STR_TEXT_COLOR_RED,
48 STR_TEXT_COLOR_GREEN,
49 STR_TEXT_COLOR_YELLOW,
50 STR_TEXT_COLOR_TOPAZ,
51 STR_TEXT_COLOR_CELADON,
52 STR_TEXT_COLOR_BABYBLUE,
53 STR_TEXT_COLOR_PALELAVENDER,
54 STR_TEXT_COLOR_PALEGOLD,
55 STR_TEXT_COLOR_LIGHTPINK,
56 STR_TEXT_COLOR_PEARLAQUA,
57 STR_TEXT_COLOR_PALESILVER,
58 };
59
60 static rct_widget window_banner_widgets[] = {
61 WINDOW_SHIM(WINDOW_TITLE, WW, WH),
62 MakeWidget({ 3, 17}, {85, 60}, WindowWidgetType::Viewport, WindowColour::Secondary, 0x0FFFFFFFE ), // tab content panel
63 MakeWidget({WW - 25, 19}, {24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_RENAME, STR_CHANGE_BANNER_TEXT_TIP ), // change banner button
64 MakeWidget({WW - 25, 43}, {24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_NO_ENTRY, STR_SET_AS_NO_ENTRY_BANNER_TIP ), // no entry button
65 MakeWidget({WW - 25, 67}, {24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_DEMOLISH, STR_DEMOLISH_BANNER_TIP ), // demolish button
66 MakeWidget({ 5, WH - 16}, {12, 12}, WindowWidgetType::ColourBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SELECT_MAIN_SIGN_COLOUR_TIP), // high money
67 MakeWidget({ 43, WH - 16}, {39, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary ), // high money
68 MakeWidget({ 70, WH - 15}, {11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_TEXT_COLOUR_TIP ), // high money
69 WIDGETS_END,
70 };
71
72 // clang-format on
73
74 class BannerWindow final : public Window
75 {
76 private:
77 CoordsXYZ _bannerViewPos;
78
CreateViewport()79 void CreateViewport()
80 {
81 rct_widget* viewportWidget = &window_banner_widgets[WIDX_VIEWPORT];
82 viewport_create(
83 this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 },
84 (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, Focus(_bannerViewPos));
85
86 if (viewport != nullptr)
87 viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0;
88 Invalidate();
89 }
90
GetBannerElement()91 BannerElement* GetBannerElement()
92 {
93 auto* banner = GetBanner(number);
94 if (banner == nullptr)
95 {
96 return nullptr;
97 }
98
99 TileElement* tileElement = map_get_first_element_at(banner->position);
100 if (tileElement == nullptr)
101 {
102 return nullptr;
103 }
104
105 do
106 {
107 auto* bannerElement = tileElement->AsBanner();
108 if (bannerElement == nullptr)
109 {
110 continue;
111 }
112 if (bannerElement->GetIndex() == number)
113 {
114 return bannerElement;
115 }
116 } while (!(tileElement++)->IsLastForTile());
117
118 return nullptr;
119 }
120
121 public:
OnOpen()122 void OnOpen() override
123 {
124 widgets = window_banner_widgets;
125 enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_BANNER_TEXT) | (1ULL << WIDX_BANNER_NO_ENTRY)
126 | (1ULL << WIDX_BANNER_DEMOLISH) | (1ULL << WIDX_MAIN_COLOUR) | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN)
127 | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN_BUTTON);
128 WindowInitScrollWidgets(this);
129 }
130
Initialise(rct_windownumber _number)131 void Initialise(rct_windownumber _number)
132 {
133 number = _number;
134 auto* banner = GetBanner(number);
135
136 auto* bannerElement = GetBannerElement();
137 if (bannerElement == nullptr)
138 return;
139
140 _bannerViewPos = CoordsXYZ{ banner->position.ToCoordsXY().ToTileCentre(), bannerElement->GetBaseZ() };
141 CreateViewport();
142 }
143
OnMouseDown(rct_widgetindex widgetIndex)144 void OnMouseDown(rct_widgetindex widgetIndex) override
145 {
146 rct_widget* widget = &widgets[widgetIndex];
147 auto* banner = GetBanner(number);
148 if (banner == nullptr)
149 {
150 Close();
151 return;
152 }
153 switch (widgetIndex)
154 {
155 case WIDX_MAIN_COLOUR:
156 WindowDropdownShowColour(this, widget, TRANSLUCENT(colours[1]), banner->colour);
157 break;
158 case WIDX_TEXT_COLOUR_DROPDOWN_BUTTON:
159
160 for (int32_t i = 0; i < 13; ++i)
161 {
162 gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
163 gDropdownItemsArgs[i] = BannerColouredTextFormats[i + 1];
164 }
165
166 // Switch to the dropdown box widget.
167 widget--;
168
169 WindowDropdownShowTextCustomWidth(
170 { widget->left + windowPos.x, widget->top + windowPos.y }, widget->height() + 1, colours[1], 0,
171 Dropdown::Flag::StayOpen, 13, widget->width() - 3);
172
173 Dropdown::SetChecked(banner->text_colour - 1, true);
174 break;
175 }
176 }
177
OnMouseUp(rct_widgetindex widgetIndex)178 void OnMouseUp(rct_widgetindex widgetIndex) override
179 {
180 auto* banner = GetBanner(number);
181 if (banner == nullptr)
182 {
183 Close();
184 return;
185 }
186 switch (widgetIndex)
187 {
188 case WIDX_CLOSE:
189 Close();
190 break;
191 case WIDX_BANNER_DEMOLISH:
192 {
193 auto* bannerElement = GetBannerElement();
194 if (bannerElement == nullptr)
195 break;
196
197 auto bannerRemoveAction = BannerRemoveAction(
198 { banner->position.ToCoordsXY(), bannerElement->GetBaseZ(), bannerElement->GetPosition() });
199 GameActions::Execute(&bannerRemoveAction);
200 break;
201 }
202 case WIDX_BANNER_TEXT:
203 window_text_input_raw_open(
204 this, WIDX_BANNER_TEXT, STR_BANNER_TEXT, STR_ENTER_BANNER_TEXT, {}, banner->GetText().c_str(), 32);
205 break;
206 case WIDX_BANNER_NO_ENTRY:
207 {
208 textinput_cancel();
209 auto bannerSetStyle = BannerSetStyleAction(
210 BannerSetStyleType::NoEntry, number, banner->flags ^ BANNER_FLAG_NO_ENTRY);
211 GameActions::Execute(&bannerSetStyle);
212 break;
213 }
214 }
215 }
216
OnDropdown(rct_widgetindex widgetIndex,int32_t dropdownIndex)217 void OnDropdown(rct_widgetindex widgetIndex, int32_t dropdownIndex) override
218 {
219 switch (widgetIndex)
220 {
221 case WIDX_MAIN_COLOUR:
222 {
223 if (dropdownIndex == -1)
224 break;
225
226 auto bannerSetStyle = BannerSetStyleAction(BannerSetStyleType::PrimaryColour, number, dropdownIndex);
227 GameActions::Execute(&bannerSetStyle);
228 break;
229 }
230 case WIDX_TEXT_COLOUR_DROPDOWN_BUTTON:
231 {
232 if (dropdownIndex == -1)
233 break;
234 auto bannerSetStyle = BannerSetStyleAction(BannerSetStyleType::TextColour, number, dropdownIndex + 1);
235 GameActions::Execute(&bannerSetStyle);
236 break;
237 }
238 }
239 }
240
OnTextInput(rct_widgetindex widgetIndex,std::string_view text)241 void OnTextInput(rct_widgetindex widgetIndex, std::string_view text) override
242 {
243 if (widgetIndex == WIDX_BANNER_TEXT)
244 {
245 auto bannerSetNameAction = BannerSetNameAction(number, std::string(text));
246 GameActions::Execute(&bannerSetNameAction);
247 }
248 }
249
OnViewportRotate()250 void OnViewportRotate() override
251 {
252 RemoveViewport();
253 CreateViewport();
254 }
255
OnDraw(rct_drawpixelinfo & dpi)256 void OnDraw(rct_drawpixelinfo& dpi) override
257 {
258 DrawWidgets(dpi);
259
260 if (viewport != nullptr)
261 {
262 window_draw_viewport(&dpi, this);
263 }
264 }
265
OnPrepareDraw()266 void OnPrepareDraw() override
267 {
268 auto* banner = GetBanner(number);
269 if (banner == nullptr)
270 {
271 return;
272 }
273 rct_widget* colourBtn = &window_banner_widgets[WIDX_MAIN_COLOUR];
274 colourBtn->type = WindowWidgetType::Empty;
275
276 auto* bannerEntry = get_banner_entry(banner->type);
277 if (bannerEntry != nullptr && (bannerEntry->flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR))
278 {
279 colourBtn->type = WindowWidgetType::ColourBtn;
280 }
281 pressed_widgets &= ~(1ULL << WIDX_BANNER_NO_ENTRY);
282 disabled_widgets &= ~(
283 (1ULL << WIDX_BANNER_TEXT) | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN) | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN_BUTTON));
284 if (banner->flags & BANNER_FLAG_NO_ENTRY)
285 {
286 pressed_widgets |= (1ULL << WIDX_BANNER_NO_ENTRY);
287 disabled_widgets |= (1ULL << WIDX_BANNER_TEXT) | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN)
288 | (1ULL << WIDX_TEXT_COLOUR_DROPDOWN_BUTTON);
289 }
290 colourBtn->image = SPRITE_ID_PALETTE_COLOUR_1(banner->colour) | IMAGE_TYPE_TRANSPARENT | SPR_PALETTE_BTN;
291 rct_widget* dropDownWidget = &window_banner_widgets[WIDX_TEXT_COLOUR_DROPDOWN];
292 dropDownWidget->text = BannerColouredTextFormats[banner->text_colour];
293 }
294 };
295
296 /**
297 *
298 * rct2: 0x006BA305
299 */
window_banner_open(rct_windownumber number)300 rct_window* window_banner_open(rct_windownumber number)
301 {
302 auto w = static_cast<BannerWindow*>(window_bring_to_front_by_number(WC_BANNER, number));
303
304 if (w != nullptr)
305 return w;
306
307 w = WindowCreate<BannerWindow>(WC_BANNER, WW, WH, 0);
308
309 if (w != nullptr)
310 w->Initialise(number);
311
312 return w;
313 }
314