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 "../../Game.h"
11 #include "../../config/Config.h"
12 #include "../../interface/Viewport.h"
13 #include "../../localisation/Localisation.h"
14 #include "../../ride/TrackDesign.h"
15 #include "../../sprites.h"
16 #include "../../world/Banner.h"
17 #include "../../world/Scenery.h"
18 #include "../../world/TileInspector.h"
19 #include "../Paint.h"
20 #include "Paint.TileElement.h"
21
22 /** rct2: 0x0098D884 */
23 // BannerBoundBoxes[rotation][0] is for the pole in the back
24 // BannerBoundBoxes[rotation][1] is for the pole and the banner in the front
25 constexpr CoordsXY BannerBoundBoxes[][2] = {
26 { { 1, 2 }, { 1, 29 } },
27 { { 2, 32 }, { 29, 32 } },
28 { { 32, 2 }, { 32, 29 } },
29 { { 2, 1 }, { 29, 1 } },
30 };
31
32 /**
33 *
34 * rct2: 0x006B9CC4
35 */
PaintBanner(paint_session * session,uint8_t direction,int32_t height,const BannerElement & bannerElement)36 void PaintBanner(paint_session* session, uint8_t direction, int32_t height, const BannerElement& bannerElement)
37 {
38 rct_drawpixelinfo* dpi = &session->DPI;
39
40 session->InteractionType = ViewportInteractionItem::Banner;
41
42 if (dpi->zoom_level > 1 || gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
43 return;
44
45 height -= 16;
46
47 auto banner = bannerElement.GetBanner();
48 if (banner == nullptr)
49 {
50 return;
51 }
52
53 auto* bannerEntry = get_banner_entry(banner->type);
54 if (bannerEntry == nullptr)
55 {
56 return;
57 }
58
59 direction += bannerElement.GetPosition();
60 direction &= 3;
61
62 CoordsXYZ boundBoxOffset = CoordsXYZ(BannerBoundBoxes[direction][0], height + 2);
63
64 uint32_t base_id = (direction << 1) + bannerEntry->image;
65 uint32_t image_id = base_id;
66
67 if (bannerElement.IsGhost()) // if being placed
68 {
69 session->InteractionType = ViewportInteractionItem::None;
70 image_id |= CONSTRUCTION_MARKER;
71 }
72 else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&bannerElement)))
73 {
74 image_id |= CONSTRUCTION_MARKER;
75 }
76 else
77 {
78 image_id |= (banner->colour << 19) | IMAGE_TYPE_REMAP;
79 }
80
81 PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 1, 1, 0x15 }, boundBoxOffset);
82 boundBoxOffset.x = BannerBoundBoxes[direction][1].x;
83 boundBoxOffset.y = BannerBoundBoxes[direction][1].y;
84
85 image_id++;
86 PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 1, 1, 0x15 }, boundBoxOffset);
87
88 // Opposite direction
89 direction = direction_reverse(direction);
90 direction--;
91 // If text not showing / ghost
92 if (direction >= 2 || (bannerElement.IsGhost()))
93 return;
94
95 uint16_t scrollingMode = bannerEntry->scrolling_mode;
96 if (scrollingMode >= MAX_SCROLLING_TEXT_MODES)
97 {
98 return;
99 }
100
101 scrollingMode += direction;
102
103 auto ft = Formatter();
104 banner->FormatTextTo(ft, /*addColour*/ true);
105
106 if (gConfigGeneral.upper_case_banners)
107 {
108 format_string_to_upper(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
109 }
110 else
111 {
112 format_string(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
113 }
114
115 uint16_t string_width = gfx_get_string_width(gCommonStringFormatBuffer, FontSpriteBase::TINY);
116 uint16_t scroll = (gCurrentTicks / 2) % string_width;
117 auto scrollIndex = scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode, COLOUR_BLACK);
118 PaintAddImageAsChild(
119 session, scrollIndex, 0, 0, 1, 1, 0x15, height + 22, boundBoxOffset.x, boundBoxOffset.y, boundBoxOffset.z);
120 }
121