Fix numerous title sequence editor bugs

* Change how current title sequence is handled. It can either be
previewing a title sequence, or playing the preset.
* LoadMM and LoadRCT1 now save when script is saved.
* No more infinite failing to load loops.
* No more crashing when attempting to display "no save selected" in
title editor.
* Title editor now gracefully fails to preview a title sequence and lets
the user know with a context error.
* When preset title sequence fails to load, the preset will forcibly be
changed to the first sequence to successfully load.

Added changelog entries for last two items.
This commit is contained in:
Robert Jordan 2017-11-02 13:36:37 -04:00 committed by Michael Steenbeek
parent 0b3da4b209
commit d79d2a7503
8 changed files with 123 additions and 64 deletions

View File

@ -58,6 +58,8 @@
- Fix: Infinite loop when removing scenery elements with >127 base height.
- Fix: Ghosting of transparent map elements when the viewport is moved in OpenGL mode.
- Fix: Clear IME buffer after committing composed text.
- Fix: Title sequence editor now gracefully fails to preview a title sequence and lets the user know with an error message.
- Fix: When preset title sequence fails to load, the preset will forcibly be changed to the first sequence to successfully load.
- Improved: [#6186] Transparent menu items now draw properly in OpenGL mode.
- Improved: [#6218] Speed up game start up time by saving scenario index to file.
- Improved: [#6423] Polish is now rendered using the sprite font, rather than TTF.

View File

@ -193,7 +193,6 @@ static rct_widget window_title_editor_widgets[] = {
static size_t _selectedTitleSequence = 0;
static bool _isSequenceReadOnly;
static TitleSequence * _editingTitleSequence = nullptr;
static bool _isSequencePlaying = false;
static const utf8 * _sequenceName;
static utf8 * _renameSavePath = nullptr;
@ -280,21 +279,13 @@ void window_title_editor_open(sint32 tab)
static void window_title_editor_close(rct_window * w)
{
size_t preset = title_get_config_sequence();
title_set_current_sequence(preset, false);
if (!gTestingTitleSequenceInGame)
{
ITitleSequencePlayer * player = window_title_editor_get_player();
player->Begin(preset);
}
gTestingTitleSequenceInGame = false;
title_stop_previewing_sequence();
// Close the related windows
window_close_by_class(WC_TITLE_COMMAND_EDITOR);
FreeTitleSequence(_editingTitleSequence);
_editingTitleSequence = nullptr;
_isSequencePlaying = false;
_sequenceName = nullptr;
SafeFree(_renameSavePath);
@ -343,7 +334,7 @@ static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIn
// Editor tab
//////////////////////////////////////////////////////////////////////////////////////////////////////
case WIDX_TITLE_EDITOR_ADD_SAVE:
if (!_isSequenceReadOnly && !_isSequencePlaying && !commandEditorOpen)
if (!_isSequenceReadOnly && !title_is_previewing_sequence() && !commandEditorOpen)
{
auto intent = Intent(WC_LOADSAVE);
intent.putExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME);
@ -433,7 +424,7 @@ static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIn
case WIDX_TITLE_EDITOR_SKIP_TO:
{
sint32 position = w->selected_list_item;
if (_isSequencePlaying && position != -1 && position < (sint32)_editingTitleSequence->NumCommands)
if (title_is_previewing_sequence() && position != -1 && position < (sint32)_editingTitleSequence->NumCommands)
{
ITitleSequencePlayer * player = window_title_editor_get_player();
title_sequence_player_seek(player, position);
@ -472,7 +463,7 @@ static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIn
}
break;
case WIDX_TITLE_EDITOR_REPLAY:
if (_isSequencePlaying)
if (title_is_previewing_sequence())
{
ITitleSequencePlayer * player = window_title_editor_get_player();
title_sequence_player_reset(player);
@ -480,34 +471,26 @@ static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIn
}
break;
case WIDX_TITLE_EDITOR_STOP:
if (_isSequencePlaying)
if (title_is_previewing_sequence())
{
size_t preset = title_get_config_sequence();
title_set_current_sequence(preset, false);
if (!gTestingTitleSequenceInGame)
{
ITitleSequencePlayer * player = window_title_editor_get_player();
player->Begin(preset);
}
_isSequencePlaying = false;
gTestingTitleSequenceInGame = false;
title_stop_previewing_sequence();
}
break;
case WIDX_TITLE_EDITOR_PLAY:
if (!_isSequencePlaying || _selectedTitleSequence != title_get_current_sequence())
if (!title_is_previewing_sequence() || _selectedTitleSequence != title_get_current_sequence())
{
ITitleSequencePlayer * player = window_title_editor_get_player();
title_set_current_sequence(_selectedTitleSequence, true);
player->Begin((uint32)_selectedTitleSequence);
_isSequencePlaying = true;
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
if (!title_preview_sequence(_selectedTitleSequence))
{
gTestingTitleSequenceInGame = true;
context_show_error(STR_ERR_FAILED_TO_LOAD_TITLE_SEQUENCE, STR_NONE);
}
else if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
{
gPreviewingTitleSequenceInGame = true;
}
}
break;
case WIDX_TITLE_EDITOR_SKIP:
if (_isSequencePlaying)
if (title_is_previewing_sequence())
{
ITitleSequencePlayer * player = window_title_editor_get_player();
sint32 position = title_sequence_player_get_current_position(player) + 1;
@ -830,8 +813,7 @@ static void window_title_editor_invalidate(rct_window * w)
w->disabled_widgets |= (1 << WIDX_TITLE_EDITOR_PLAY);
else
w->disabled_widgets &= ~(1 << WIDX_TITLE_EDITOR_PLAY);
if (!_isSequencePlaying)
if (!title_is_previewing_sequence())
w->disabled_widgets |= (1 << WIDX_TITLE_EDITOR_REPLAY) | (1 << WIDX_TITLE_EDITOR_STOP) | (1 << WIDX_TITLE_EDITOR_SKIP) | (1 << WIDX_TITLE_EDITOR_SKIP_TO);
else
w->disabled_widgets &= ~((1 << WIDX_TITLE_EDITOR_REPLAY) | (1 << WIDX_TITLE_EDITOR_STOP) | (1 << WIDX_TITLE_EDITOR_SKIP) | (1 << WIDX_TITLE_EDITOR_SKIP_TO));
@ -929,7 +911,7 @@ static void window_title_editor_scrollpaint_saves(rct_window * w, rct_drawpixeli
static void window_title_editor_scrollpaint_commands(rct_window * w, rct_drawpixelinfo * dpi)
{
sint32 position = -1;
if (_isSequencePlaying && (uint16)_selectedTitleSequence == title_get_current_sequence())
if (title_is_previewing_sequence() && _selectedTitleSequence == title_get_current_sequence())
{
ITitleSequencePlayer * player = window_title_editor_get_player();
position = title_sequence_player_get_current_position(player);
@ -968,7 +950,10 @@ static void window_title_editor_scrollpaint_commands(rct_window * w, rct_drawpix
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_NO_SAVE;
error = true;
}
set_format_arg(0, uintptr_t, _editingTitleSequence->Saves[command->SaveIndex]);
else
{
set_format_arg(0, uintptr_t, _editingTitleSequence->Saves[command->SaveIndex]);
}
break;
case TITLE_SCRIPT_LOADMM:
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_SFMM;
@ -1087,7 +1072,7 @@ static bool window_title_editor_check_can_edit()
if (_isSequenceReadOnly)
context_show_error(STR_ERROR_CANT_CHANGE_TITLE_SEQUENCE, STR_NONE);
else if (_isSequencePlaying)
else if (title_is_previewing_sequence())
context_show_error(STR_TITLE_EDITOR_ERR_CANT_EDIT_WHILE_PLAYING, STR_TITLE_EDITOR_PRESS_STOP_TO_CONTINUE_EDITING);
else if (commandEditorOpen)
context_show_error(STR_TITLE_EDITOR_ERR_CANT_CHANGE_WHILE_EDITOR_IS_OPEN, STR_NONE);

View File

@ -295,7 +295,7 @@ void game_update()
screenshot_check();
game_handle_keyboard_input();
if (game_is_not_paused() && gTestingTitleSequenceInGame)
if (game_is_not_paused() && gPreviewingTitleSequenceInGame)
{
title_sequence_player_update((ITitleSequencePlayer*)title_get_sequence_player());
}

View File

@ -58,13 +58,41 @@ size_t TitleScreen::GetCurrentSequence()
return _currentSequence;
}
void TitleScreen::SetCurrentSequence(size_t value, bool loadSequence)
bool TitleScreen::PreviewSequence(size_t value)
{
_currentSequence = value;
if (loadSequence)
_previewingSequence = TryLoadSequence(true);
if (_previewingSequence)
{
TryLoadSequence();
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
{
gPreviewingTitleSequenceInGame = true;
}
}
else
{
_currentSequence = title_get_config_sequence();
if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)
{
TryLoadSequence();
}
}
return _previewingSequence;
}
void TitleScreen::StopPreviewingSequence()
{
if (_previewingSequence)
{
_previewingSequence = false;
_currentSequence = title_get_config_sequence();
gPreviewingTitleSequenceInGame = false;
}
}
bool TitleScreen::IsPreviewingSequence()
{
return _previewingSequence;
}
bool TitleScreen::ShouldHideVersionInfo()
@ -154,9 +182,9 @@ void TitleScreen::Update()
gInUpdateCode = false;
}
void TitleScreen::ChangeSequence(size_t preset)
void TitleScreen::ChangePresetSequence(size_t preset)
{
size_t count = title_sequence_manager_get_count();
size_t count = TitleSequenceManager::GetCount();
if (preset >= count)
{
return;
@ -166,7 +194,8 @@ void TitleScreen::ChangeSequence(size_t preset)
SafeFree(gConfigInterface.current_title_sequence_preset);
gConfigInterface.current_title_sequence_preset = _strdup(configId);
_currentSequence = preset;
if (!_previewingSequence)
_currentSequence = preset;
window_invalidate_all();
}
@ -200,13 +229,13 @@ void TitleScreen::TitleInitialise()
seqId = 0;
}
}
title_sequence_change_preset((sint32)seqId);
ChangePresetSequence((sint32)seqId);
TryLoadSequence();
}
void TitleScreen::TryLoadSequence()
bool TitleScreen::TryLoadSequence(bool loadPreview)
{
if (_loadedTitleSequenceId != _currentSequence)
if (_loadedTitleSequenceId != _currentSequence || loadPreview)
{
size_t numSequences = TitleSequenceManager::GetCount();
if (numSequences > 0)
@ -217,20 +246,32 @@ void TitleScreen::TryLoadSequence()
if (_sequencePlayer->Begin(targetSequence) && _sequencePlayer->Update())
{
_loadedTitleSequenceId = targetSequence;
if (targetSequence != _currentSequence && !loadPreview)
{
// Forcefully change the preset to a preset that works.
const utf8 * configId = title_sequence_manager_get_config_id(targetSequence);
SafeFree(gConfigInterface.current_title_sequence_preset);
gConfigInterface.current_title_sequence_preset = _strdup(configId);
}
_currentSequence = targetSequence;
gfx_invalidate_screen();
return;
return true;
}
targetSequence = (targetSequence + 1) % numSequences;
}
while (targetSequence != _currentSequence);
while (targetSequence != _currentSequence && !loadPreview);
}
Console::Error::WriteLine("Unable to play any title sequences.");
_sequencePlayer->Eject();
_currentSequence = SIZE_MAX;
_loadedTitleSequenceId = SIZE_MAX;
game_init_all(150);
if (!loadPreview)
{
game_init_all(150);
}
return false;
}
return true;
}
extern "C"
@ -265,7 +306,7 @@ extern "C"
{
if (_singleton != nullptr)
{
_singleton->ChangeSequence(preset);
_singleton->ChangePresetSequence(preset);
}
}
@ -302,12 +343,30 @@ extern "C"
return result;
}
void title_set_current_sequence(size_t value, bool loadSequence)
bool title_preview_sequence(size_t value)
{
if (_singleton != nullptr)
{
_singleton->SetCurrentSequence(value, loadSequence);
return _singleton->PreviewSequence(value);
}
return false;
}
void title_stop_previewing_sequence()
{
if (_singleton != nullptr)
{
_singleton->StopPreviewingSequence();
}
}
bool title_is_previewing_sequence()
{
if (_singleton != nullptr)
{
return _singleton->IsPreviewingSequence();
}
return false;
}
void DrawOpenRCT2(rct_drawpixelinfo * dpi, sint32 x, sint32 y)

View File

@ -28,7 +28,9 @@ class TitleScreen final
public:
ITitleSequencePlayer * GetSequencePlayer();
size_t GetCurrentSequence();
void SetCurrentSequence(size_t value, bool loadSequence);
bool PreviewSequence(size_t value);
void StopPreviewingSequence();
bool IsPreviewingSequence();
bool ShouldHideVersionInfo();
void SetHideVersionInfo(bool value);
@ -38,16 +40,17 @@ public:
void Load();
void Update();
void CreateWindows();
void ChangeSequence(size_t preset);
void ChangePresetSequence(size_t preset);
private:
ITitleSequencePlayer * _sequencePlayer = nullptr;
size_t _loadedTitleSequenceId = SIZE_MAX;
size_t _currentSequence = SIZE_MAX;
bool _hideVersionInfo = false;
bool _previewingSequence = false;
void TitleInitialise();
void TryLoadSequence();
bool TryLoadSequence(bool loadPreview = false);
};
#endif
@ -63,7 +66,9 @@ extern "C"
void title_set_hide_version_info(bool value);
size_t title_get_config_sequence();
size_t title_get_current_sequence();
void title_set_current_sequence(size_t value, bool loadSequence);
bool title_preview_sequence(size_t value);
void title_stop_previewing_sequence();
bool title_is_previewing_sequence();
void DrawOpenRCT2(rct_drawpixelinfo * dpi, sint32 x, sint32 y);
#ifdef __cplusplus
}

