OpenRCT2/src/openrct2-ui/windows/TitleMenu.cpp

301 lines
10 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2014-2022 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
2018-06-22 23:21:44 +02:00
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Widget.h>
2022-02-20 20:27:43 +01:00
#include <openrct2-ui/scripting/CustomMenu.h>
2017-08-06 21:20:05 +02:00
#include <openrct2-ui/windows/Window.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/Context.h>
#include <openrct2/Editor.h>
2017-11-30 18:17:06 +01:00
#include <openrct2/Game.h>
2017-12-12 14:52:57 +01:00
#include <openrct2/Input.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/ParkImporter.h>
#include <openrct2/PlatformEnvironment.h>
Split actions hpp files into separate h and cpp files (#13548) * Split up SmallSceneryPlace/Remove Added undo function for Remove Scenery * Refactor: Balloon and Banner actions hpp=>h/cpp * Refactor: rename all action *.hpp files to *.cpp This is preparation for separation in later commits. Note that without the complete set of commits in this branch, the code will not build. * Refactor Clear, Climate, Custom, and Footpath actions hpp=>h/cpp * VSCode: add src subdirectories to includePath * Refactor Guest actions hpp=>h/cpp * Refactor Land actions hpp=>h/cpp * Refactor LargeScenery actions hpp=>h/cpp * Refactor Load, Maze, Network actions hpp=>h/cpp * Refactor Park actions hpp=>h/cpp * Refactor/style: move private function declarations in actions *.h Previous action .h files included private function declarations with private member variables, before public function declarations. This commit re-orders the header files to the following order: - public member variables - private member variables - public functions - private functions * Refactor Pause action hpp=>h/cpp * Refactor Peep, Place, Player actions hpp=>h/cpp * Refactor Ride actions hpp=>h/cpp * Refactor Scenario, Set*, Sign* actions hpp=>h/cpp * Refactor SmallScenerySetColourAction hpp=>h/cpp * Refactor Staff actions hpp=>h/cpp * Refactor Surface, Tile, Track* actions hpp=>h/cpp * Refactor Wall and Water actions hpp=>h/cpp * Fix various includes and other compile errors Update includes for tests. Move static function declarations to .h files Add explicit includes to various files that were previously implicit (the required header was a nested include in an action hpp file, and the action .h file does not include that header) Move RideSetStatus string enum to the cpp file to avoid unused imports * Xcode: modify project file for actions refactor * Cleanup whitespace and end-of-file newlines Co-authored-by: duncanspumpkin <duncans_pumpkin@hotmail.co.uk>
2020-12-10 07:39:10 +01:00
#include <openrct2/actions/LoadOrQuitAction.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/config/Config.h>
2018-01-06 18:32:25 +01:00
#include <openrct2/localisation/Localisation.h>
#include <openrct2/sprites.h>
#include <openrct2/ui/UiContext.h>
// clang-format off
enum {
WIDX_START_NEW_GAME,
WIDX_CONTINUE_SAVED_GAME,
WIDX_MULTIPLAYER,
WIDX_GAME_TOOLS,
WIDX_NEW_VERSION,
};
2022-02-20 20:27:43 +01:00
enum
{
DDIDX_SCENARIO_EDITOR,
DDIDX_CONVERT_SAVED_GAME,
DDIDX_TRACK_DESIGNER,
DDIDX_TRACK_MANAGER,
DDIDX_OPEN_CONTENT_FOLDER,
DDIDX_CUSTOM_BEGIN = 6,
};
static ScreenRect _filterRect;
static constexpr ScreenSize MenuButtonDims = { 82, 82 };
static constexpr ScreenSize UpdateButtonDims = { MenuButtonDims.width * 4, 28 };
static rct_widget window_title_menu_widgets[] = {
MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims, WindowWidgetType::ImgBtn, WindowColour::Tertiary, SPR_MENU_NEW_GAME, STR_START_NEW_GAME_TIP),
MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims, WindowWidgetType::ImgBtn, WindowColour::Tertiary, SPR_MENU_LOAD_GAME, STR_CONTINUE_SAVED_GAME_TIP),
MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims, WindowWidgetType::ImgBtn, WindowColour::Tertiary, SPR_G2_MENU_MULTIPLAYER, STR_SHOW_MULTIPLAYER_TIP),
MakeWidget({0, UpdateButtonDims.height}, MenuButtonDims, WindowWidgetType::ImgBtn, WindowColour::Tertiary, SPR_MENU_TOOLBOX, STR_GAME_TOOLS_TIP),
MakeWidget({0, 0}, UpdateButtonDims, WindowWidgetType::Empty, WindowColour::Secondary, STR_UPDATE_AVAILABLE),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
};
2022-08-21 18:49:23 +02:00
static void WindowTitleMenuMouseup(rct_window *w, WidgetIndex widgetIndex);
static void WindowTitleMenuMousedown(rct_window *w, WidgetIndex widgetIndex, rct_widget* widget);
static void WindowTitleMenuDropdown(rct_window *w, WidgetIndex widgetIndex, int32_t dropdownIndex);
static void WindowTitleMenuCursor(rct_window *w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID *cursorId);
static void WindowTitleMenuInvalidate(rct_window *w);
static void WindowTitleMenuPaint(rct_window *w, rct_drawpixelinfo *dpi);
2014-04-09 15:43:27 +02:00
static WindowEventList window_title_menu_events([](auto& events)
{
events.mouse_up = &WindowTitleMenuMouseup;
events.mouse_down = &WindowTitleMenuMousedown;
events.dropdown = &WindowTitleMenuDropdown;
events.cursor = &WindowTitleMenuCursor;
events.invalidate = &WindowTitleMenuInvalidate;
events.paint = &WindowTitleMenuPaint;
});
// clang-format on
/**
* Creates the window containing the menu buttons on the title screen.
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
*/
rct_window* WindowTitleMenuOpen()
{
rct_window* window;
const uint16_t windowHeight = MenuButtonDims.height + UpdateButtonDims.height;
window = WindowCreate(
ScreenCoordsXY(0, context_get_height() - 182), 0, windowHeight, &window_title_menu_events, WindowClass::TitleMenu,
2018-06-22 23:21:44 +02:00
WF_STICK_TO_BACK | WF_TRANSPARENT | WF_NO_BACKGROUND);
window->widgets = window_title_menu_widgets;
#ifdef DISABLE_NETWORK
window->widgets[WIDX_MULTIPLAYER].type = WindowWidgetType::Empty;
#endif
2022-08-21 18:49:23 +02:00
WidgetIndex i = 0;
int32_t x = 0;
for (rct_widget* widget = window->widgets; widget != &window->widgets[WIDX_NEW_VERSION]; widget++)
2018-06-22 23:21:44 +02:00
{
if (widget->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
widget->left = x;
widget->right = x + MenuButtonDims.width - 1;
x += MenuButtonDims.width;
2018-06-22 23:21:44 +02:00
}
i++;
}
window->width = x;
window->widgets[WIDX_NEW_VERSION].right = window->width;
2020-03-01 20:32:35 +01:00
window->windowPos.x = (context_get_width() - window->width) / 2;
window->colours[1] = TRANSLUCENT(COLOUR_LIGHT_ORANGE);
WindowInitScrollWidgets(*window);
2017-08-06 05:22:00 +02:00
return window;
2014-04-09 15:43:27 +02:00
}
static void WindowTitleMenuScenarioselectCallback(const utf8* path)
{
game_notify_map_change();
OpenRCT2::GetContext()->LoadParkFromFile(path, false, true);
game_load_scripts();
2022-02-20 03:05:24 +01:00
game_notify_map_changed();
}
2022-08-21 18:49:23 +02:00
static void WindowTitleMenuMouseup(rct_window* w, WidgetIndex widgetIndex)
2014-04-09 15:43:27 +02:00
{
2018-06-22 23:21:44 +02:00
rct_window* windowToOpen = nullptr;
switch (widgetIndex)
{
case WIDX_START_NEW_GAME:
windowToOpen = window_find_by_class(WindowClass::ScenarioSelect);
2018-06-22 23:21:44 +02:00
if (windowToOpen != nullptr)
{
window_bring_to_front(*windowToOpen);
2018-06-22 23:21:44 +02:00
}
else
{
window_close_by_class(WindowClass::Loadsave);
window_close_by_class(WindowClass::ServerList);
WindowScenarioselectOpen(WindowTitleMenuScenarioselectCallback, false);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_CONTINUE_SAVED_GAME:
windowToOpen = window_find_by_class(WindowClass::Loadsave);
2018-06-22 23:21:44 +02:00
if (windowToOpen != nullptr)
{
window_bring_to_front(*windowToOpen);
2018-06-22 23:21:44 +02:00
}
else
{
window_close_by_class(WindowClass::ScenarioSelect);
window_close_by_class(WindowClass::ServerList);
2019-02-21 10:34:30 +01:00
auto loadOrQuitAction = LoadOrQuitAction(LoadOrQuitModes::OpenSavePrompt);
GameActions::Execute(&loadOrQuitAction);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_MULTIPLAYER:
windowToOpen = window_find_by_class(WindowClass::ServerList);
2018-06-22 23:21:44 +02:00
if (windowToOpen != nullptr)
{
window_bring_to_front(*windowToOpen);
2018-06-22 23:21:44 +02:00
}
else
{
window_close_by_class(WindowClass::ScenarioSelect);
window_close_by_class(WindowClass::Loadsave);
context_open_window(WindowClass::ServerList);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_NEW_VERSION:
context_open_window_view(WV_NEW_VERSION_INFO);
break;
}
2014-04-09 15:43:27 +02:00
}
2022-08-21 18:49:23 +02:00
static void WindowTitleMenuMousedown(rct_window* w, WidgetIndex widgetIndex, rct_widget* widget)
2014-04-09 15:43:27 +02:00
{
2018-06-22 23:21:44 +02:00
if (widgetIndex == WIDX_GAME_TOOLS)
{
2022-02-20 20:27:43 +01:00
int32_t i = 0;
gDropdownItems[i++].Format = STR_SCENARIO_EDITOR;
gDropdownItems[i++].Format = STR_CONVERT_SAVED_GAME_TO_SCENARIO;
gDropdownItems[i++].Format = STR_ROLLER_COASTER_DESIGNER;
gDropdownItems[i++].Format = STR_TRACK_DESIGNS_MANAGER;
gDropdownItems[i++].Format = STR_OPEN_USER_CONTENT_FOLDER;
#ifdef ENABLE_SCRIPTING
auto hasCustomItems = false;
const auto& customMenuItems = OpenRCT2::Scripting::CustomMenuItems;
if (!customMenuItems.empty())
{
for (const auto& item : customMenuItems)
{
if (item.Kind == OpenRCT2::Scripting::CustomToolbarMenuItemKind::Toolbox)
{
// Add seperator
if (!hasCustomItems)
{
hasCustomItems = true;
gDropdownItems[i++].Format = STR_EMPTY;
}
gDropdownItems[i].Format = STR_STRING;
auto sz = item.Text.c_str();
std::memcpy(&gDropdownItems[i].Args, &sz, sizeof(const char*));
i++;
}
}
}
#endif
int32_t yOffset = 0;
if (i > 5)
{
yOffset = -(widget->height() + 5 + (i * 12));
}
WindowDropdownShowText(
2022-02-20 20:27:43 +01:00
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top + yOffset }, widget->height() + 1,
TRANSLUCENT(w->colours[0]), Dropdown::Flag::StayOpen, i);
}
2014-04-09 15:43:27 +02:00
}
2022-02-20 20:27:43 +01:00
static void InvokeCustomToolboxMenuItem(size_t index)
{
#ifdef ENABLE_SCRIPTING
const auto& customMenuItems = OpenRCT2::Scripting::CustomMenuItems;
size_t i = 0;
for (const auto& item : customMenuItems)
{
if (item.Kind == OpenRCT2::Scripting::CustomToolbarMenuItemKind::Toolbox)
{
if (i == index)
{
item.Invoke();
break;
}
i++;
}
}
#endif
}
2022-08-21 18:49:23 +02:00
static void WindowTitleMenuDropdown(rct_window* w, WidgetIndex widgetIndex, int32_t dropdownIndex)
2014-04-09 15:43:27 +02:00
{
2018-06-22 23:21:44 +02:00
if (widgetIndex == WIDX_GAME_TOOLS)
{
switch (dropdownIndex)
{
2022-02-20 20:27:43 +01:00
case DDIDX_SCENARIO_EDITOR:
2018-06-22 23:21:44 +02:00
Editor::Load();
break;
2022-02-20 20:27:43 +01:00
case DDIDX_CONVERT_SAVED_GAME:
2018-06-22 23:21:44 +02:00
Editor::ConvertSaveToScenario();
break;
2022-02-20 20:27:43 +01:00
case DDIDX_TRACK_DESIGNER:
2018-06-22 23:21:44 +02:00
Editor::LoadTrackDesigner();
break;
2022-02-20 20:27:43 +01:00
case DDIDX_TRACK_MANAGER:
2018-06-22 23:21:44 +02:00
Editor::LoadTrackManager();
break;
2022-02-20 20:27:43 +01:00
case DDIDX_OPEN_CONTENT_FOLDER:
{
auto context = OpenRCT2::GetContext();
2018-09-04 18:05:11 +02:00
auto env = context->GetPlatformEnvironment();
auto uiContext = context->GetUiContext();
uiContext->OpenFolder(env->GetDirectoryPath(OpenRCT2::DIRBASE::USER));
break;
}
2022-02-20 20:27:43 +01:00
default:
InvokeCustomToolboxMenuItem(dropdownIndex - DDIDX_CUSTOM_BEGIN);
break;
}
}
2014-04-09 15:43:27 +02:00
}
static void WindowTitleMenuCursor(
2022-08-21 18:49:23 +02:00
rct_window* w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords, CursorID* cursorId)
2014-04-09 15:43:27 +02:00
{
gTooltipTimeout = 2000;
2014-04-09 15:43:27 +02:00
}
static void WindowTitleMenuInvalidate(rct_window* w)
{
_filterRect = { w->windowPos.x, w->windowPos.y + UpdateButtonDims.height, w->windowPos.x + w->width - 1,
w->windowPos.y + MenuButtonDims.height + UpdateButtonDims.height - 1 };
if (OpenRCT2::GetContext()->HasNewVersionInfo())
{
w->widgets[WIDX_NEW_VERSION].type = WindowWidgetType::Button;
_filterRect.Point1.y = w->windowPos.y;
}
}
static void WindowTitleMenuPaint(rct_window* w, rct_drawpixelinfo* dpi)
2014-04-09 15:43:27 +02:00
{
gfx_filter_rect(dpi, _filterRect, FilterPaletteID::Palette51);
WindowDrawWidgets(*w, dpi);
}