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/Widget.h>
12 #include <openrct2-ui/windows/Window.h>
13 #include <openrct2/Context.h>
14 #include <openrct2/Editor.h>
15 #include <openrct2/Game.h>
16 #include <openrct2/Input.h>
17 #include <openrct2/ParkImporter.h>
18 #include <openrct2/PlatformEnvironment.h>
19 #include <openrct2/actions/LoadOrQuitAction.h>
20 #include <openrct2/config/Config.h>
21 #include <openrct2/localisation/Localisation.h>
22 #include <openrct2/sprites.h>
23 #include <openrct2/ui/UiContext.h>
24 
25 // clang-format off
26 enum {
27     WIDX_START_NEW_GAME,
28     WIDX_CONTINUE_SAVED_GAME,
29     WIDX_MULTIPLAYER,
30     WIDX_GAME_TOOLS,
31     WIDX_NEW_VERSION,
32 };
33 
34 static ScreenRect _filterRect;
35 static constexpr ScreenSize MenuButtonDims = { 82, 82 };
36 static constexpr ScreenSize UpdateButtonDims = { MenuButtonDims.width * 4, 28 };
37 
38 static rct_widget window_title_menu_widgets[] = {
39     MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims,   WindowWidgetType::ImgBtn, WindowColour::Tertiary,  SPR_MENU_NEW_GAME,       STR_START_NEW_GAME_TIP),
40     MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims,   WindowWidgetType::ImgBtn, WindowColour::Tertiary,  SPR_MENU_LOAD_GAME,      STR_CONTINUE_SAVED_GAME_TIP),
41     MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims,   WindowWidgetType::ImgBtn, WindowColour::Tertiary,  SPR_G2_MENU_MULTIPLAYER, STR_SHOW_MULTIPLAYER_TIP),
42     MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims,   WindowWidgetType::ImgBtn, WindowColour::Tertiary,  SPR_MENU_TOOLBOX,        STR_GAME_TOOLS_TIP),
43     MakeWidget({0,                       0}, UpdateButtonDims, WindowWidgetType::Empty,  WindowColour::Secondary, STR_UPDATE_AVAILABLE),
44     WIDGETS_END,
45 };
46 
47 static void window_title_menu_mouseup(rct_window *w, rct_widgetindex widgetIndex);
48 static void window_title_menu_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget* widget);
49 static void window_title_menu_dropdown(rct_window *w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
50 static void window_title_menu_cursor(rct_window *w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID *cursorId);
51 static void window_title_menu_invalidate(rct_window *w);
52 static void window_title_menu_paint(rct_window *w, rct_drawpixelinfo *dpi);
53 
54 static rct_window_event_list window_title_menu_events([](auto& events)
__anone20e383e0202(auto& events) 55 {
56     events.mouse_up = &window_title_menu_mouseup;
57     events.mouse_down = &window_title_menu_mousedown;
58     events.dropdown = &window_title_menu_dropdown;
59     events.cursor = &window_title_menu_cursor;
60     events.invalidate = &window_title_menu_invalidate;
61     events.paint = &window_title_menu_paint;
62 });
63 // clang-format on
64 
65 /**
66  * Creates the window containing the menu buttons on the title screen.
67  *  rct2: 0x0066B5C0 (part of 0x0066B3E8)
68  */
window_title_menu_open()69 rct_window* window_title_menu_open()
70 {
71     rct_window* window;
72 
73     const uint16_t windowHeight = MenuButtonDims.height + UpdateButtonDims.height;
74     window = WindowCreate(
75         ScreenCoordsXY(0, context_get_height() - 182), 0, windowHeight, &window_title_menu_events, WC_TITLE_MENU,
76         WF_STICK_TO_BACK | WF_TRANSPARENT | WF_NO_BACKGROUND);
77 
78     window->widgets = window_title_menu_widgets;
79     window->enabled_widgets
80         = ((1ULL << WIDX_START_NEW_GAME) | (1ULL << WIDX_CONTINUE_SAVED_GAME) |
81 #ifndef DISABLE_NETWORK
82            (1ULL << WIDX_MULTIPLAYER) |
83 #endif
84            (1ULL << WIDX_GAME_TOOLS));
85 
86     rct_widgetindex i = 0;
87     int32_t x = 0;
88     for (rct_widget* widget = window->widgets; widget != &window->widgets[WIDX_NEW_VERSION]; widget++)
89     {
90         if (WidgetIsEnabled(window, i))
91         {
92             widget->left = x;
93             widget->right = x + MenuButtonDims.width - 1;
94 
95             x += MenuButtonDims.width;
96         }
97         else
98         {
99             widget->type = WindowWidgetType::Empty;
100         }
101         i++;
102     }
103     window->width = x;
104     window->widgets[WIDX_NEW_VERSION].right = window->width;
105     window->windowPos.x = (context_get_width() - window->width) / 2;
106     window->colours[1] = TRANSLUCENT(COLOUR_LIGHT_ORANGE);
107 
108     WindowInitScrollWidgets(window);
109 
110     return window;
111 }
112 
window_title_menu_scenarioselect_callback(const utf8 * path)113 static void window_title_menu_scenarioselect_callback(const utf8* path)
114 {
115     context_load_park_from_file(path);
116     game_load_scripts();
117 }
118 
window_title_menu_mouseup(rct_window * w,rct_widgetindex widgetIndex)119 static void window_title_menu_mouseup(rct_window* w, rct_widgetindex widgetIndex)
120 {
121     rct_window* windowToOpen = nullptr;
122 
123     switch (widgetIndex)
124     {
125         case WIDX_START_NEW_GAME:
126             windowToOpen = window_find_by_class(WC_SCENARIO_SELECT);
127             if (windowToOpen != nullptr)
128             {
129                 window_bring_to_front(windowToOpen);
130             }
131             else
132             {
133                 window_close_by_class(WC_LOADSAVE);
134                 window_close_by_class(WC_SERVER_LIST);
135                 window_scenarioselect_open(window_title_menu_scenarioselect_callback, false);
136             }
137             break;
138         case WIDX_CONTINUE_SAVED_GAME:
139             windowToOpen = window_find_by_class(WC_LOADSAVE);
140             if (windowToOpen != nullptr)
141             {
142                 window_bring_to_front(windowToOpen);
143             }
144             else
145             {
146                 window_close_by_class(WC_SCENARIO_SELECT);
147                 window_close_by_class(WC_SERVER_LIST);
148                 auto loadOrQuitAction = LoadOrQuitAction(LoadOrQuitModes::OpenSavePrompt);
149                 GameActions::Execute(&loadOrQuitAction);
150             }
151             break;
152         case WIDX_MULTIPLAYER:
153             windowToOpen = window_find_by_class(WC_SERVER_LIST);
154             if (windowToOpen != nullptr)
155             {
156                 window_bring_to_front(windowToOpen);
157             }
158             else
159             {
160                 window_close_by_class(WC_SCENARIO_SELECT);
161                 window_close_by_class(WC_LOADSAVE);
162                 context_open_window(WC_SERVER_LIST);
163             }
164             break;
165         case WIDX_NEW_VERSION:
166             context_open_window_view(WV_NEW_VERSION_INFO);
167             break;
168     }
169 }
170 
window_title_menu_mousedown(rct_window * w,rct_widgetindex widgetIndex,rct_widget * widget)171 static void window_title_menu_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
172 {
173     if (widgetIndex == WIDX_GAME_TOOLS)
174     {
175         gDropdownItemsFormat[0] = STR_SCENARIO_EDITOR;
176         gDropdownItemsFormat[1] = STR_CONVERT_SAVED_GAME_TO_SCENARIO;
177         gDropdownItemsFormat[2] = STR_ROLLER_COASTER_DESIGNER;
178         gDropdownItemsFormat[3] = STR_TRACK_DESIGNS_MANAGER;
179         gDropdownItemsFormat[4] = STR_OPEN_USER_CONTENT_FOLDER;
180         WindowDropdownShowText(
181             { w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, TRANSLUCENT(w->colours[0]),
182             Dropdown::Flag::StayOpen, 5);
183     }
184 }
185 
window_title_menu_dropdown(rct_window * w,rct_widgetindex widgetIndex,int32_t dropdownIndex)186 static void window_title_menu_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
187 {
188     if (widgetIndex == WIDX_GAME_TOOLS)
189     {
190         switch (dropdownIndex)
191         {
192             case 0:
193                 Editor::Load();
194                 break;
195             case 1:
196                 Editor::ConvertSaveToScenario();
197                 break;
198             case 2:
199                 Editor::LoadTrackDesigner();
200                 break;
201             case 3:
202                 Editor::LoadTrackManager();
203                 break;
204             case 4:
205             {
206                 auto context = OpenRCT2::GetContext();
207                 auto env = context->GetPlatformEnvironment();
208                 auto uiContext = context->GetUiContext();
209                 uiContext->OpenFolder(env->GetDirectoryPath(OpenRCT2::DIRBASE::USER));
210                 break;
211             }
212         }
213     }
214 }
215 
window_title_menu_cursor(rct_window * w,rct_widgetindex widgetIndex,const ScreenCoordsXY & screenCoords,CursorID * cursorId)216 static void window_title_menu_cursor(
217     rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID* cursorId)
218 {
219     gTooltipTimeout = 2000;
220 }
221 
window_title_menu_invalidate(rct_window * w)222 static void window_title_menu_invalidate(rct_window* w)
223 {
224     _filterRect = { w->windowPos.x, w->windowPos.y + UpdateButtonDims.height, w->windowPos.x + w->width - 1,
225                     w->windowPos.y + MenuButtonDims.height + UpdateButtonDims.height - 1 };
226     if (OpenRCT2::GetContext()->HasNewVersionInfo())
227     {
228         w->enabled_widgets |= (1ULL << WIDX_NEW_VERSION);
229         w->widgets[WIDX_NEW_VERSION].type = WindowWidgetType::Button;
230         _filterRect.Point1.y = w->windowPos.y;
231     }
232 }
233 
window_title_menu_paint(rct_window * w,rct_drawpixelinfo * dpi)234 static void window_title_menu_paint(rct_window* w, rct_drawpixelinfo* dpi)
235 {
236     gfx_filter_rect(dpi, _filterRect, FilterPaletteID::Palette51);
237     WindowDrawWidgets(w, dpi);
238 }
239