View File

@ -581,6 +581,13 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq)
{
const TitleCommand * command = &seq->Commands[i];
switch (command->Type) {
case TITLE_SCRIPT_LOADMM:
sb.Append("LOADMM");
break;
case TITLE_SCRIPT_LOADRCT1:
String::Format(buffer, sizeof(buffer), "LOADRCT1 %u", command->SaveIndex);
sb.Append(buffer);
break;
case TITLE_SCRIPT_LOAD:
if (command->SaveIndex == 0xFF)
{

View File

@ -159,8 +159,7 @@ public:
}
else
{
SkipToNextLoadCommand();
if (_position == entryPosition)
if (!SkipToNextLoadCommand() || _position == entryPosition)
{
Console::Error::WriteLine("Unable to load any parks from %s.", _sequence->Name);
return false;
@ -234,15 +233,17 @@ private:
}
}
void SkipToNextLoadCommand()
bool SkipToNextLoadCommand()
{
sint32 entryPosition = _position;
const TitleCommand * command;
do
{
IncrementPosition();
command = &_sequence->Commands[_position];
}
while (!TitleSequenceIsLoadCommand(command));
while (!TitleSequenceIsLoadCommand(command) && _position != entryPosition);
return _position != entryPosition;
}
bool ExecuteCommand(const TitleCommand * command)
@ -369,7 +370,7 @@ private:
bool success = false;
try
{
if (gTestingTitleSequenceInGame)
if (gPreviewingTitleSequenceInGame)
{
gLoadKeepWindowsOpen = true;
CloseParkSpecificWindows();
@ -402,7 +403,7 @@ private:
bool success = false;
try
{
if (gTestingTitleSequenceInGame)
if (gPreviewingTitleSequenceInGame)
{
gLoadKeepWindowsOpen = true;
CloseParkSpecificWindows();
@ -543,7 +544,7 @@ ITitleSequencePlayer * CreateTitleSequencePlayer(IScenarioRepository * scenarioR
extern "C"
{
bool gTestingTitleSequenceInGame = false;
bool gPreviewingTitleSequenceInGame = false;
sint32 title_sequence_player_get_current_position(ITitleSequencePlayer * player)
{

View File

@ -46,7 +46,7 @@ extern "C"
{
#endif
// When testing title sequences within a normal game
extern bool gTestingTitleSequenceInGame;
extern bool gPreviewingTitleSequenceInGame;
sint32 title_sequence_player_get_current_position(ITitleSequencePlayer * player);
bool title_sequence_player_begin(ITitleSequencePlayer * player, uint32 titleSequenceId);