OpenRCT2/src/openrct2/title/TitleScreen.cpp

461 lines
12 KiB
C++
Raw Normal View History

/*****************************************************************************
2020-07-21 15:04:34 +02:00
* Copyright (c) 2014-2020 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:15:14 +02:00
#include "TitleScreen.h"
#include "../Context.h"
2018-06-22 23:15:14 +02:00
#include "../Game.h"
#include "../GameState.h"
2018-06-22 23:15:14 +02:00
#include "../Input.h"
2016-12-16 00:16:02 +01:00
#include "../OpenRCT2.h"
#include "../Version.h"
#include "../audio/audio.h"
2018-06-22 23:15:14 +02:00
#include "../config/Config.h"
#include "../core/Console.hpp"
2018-01-05 22:17:33 +01:00
#include "../drawing/Drawing.h"
2018-06-22 23:15:14 +02:00
#include "../interface/Screenshot.h"
2018-01-06 00:45:53 +01:00
#include "../interface/Viewport.h"
2018-01-06 01:05:16 +01:00
#include "../interface/Window.h"
2018-01-06 18:32:25 +01:00
#include "../localisation/Localisation.h"
2021-08-17 05:33:50 +02:00
#include "../network/NetworkBase.h"
2018-06-22 23:15:14 +02:00
#include "../network/network.h"
#include "../scenario/Scenario.h"
#include "../scenario/ScenarioRepository.h"
#include "../ui/UiContext.h"
2019-12-19 20:55:04 +01:00
#include "../util/Util.h"
2018-06-22 23:15:14 +02:00
#include "TitleSequence.h"
#include "TitleSequenceManager.h"
#include "TitleSequencePlayer.h"
using namespace OpenRCT2;
2017-07-23 00:42:14 +02:00
// TODO Remove when no longer required.
bool gPreviewingTitleSequenceInGame;
2018-06-22 23:15:14 +02:00
static TitleScreen* _singleton = nullptr;
2017-07-23 00:42:14 +02:00
TitleScreen::TitleScreen(GameState& gameState)
: _gameState(gameState)
2017-07-23 00:42:14 +02:00
{
_singleton = this;
}
TitleScreen::~TitleScreen()
{
_singleton = nullptr;
}
2018-06-22 23:15:14 +02:00
ITitleSequencePlayer* TitleScreen::GetSequencePlayer()
2017-07-23 00:42:14 +02:00
{
return _sequencePlayer;
}
size_t TitleScreen::GetCurrentSequence()
2017-07-23 00:42:14 +02:00
{
return _currentSequence;
}
bool TitleScreen::PreviewSequence(size_t value)
2017-07-23 00:42:14 +02:00
{
_currentSequence = value;
_previewingSequence = TryLoadSequence(true);
if (_previewingSequence)
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
{
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
{
gPreviewingTitleSequenceInGame = true;
}
}
else
{
_currentSequence = title_get_config_sequence();
if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)
{
TryLoadSequence();
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
}
return _previewingSequence;
}
void TitleScreen::StopPreviewingSequence()
{
if (_previewingSequence)
{
2018-06-22 23:15:14 +02:00
rct_window* mainWindow = window_get_main();
if (mainWindow != nullptr)
{
window_unfollow_sprite(mainWindow);
}
_previewingSequence = false;
_currentSequence = title_get_config_sequence();
gPreviewingTitleSequenceInGame = false;
}
}
bool TitleScreen::IsPreviewingSequence()
{
return _previewingSequence;
2017-07-23 00:42:14 +02:00
}
bool TitleScreen::ShouldHideVersionInfo()
{
return _hideVersionInfo;
}
void TitleScreen::SetHideVersionInfo(bool value)
{
_hideVersionInfo = value;
}
void TitleScreen::Load()
{
log_verbose("TitleScreen::Load()");
if (game_is_paused())
{
pause_toggle();
}
gScreenFlags = SCREEN_FLAGS_TITLE_DEMO;
gScreenAge = 0;
gCurrentLoadedPath = "";
2017-07-23 00:42:14 +02:00
2021-08-17 09:36:18 +02:00
#ifndef DISABLE_NETWORK
2021-08-17 05:33:50 +02:00
GetContext()->GetNetwork().Close();
2021-08-17 09:36:18 +02:00
#endif
OpenRCT2::Audio::StopAll();
GetContext()->GetGameState()->InitAll(150);
2017-07-23 00:42:14 +02:00
viewport_init_all();
2017-08-12 23:06:12 +02:00
context_open_window(WC_MAIN_WINDOW);
2017-07-23 00:42:14 +02:00
CreateWindows();
TitleInitialise();
OpenRCT2::Audio::PlayTitleMusic();
2017-07-23 00:42:14 +02:00
if (gOpenRCT2ShowChangelog)
{
gOpenRCT2ShowChangelog = false;
2017-08-06 05:22:00 +02:00
context_open_window(WC_CHANGELOG);
2017-07-23 00:42:14 +02:00
}
if (_sequencePlayer != nullptr)
{
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
_sequencePlayer->Begin(_currentSequence);
2017-07-23 00:42:14 +02:00
// Force the title sequence to load / update so we
// don't see a blank screen for a split second.
TryLoadSequence();
_sequencePlayer->Update();
}
log_verbose("TitleScreen::Load() finished");
}
void TitleScreen::Update()
{
2017-07-23 00:42:14 +02:00
gInUpdateCode = true;
screenshot_check();
title_handle_keyboard_input();
if (game_is_not_paused())
{
TryLoadSequence();
_sequencePlayer->Update();
int32_t numUpdates = 1;
2018-06-22 23:15:14 +02:00
if (gGameSpeed > 1)
{
2017-07-23 00:42:14 +02:00
numUpdates = 1 << (gGameSpeed - 1);
}
for (int32_t i = 0; i < numUpdates; i++)
2017-07-23 00:42:14 +02:00
{
_gameState.UpdateLogic();
2017-07-23 00:42:14 +02:00
}
update_palette_effects();
// update_weather_animation();
2017-07-23 00:42:14 +02:00
}
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, false);
2017-10-21 17:57:37 +02:00
context_update_map_tooltip();
2017-07-23 00:42:14 +02:00
window_dispatch_update_all();
gSavedAge++;
2017-12-07 22:16:20 +01:00
context_handle_input();
2017-07-23 00:42:14 +02:00
gInUpdateCode = false;
}
void TitleScreen::ChangePresetSequence(size_t preset)
2017-07-23 00:42:14 +02:00
{
size_t count = TitleSequenceManager::GetCount();
2017-10-31 17:57:16 +01:00
if (preset >= count)
2017-07-23 00:42:14 +02:00
{
return;
}
2018-06-22 23:15:14 +02:00
const utf8* configId = title_sequence_manager_get_config_id(preset);
2017-07-23 00:42:14 +02:00
SafeFree(gConfigInterface.current_title_sequence_preset);
gConfigInterface.current_title_sequence_preset = _strdup(configId);
if (!_previewingSequence)
_currentSequence = preset;
2017-07-23 00:42:14 +02:00
window_invalidate_all();
}
/**
2017-07-23 00:42:14 +02:00
* Creates the windows shown on the title screen; New game, load game,
* tutorial, toolbox and exit.
*/
2017-07-23 00:42:14 +02:00
void TitleScreen::CreateWindows()
{
2017-08-06 05:22:00 +02:00
context_open_window(WC_TITLE_MENU);
context_open_window(WC_TITLE_EXIT);
context_open_window(WC_TITLE_OPTIONS);
context_open_window(WC_TITLE_LOGO);
2017-07-23 00:42:14 +02:00
window_resize_gui(context_get_width(), context_get_height());
_hideVersionInfo = false;
}
void TitleScreen::TitleInitialise()
{
if (_sequencePlayer == nullptr)
{
_sequencePlayer = GetContext()->GetUiContext()->GetTitleSequencePlayer();
}
2019-12-19 20:55:04 +01:00
if (gConfigInterface.random_title_sequence)
{
bool RCT1Installed = false, RCT1AAInstalled = false, RCT1LLInstalled = false;
int RCT1Count = 0;
size_t scenarioCount = scenario_repository_get_count();
2020-01-20 22:35:51 +01:00
for (size_t s = 0; s < scenarioCount; s++)
{
if (scenario_repository_get_by_index(s)->source_game == ScenarioSource::RCT1)
2020-01-20 22:35:51 +01:00
{
2019-12-19 20:55:04 +01:00
RCT1Count++;
}
if (scenario_repository_get_by_index(s)->source_game == ScenarioSource::RCT1_AA)
2020-01-20 22:35:51 +01:00
{
2019-12-19 20:55:04 +01:00
RCT1AAInstalled = true;
}
if (scenario_repository_get_by_index(s)->source_game == ScenarioSource::RCT1_LL)
2020-01-20 22:35:51 +01:00
{
2019-12-19 20:55:04 +01:00
RCT1LLInstalled = true;
}
}
2020-01-20 22:35:51 +01:00
// Mega Park can show up in the scenario list even if RCT1 has been uninstalled, so it must be greater than 1
if (RCT1Count > 1)
{
2019-12-19 20:55:04 +01:00
RCT1Installed = true;
}
2020-01-20 22:35:51 +01:00
2019-12-19 20:55:04 +01:00
int32_t random = 0;
bool safeSequence = false;
std::string RCT1String = format_string(STR_TITLE_SEQUENCE_RCT1, nullptr);
std::string RCT1AAString = format_string(STR_TITLE_SEQUENCE_RCT1_AA, nullptr);
std::string RCT1LLString = format_string(STR_TITLE_SEQUENCE_RCT1_AA_LL, nullptr);
2020-01-20 22:35:51 +01:00
// Ensure the random sequence chosen isn't from RCT1 or expansion if the player doesn't have it installed
while (!safeSequence)
{
2019-12-19 20:55:04 +01:00
size_t total = TitleSequenceManager::GetCount();
random = util_rand() % static_cast<int32_t>(total);
2019-12-19 20:55:04 +01:00
const utf8* scName = title_sequence_manager_get_name(random);
safeSequence = true;
2020-01-20 22:35:51 +01:00
if (scName == RCT1String)
{
2019-12-19 20:55:04 +01:00
safeSequence = RCT1Installed;
2020-01-20 22:35:51 +01:00
}
if (scName == RCT1AAString)
{
2019-12-19 20:55:04 +01:00
safeSequence = RCT1AAInstalled;
2020-01-20 22:35:51 +01:00
}
if (scName == RCT1LLString)
{
2019-12-19 20:55:04 +01:00
safeSequence = RCT1LLInstalled;
}
}
ChangePresetSequence(random);
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
size_t seqId = title_get_config_sequence();
if (seqId == SIZE_MAX)
{
seqId = title_sequence_manager_get_index_for_config_id("*OPENRCT2");
if (seqId == SIZE_MAX)
{
seqId = 0;
}
}
ChangePresetSequence(static_cast<int32_t>(seqId));
}
bool TitleScreen::TryLoadSequence(bool loadPreview)
{
if (_loadedTitleSequenceId != _currentSequence || loadPreview)
{
2021-01-28 01:50:30 +01:00
if (_sequencePlayer == nullptr)
{
_sequencePlayer = GetContext()->GetUiContext()->GetTitleSequencePlayer();
}
size_t numSequences = TitleSequenceManager::GetCount();
if (numSequences > 0)
{
size_t targetSequence = _currentSequence;
do
{
if (_sequencePlayer->Begin(targetSequence) && _sequencePlayer->Update())
{
_loadedTitleSequenceId = targetSequence;
if (targetSequence != _currentSequence && !loadPreview)
{
// Forcefully change the preset to a preset that works.
2018-06-22 23:15:14 +02:00
const utf8* configId = title_sequence_manager_get_config_id(targetSequence);
SafeFree(gConfigInterface.current_title_sequence_preset);
gConfigInterface.current_title_sequence_preset = _strdup(configId);
}
2017-07-23 00:42:14 +02:00
_currentSequence = targetSequence;
gfx_invalidate_screen();
return true;
}
targetSequence = (targetSequence + 1) % numSequences;
2018-06-22 23:15:14 +02:00
} while (targetSequence != _currentSequence && !loadPreview);
}
Console::Error::WriteLine("Unable to play any title sequences.");
_sequencePlayer->Eject();
_currentSequence = SIZE_MAX;
_loadedTitleSequenceId = SIZE_MAX;
if (!loadPreview)
{
GetContext()->GetGameState()->InitAll(150);
}
return false;
}
return true;
}
2018-02-01 18:49:14 +01:00
void title_load()
{
2018-02-01 18:49:14 +01:00
if (_singleton != nullptr)
{
2018-02-01 18:49:14 +01:00
_singleton->Load();
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
void title_create_windows()
{
if (_singleton != nullptr)
{
2018-02-01 18:49:14 +01:00
_singleton->CreateWindows();
}
2018-02-01 18:49:14 +01:00
}
2018-06-22 23:15:14 +02:00
void* title_get_sequence_player()
2018-02-01 18:49:14 +01:00
{
2018-06-22 23:15:14 +02:00
void* result = nullptr;
2018-02-01 18:49:14 +01:00
if (_singleton != nullptr)
{
2018-02-01 18:49:14 +01:00
result = _singleton->GetSequencePlayer();
2017-07-23 00:42:14 +02:00
}
2018-02-01 18:49:14 +01:00
return result;
}
2018-02-01 18:49:14 +01:00
void title_sequence_change_preset(size_t preset)
{
if (_singleton != nullptr)
2017-07-23 00:42:14 +02:00
{
2018-02-01 18:49:14 +01:00
_singleton->ChangePresetSequence(preset);
2017-07-23 00:42:14 +02:00
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
bool title_should_hide_version_info()
{
bool result = false;
if (_singleton != nullptr)
2017-07-23 00:42:14 +02:00
{
2018-02-01 18:49:14 +01:00
result = _singleton->ShouldHideVersionInfo();
2017-07-23 00:42:14 +02:00
}
2018-02-01 18:49:14 +01:00
return result;
}
2018-02-01 18:49:14 +01:00
void title_set_hide_version_info(bool value)
{
if (_singleton != nullptr)
2017-07-23 00:42:14 +02:00
{
2018-02-01 18:49:14 +01:00
_singleton->SetHideVersionInfo(value);
2017-07-23 00:42:14 +02:00
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
size_t title_get_config_sequence()
{
return title_sequence_manager_get_index_for_config_id(gConfigInterface.current_title_sequence_preset);
}
Feature: Preview title sequences in-game Title sequences can now be played back in-game, allowing for much easier editing. Improved title sequence playback in general. Clicking play while on a different title sequence will play the new one. Clicking stop will make the title screen go back to the config title sequence. And the closing the title sequence window will also make the game go back to the config title sequence, and reload the sequence if it was modified. Changes made to title sequences in-game are now correctly loaded in the title screen. Starting a title sequence within the editor will now always reset it even if it's the current playing sequence. (Not for playing in the editor though). Get Location in title sequence command editor now has 100% accuracy compared to before where it would usually get some offset value. Added `get_map_coordinates_from_pos_window` which will allow getting the viewport coordinates of a specific window even if the input coordinates are under another window. This has use with getting 2D positions from the main window without the other windows getting in the way. Options window will now always specify the config title sequence in the dropdown and not the current title sequence. Made a global variable `gLoadKeepWindowsOpen`, in game.h to keep windows open when loading a park. When loading a title sequence park in-game. The sequence player will force-close all park-specific windows ahead of time. Skipping while testing title sequences no longer needs to reload the park if the current playback position is already before the target position and ahead of the load position. Added changelog entry.
2017-10-30 12:07:01 +01:00
2018-02-01 18:49:14 +01:00
size_t title_get_current_sequence()
{
size_t result = 0;
if (_singleton != nullptr)
2017-07-23 00:42:14 +02:00
{
2018-02-01 18:49:14 +01:00
result = _singleton->GetCurrentSequence();
2017-07-23 00:42:14 +02:00
}
2018-02-01 18:49:14 +01:00
return result;
}
2018-02-01 18:49:14 +01:00
bool title_preview_sequence(size_t value)
{
if (_singleton != nullptr)
{
2018-02-01 18:49:14 +01:00
return _singleton->PreviewSequence(value);
}
2018-02-01 18:49:14 +01:00
return false;
}
2018-02-01 18:49:14 +01:00
void title_stop_previewing_sequence()
{
if (_singleton != nullptr)
{
2018-02-01 18:49:14 +01:00
_singleton->StopPreviewingSequence();
}
2018-02-01 18:49:14 +01:00
}
2018-02-01 18:49:14 +01:00
bool title_is_previewing_sequence()
{
if (_singleton != nullptr)
2017-07-23 00:42:14 +02:00
{
2018-02-01 18:49:14 +01:00
return _singleton->IsPreviewingSequence();
}
2018-02-01 18:49:14 +01:00
return false;
}
2020-06-21 21:30:58 +02:00
void DrawOpenRCT2(rct_drawpixelinfo* dpi, const ScreenCoordsXY& screenCoords)
2018-02-01 18:49:14 +01:00
{
2020-10-16 01:13:52 +02:00
thread_local std::string buffer;
buffer.clear();
buffer.assign("{OUTLINE}{WHITE}");
2018-02-01 18:49:14 +01:00
// Write name and version information
2020-10-16 01:13:52 +02:00
buffer += gVersionInfoFull;
gfx_draw_string(dpi, screenCoords + ScreenCoordsXY(5, 5 - 13), buffer.c_str(), { COLOUR_BLACK });
2018-02-01 18:49:14 +01:00
// Invalidate screen area
int16_t width = static_cast<int16_t>(gfx_get_string_width(buffer, FontSpriteBase::MEDIUM));
2020-06-21 21:30:58 +02:00
gfx_set_dirty_blocks(
{ screenCoords, screenCoords + ScreenCoordsXY{ width, 30 } }); // 30 is an arbitrary height to catch both strings
2018-02-01 18:49:14 +01:00
// Write platform information
buffer.assign("{OUTLINE}{WHITE}");
buffer.append(OPENRCT2_PLATFORM);
2020-10-16 01:13:52 +02:00
buffer.append(" (");
buffer.append(OPENRCT2_ARCHITECTURE);
buffer.append(")");
gfx_draw_string(dpi, screenCoords + ScreenCoordsXY(5, 5), buffer.c_str(), { COLOUR_BLACK });
}