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

1178 lines
50 KiB
C++
Raw Normal View History

2015-06-24 18:22:12 +02:00
/*****************************************************************************
* Copyright (c) 2014-2019 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.
*****************************************************************************/
2015-06-24 18:22:12 +02:00
2018-06-22 23:21:44 +02:00
#include "../title/TitleSequencePlayer.h"
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Context.h>
2017-09-10 11:02:16 +02:00
#include <openrct2/FileClassifier.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/Game.h>
#include <openrct2/Input.h>
2017-09-10 11:02:16 +02:00
#include <openrct2/OpenRCT2.h>
#include <openrct2/ParkImporter.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/config/Config.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/scenario/Scenario.h>
#include <openrct2/scenario/ScenarioRepository.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/sprites.h>
2017-09-10 11:02:16 +02:00
#include <openrct2/title/TitleScreen.h>
#include <openrct2/title/TitleSequence.h>
#include <openrct2/title/TitleSequenceManager.h>
#include <openrct2/title/TitleSequencePlayer.h>
2017-12-13 13:02:24 +01:00
#include <openrct2/util/Util.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/windows/Intent.h>
2015-06-24 18:22:12 +02:00
// clang-format off
2016-12-05 03:21:54 +01:00
enum WINDOW_TITLE_EDITOR_TAB {
WINDOW_TITLE_EDITOR_TAB_PRESETS,
WINDOW_TITLE_EDITOR_TAB_SAVES,
WINDOW_TITLE_EDITOR_TAB_SCRIPT,
WINDOW_TITLE_EDITOR_TAB_COUNT
2016-12-05 03:21:54 +01:00
};
2015-06-24 18:22:12 +02:00
static void window_title_editor_close(rct_window * w);
static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIndex);
static void window_title_editor_resize(rct_window * w);
static void window_title_editor_mousedown(rct_window * w, rct_widgetindex widgetIndex, rct_widget * widget);
static void window_title_editor_dropdown(rct_window * w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
static void window_title_editor_update(rct_window * w);
static void window_title_editor_scrollgetsize(rct_window * w, int32_t scrollIndex, int32_t * width, int32_t * height);
static void window_title_editor_scrollmousedown(rct_window * w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
static void window_title_editor_scrollmouseover(rct_window * w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
static void window_title_editor_textinput(rct_window * w, rct_widgetindex widgetIndex, char * text);
static void window_title_editor_invalidate(rct_window * w);
static void window_title_editor_paint(rct_window * w, rct_drawpixelinfo * dpi);
static void window_title_editor_scrollpaint(rct_window * w, rct_drawpixelinfo * dpi, int32_t scrollIndex);
static void window_title_editor_scrollpaint_saves(rct_window * w, rct_drawpixelinfo * dpi);
static void window_title_editor_scrollpaint_commands(rct_window * w, rct_drawpixelinfo * dpi);
static void window_title_editor_draw_tab_images(rct_drawpixelinfo * dpi, rct_window * w);
2016-11-27 15:47:02 +01:00
static void window_title_editor_load_sequence(size_t index);
2016-11-26 16:32:49 +01:00
static ITitleSequencePlayer * window_title_editor_get_player();
2016-11-27 15:47:02 +01:00
static bool window_title_editor_check_can_edit();
static void window_title_editor_add_park_callback(int32_t result, const utf8 * path);
2016-12-07 13:00:02 +01:00
static void window_title_editor_rename_park(size_t index, const utf8 * name);
2015-06-24 18:22:12 +02:00
static rct_window_event_list window_title_editor_events = {
window_title_editor_close,
window_title_editor_mouseup,
window_title_editor_resize,
window_title_editor_mousedown,
window_title_editor_dropdown,
2017-08-15 10:07:44 +02:00
nullptr,
window_title_editor_update,
2017-08-15 10:07:44 +02:00
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_title_editor_scrollgetsize,
window_title_editor_scrollmousedown,
2017-08-15 10:07:44 +02:00
nullptr,
window_title_editor_scrollmouseover,
window_title_editor_textinput,
2017-08-15 10:07:44 +02:00
nullptr,
nullptr,
2018-08-04 16:24:24 +02:00
nullptr,
2017-08-15 10:07:44 +02:00
nullptr,
nullptr,
window_title_editor_invalidate,
window_title_editor_paint,
window_title_editor_scrollpaint,
2015-06-24 18:22:12 +02:00
};
enum WINDOW_TITLE_EDITOR_WIDGET_IDX {
WIDX_TITLE_EDITOR_BACKGROUND,
WIDX_TITLE_EDITOR_TITLE,
WIDX_TITLE_EDITOR_CLOSE,
WIDX_TITLE_EDITOR_TAB_CONTENT_PANEL,
WIDX_TITLE_EDITOR_PRESETS_TAB,
WIDX_TITLE_EDITOR_SAVES_TAB,
WIDX_TITLE_EDITOR_SCRIPT_TAB,
WIDX_TITLE_EDITOR_LIST,
// Presets Tab
WIDX_TITLE_EDITOR_PRESETS,
WIDX_TITLE_EDITOR_PRESETS_DROPDOWN,
WIDX_TITLE_EDITOR_NEW_BUTTON,
WIDX_TITLE_EDITOR_DUPLICATE_BUTTON,
WIDX_TITLE_EDITOR_DELETE_BUTTON,
WIDX_TITLE_EDITOR_RENAME_BUTTON,
// Saves Tab
WIDX_TITLE_EDITOR_ADD_SAVE,
WIDX_TITLE_EDITOR_REMOVE_SAVE,
WIDX_TITLE_EDITOR_RENAME_SAVE,
WIDX_TITLE_EDITOR_LOAD_SAVE,
// Script Tab
WIDX_TITLE_EDITOR_INSERT,
WIDX_TITLE_EDITOR_EDIT,
WIDX_TITLE_EDITOR_DELETE,
//WIDX_TITLE_EDITOR_RELOAD,
WIDX_TITLE_EDITOR_SKIP_TO,
WIDX_TITLE_EDITOR_MOVE_DOWN,
WIDX_TITLE_EDITOR_MOVE_UP,
WIDX_TITLE_EDITOR_REPLAY,
WIDX_TITLE_EDITOR_STOP,
WIDX_TITLE_EDITOR_PLAY,
WIDX_TITLE_EDITOR_SKIP,
2015-06-24 18:22:12 +02:00
};
// Increase BW if certain languages do not fit
2015-06-24 18:22:12 +02:00
// BW should be a multiple of 4
2020-05-09 17:05:01 +02:00
static constexpr const int32_t WW = 320;
static constexpr const int32_t WH = 270;
2019-10-24 05:38:13 +02:00
constexpr int32_t BX = 8;
constexpr int32_t BW = 72;
constexpr int32_t BY = 52;
constexpr int32_t BH = 63;
constexpr int32_t BS = 18;
constexpr int32_t SCROLL_WIDTH = 350;
2020-05-09 17:05:01 +02:00
static constexpr const int32_t WH2 = 127;
2015-06-24 18:22:12 +02:00
static rct_widget window_title_editor_widgets[] = {
{ WWT_FRAME, 0, 0, WW-1, 0, WH2-1, 0xFFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, WW-2, 1, 14, STR_TITLE_EDITOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, WW-13, WW-3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close button
{ WWT_RESIZE, 1, 0, WW-1, 43, WH2-1, 0xFFFFFFFF, STR_NONE }, // tab content panel
{ WWT_TAB, 1, 3, 33, 17, 43, IMAGE_TYPE_REMAP | SPR_TAB, STR_THEMES_TAB_SETTINGS_TIP }, // presets tab
{ WWT_TAB, 1, 34, 64, 17, 43, IMAGE_TYPE_REMAP | SPR_TAB, STR_TITLE_EDITOR_SAVES_TAB_TIP }, // saves tab
{ WWT_TAB, 1, 65, 95, 17, 43, IMAGE_TYPE_REMAP | SPR_TAB, STR_TITLE_EDITOR_SCRIPT_TAB_TIP }, // script tab
{ WWT_SCROLL, 1, BX+BW+9,WW-4, 48, WH-4, SCROLL_BOTH, STR_NONE }, // command/save list
// Presets Tab
{ WWT_DROPDOWN, 1, 125, 299, 60, 71, STR_NONE, STR_NONE }, // Preset title sequences
{ WWT_BUTTON, 1, 288, 298, 61, 70, STR_DROPDOWN_GLYPH, STR_NONE },
{ WWT_BUTTON, 1, 10, 100, 82, 93, STR_TITLE_EDITOR_ACTION_CREATE, STR_TITLE_EDITOR_ACTION_CREATE_SEQUENCE_TIP }, // Create button
{ WWT_BUTTON, 1, 10, 100, 82+20, 93+20, STR_TITLE_EDITOR_ACTION_DUPLICATE, STR_TITLE_EDITOR_ACTION_DUPLICATE_SEQUENCE_TIP }, // Duplicate button
{ WWT_BUTTON, 1, 110, 200, 82, 93, STR_TRACK_MANAGE_DELETE, STR_TITLE_EDITOR_ACTION_DELETE_SEQUENCE_TIP }, // Delete button
{ WWT_BUTTON, 1, 210, 300, 82, 93, STR_TRACK_MANAGE_RENAME, STR_TITLE_EDITOR_ACTION_RENAME_SEQUENCE_TIP }, // Rename button
// Saves Tab
{ WWT_BUTTON, 1, BX, BX+BW-1,BY, BH, STR_TITLE_EDITOR_ACTION_ADD, STR_TITLE_EDITOR_ACTION_ADD_TIP }, // Add
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*1), BH+(BS*1), STR_TITLE_EDITOR_ACTION_REMOVE, STR_TITLE_EDITOR_ACTION_REMOVE_TIP }, // Remove
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*2), BH+(BS*2), STR_TRACK_MANAGE_RENAME, STR_TITLE_EDITOR_ACTION_RENAME_TIP }, // Rename
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*3), BH+(BS*3), STR_TITLE_EDITOR_ACTION_LOAD, STR_TITLE_EDITOR_ACTION_LOAD_TIP }, // Load
// Script Tab
{ WWT_BUTTON, 1, BX, BX+BW-1,BY, BH, STR_TITLE_EDITOR_ACTION_INSERT, STR_TITLE_EDITOR_ACTION_INSERT_TIP }, // Insert
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*1), BH+(BS*1), STR_TITLE_EDITOR_ACTION_EDIT, STR_TITLE_EDITOR_ACTION_EDIT_TIP }, // Edit
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*2), BH+(BS*2), STR_TRACK_MANAGE_DELETE, STR_TITLE_EDITOR_ACTION_DELETE_TIP }, // Delete
//{ WWT_DROPDOWN_BUTTON, 1, BX, BX+BW-1,BY+(BS*3), BH+(BS*3), STR_TITLE_EDITOR_ACTION_RELOAD, STR_TITLE_EDITOR_ACTION_RELOAD_TIP }, // Reload
{ WWT_BUTTON, 1, BX, BX+BW-1,BY+(BS*3), BH+(BS*3), STR_TITLE_EDITOR_ACTION_SKIP_TO, STR_TITLE_EDITOR_ACTION_SKIP_TO_TIP }, // Skip to
{ WWT_BUTTON, 1, BX, BX+BW/2-1,BY+(BS*5),BH+(BS*5), STR_DOWN, STR_TITLE_EDITOR_ACTION_MOVE_DOWN_TIP }, // Move down
{ WWT_BUTTON, 1, BX+BW/2,BX+BW-1,BY+(BS*5), BH+(BS*5), STR_UP, STR_TITLE_EDITOR_ACTION_MOVE_UP_TIP }, // Move up
{ WWT_IMGBTN, 1, BX, BX+BW/4-1, WH-32, WH-16, SPR_G2_TITLE_RESTART, STR_TITLE_EDITOR_ACTION_REPLAY_TIP }, // Replay
{ WWT_IMGBTN, 1, BX+BW/4,BX+BW/2-1, WH-32, WH-16, SPR_G2_TITLE_STOP, STR_TITLE_EDITOR_ACTION_STOP_TIP }, // Stop
{ WWT_IMGBTN, 1, BX+BW/2,BX+BW*3/4-1,WH-32, WH-16, SPR_G2_TITLE_PLAY, STR_TITLE_EDITOR_ACTION_PLAY_TIP }, // Play
{ WWT_IMGBTN, 1, BX+BW*3/4,BX+BW, WH-32, WH-16, SPR_G2_TITLE_SKIP, STR_TITLE_EDITOR_ACTION_SKIP_TIP }, // Skip
{ WIDGETS_END },
2015-06-24 18:22:12 +02:00
};
static size_t _selectedTitleSequence = SIZE_MAX;
2016-11-27 15:47:02 +01:00
static bool _isSequenceReadOnly;
2017-08-15 10:07:44 +02:00
static TitleSequence * _editingTitleSequence = nullptr;
2016-11-27 15:47:02 +01:00
static const utf8 * _sequenceName;
2017-08-15 10:07:44 +02:00
static utf8 * _renameSavePath = nullptr;
static int16_t _window_title_editor_highlighted_index;
static int32_t window_title_editor_tab_animation_loops[] = {
64,
1,
28
2015-06-24 18:22:12 +02:00
};
static int32_t window_title_editor_tab_animation_divisor[] = {
4,
1,
4
2015-06-24 18:22:12 +02:00
};
static int32_t window_title_editor_tab_sprites[] = {
SPR_TAB_RIDE_0,
SPR_FLOPPY,
SPR_TAB_STATS_0
2015-06-24 18:22:12 +02:00
};
// clang-format on
2015-06-24 18:22:12 +02:00
void window_title_editor_open(int32_t tab)
2015-06-24 18:22:12 +02:00
{
2018-06-22 23:21:44 +02:00
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_class(WC_TITLE_EDITOR);
2017-08-15 10:07:44 +02:00
if (window != nullptr)
return;
if (_selectedTitleSequence == SIZE_MAX)
_selectedTitleSequence = title_get_config_sequence();
window = window_create_auto_pos(WW, WH2, &window_title_editor_events, WC_TITLE_EDITOR, WF_10 | WF_RESIZABLE);
window->widgets = window_title_editor_widgets;
2018-06-22 23:21:44 +02:00
window->enabled_widgets = (1 << WIDX_TITLE_EDITOR_CLOSE) | (1 << WIDX_TITLE_EDITOR_PRESETS_TAB)
| (1 << WIDX_TITLE_EDITOR_SAVES_TAB) | (1 << WIDX_TITLE_EDITOR_SCRIPT_TAB) |
(1 << WIDX_TITLE_EDITOR_PRESETS) | (1 << WIDX_TITLE_EDITOR_PRESETS_DROPDOWN) | (1 << WIDX_TITLE_EDITOR_NEW_BUTTON)
| (1 << WIDX_TITLE_EDITOR_DUPLICATE_BUTTON) | (1 << WIDX_TITLE_EDITOR_DELETE_BUTTON)
| (1 << WIDX_TITLE_EDITOR_RENAME_BUTTON) |
(1 << WIDX_TITLE_EDITOR_ADD_SAVE) | (1 << WIDX_TITLE_EDITOR_REMOVE_SAVE) | (1 << WIDX_TITLE_EDITOR_RENAME_SAVE)
| (1 << WIDX_TITLE_EDITOR_LOAD_SAVE) |
(1 << WIDX_TITLE_EDITOR_INSERT) | (1 << WIDX_TITLE_EDITOR_EDIT) | (1 << WIDX_TITLE_EDITOR_DELETE) |
//(1 << WIDX_TITLE_EDITOR_RELOAD) |
2018-06-22 23:21:44 +02:00
(1 << WIDX_TITLE_EDITOR_SKIP_TO) | (1 << WIDX_TITLE_EDITOR_MOVE_DOWN) | (1 << WIDX_TITLE_EDITOR_MOVE_UP) |
2018-06-22 23:21:44 +02:00
(1 << WIDX_TITLE_EDITOR_PLAY) | (1 << WIDX_TITLE_EDITOR_STOP) | (1 << WIDX_TITLE_EDITOR_REPLAY)
| (1 << WIDX_TITLE_EDITOR_SKIP);
window_init_scroll_widgets(window);
window->list_information_type = 0;
window->selected_tab = tab;
window->selected_list_item = -1;
_window_title_editor_highlighted_index = -1;
window->scrolls[0].v_top = 0;
window->scrolls[0].h_left = 0;
window->min_width = WW;
window->min_height = WH;
window->max_width = 500;
window->max_height = 450;
if (_selectedTitleSequence >= title_sequence_manager_get_count())
_selectedTitleSequence = 0;
window_title_editor_load_sequence(_selectedTitleSequence);
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_close(rct_window* w)
{
title_stop_previewing_sequence();
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
// Close the related windows
window_close_by_class(WC_TITLE_COMMAND_EDITOR);
FreeTitleSequence(_editingTitleSequence);
2017-08-15 10:07:44 +02:00
_editingTitleSequence = nullptr;
_sequenceName = nullptr;
SafeFree(_renameSavePath);
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_mouseup(rct_window* w, rct_widgetindex widgetIndex)
2015-06-24 18:22:12 +02:00
{
2017-08-15 10:07:44 +02:00
bool commandEditorOpen = (window_find_by_class(WC_TITLE_COMMAND_EDITOR) != nullptr);
switch (widgetIndex)
{
2018-06-22 23:21:44 +02:00
case WIDX_TITLE_EDITOR_CLOSE:
window_close(w);
break;
2018-06-22 23:21:44 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Presets tab
//////////////////////////////////////////////////////////////////////////////////////////////////////
case WIDX_TITLE_EDITOR_NEW_BUTTON:
if (!commandEditorOpen)
{
2018-06-22 23:21:44 +02:00
window_text_input_open(
2018-10-17 21:55:12 +02:00
w, widgetIndex, STR_TITLE_EDITOR_ACTION_CREATE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_NONE, 0, 64);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_TITLE_EDITOR_DUPLICATE_BUTTON:
if (!commandEditorOpen && _editingTitleSequence != nullptr)
{
window_text_input_open(
w, widgetIndex, STR_TITLE_EDITOR_ACTION_DUPLICATE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_STRING,
reinterpret_cast<uintptr_t>(_sequenceName), 64);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_TITLE_EDITOR_DELETE_BUTTON:
if (window_title_editor_check_can_edit())
{
title_sequence_manager_delete(_selectedTitleSequence);
window_title_editor_load_sequence(0);
}
break;
case WIDX_TITLE_EDITOR_RENAME_BUTTON:
if (window_title_editor_check_can_edit() && _editingTitleSequence != nullptr)
{
window_text_input_open(
w, widgetIndex, STR_TRACK_MANAGE_RENAME, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_STRING,
reinterpret_cast<uintptr_t>(_sequenceName), 64);
2018-06-22 23:21:44 +02:00
}
break;
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Editor tab
//////////////////////////////////////////////////////////////////////////////////////////////////////
case WIDX_TITLE_EDITOR_ADD_SAVE:
if (!_isSequenceReadOnly && !title_is_previewing_sequence() && !commandEditorOpen)
{
auto intent = Intent(WC_LOADSAVE);
intent.putExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME);
intent.putExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast<void*>(window_title_editor_add_park_callback));
2018-06-22 23:21:44 +02:00
context_open_intent(&intent);
}
break;
case WIDX_TITLE_EDITOR_REMOVE_SAVE:
if (window_title_editor_check_can_edit())
{
if (w->selected_list_item != -1)
{
2018-06-22 23:21:44 +02:00
TitleSequenceRemovePark(_editingTitleSequence, w->selected_list_item);
2020-04-19 14:08:22 +02:00
if (w->selected_list_item >= static_cast<int16_t>(_editingTitleSequence->NumSaves))
2018-06-22 23:21:44 +02:00
{
w->selected_list_item--;
}
}
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_RENAME_SAVE:
if (window_title_editor_check_can_edit())
{
2018-06-22 23:21:44 +02:00
if (w->selected_list_item != -1)
{
window_text_input_open(
w, widgetIndex, STR_FILEBROWSER_RENAME_SAVE_TITLE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SAVE, STR_STRING,
reinterpret_cast<uintptr_t>(_editingTitleSequence->Saves[w->selected_list_item]), 52 - 1);
2018-06-22 23:21:44 +02:00
}
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_LOAD_SAVE:
2020-04-19 14:08:22 +02:00
if (w->selected_list_item >= 0 && w->selected_list_item < static_cast<int16_t>(_editingTitleSequence->NumSaves))
2018-06-22 23:21:44 +02:00
{
auto handle = TitleSequenceGetParkHandle(_editingTitleSequence, w->selected_list_item);
auto stream = static_cast<IStream*>(handle->Stream);
2018-06-22 23:21:44 +02:00
auto hintPath = String::ToStd(handle->HintPath);
bool isScenario = ParkImporter::ExtensionIsScenario(hintPath);
try
{
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
auto parkImporter = std::unique_ptr<IParkImporter>(ParkImporter::Create(hintPath));
auto result = parkImporter->LoadFromStream(stream, isScenario);
objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size());
parkImporter->Import();
if (isScenario)
scenario_begin();
else
game_load_init();
TitleSequenceCloseParkHandle(handle);
window_title_editor_open(WINDOW_TITLE_EDITOR_TAB_SAVES);
}
catch (const std::exception&)
{
context_show_error(ERROR_TYPE_FILE_LOAD, STR_FILE_CONTAINS_INVALID_DATA);
}
2018-06-22 23:21:44 +02:00
}
break;
2018-06-22 23:21:44 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Commands tab
//////////////////////////////////////////////////////////////////////////////////////////////////////
case WIDX_TITLE_EDITOR_INSERT:
if (window_title_editor_check_can_edit())
{
2018-06-22 23:21:44 +02:00
if (w->selected_list_item != -1)
window_title_command_editor_open(_editingTitleSequence, w->selected_list_item + 1, true);
else
window_title_command_editor_open(
_editingTitleSequence, static_cast<int32_t>(_editingTitleSequence->NumCommands), true);
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_EDIT:
if (window_title_editor_check_can_edit())
{
if (w->selected_list_item != -1
&& w->selected_list_item < static_cast<int16_t>(_editingTitleSequence->NumCommands))
{
2018-06-22 23:21:44 +02:00
window_title_command_editor_open(_editingTitleSequence, w->selected_list_item, false);
}
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_TITLE_EDITOR_DELETE:
if (window_title_editor_check_can_edit())
{
if (w->selected_list_item != -1
&& w->selected_list_item < static_cast<int16_t>(_editingTitleSequence->NumCommands))
{
for (int32_t i = w->selected_list_item; i < static_cast<int16_t>(_editingTitleSequence->NumCommands) - 1;
i++)
2018-06-22 23:21:44 +02:00
{
_editingTitleSequence->Commands[i] = _editingTitleSequence->Commands[i + 1];
}
_editingTitleSequence->NumCommands--;
if (w->selected_list_item >= static_cast<int16_t>(_editingTitleSequence->NumCommands))
2018-06-22 23:21:44 +02:00
{
w->selected_list_item--;
}
TitleSequenceSave(_editingTitleSequence);
}
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_SKIP_TO:
{
2018-06-22 23:21:44 +02:00
int32_t position = w->selected_list_item;
if (title_is_previewing_sequence() && position != -1
&& position < static_cast<int32_t>(_editingTitleSequence->NumCommands))
{
2018-06-22 23:21:44 +02:00
auto player = window_title_editor_get_player();
player->Seek(position);
player->Update();
}
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case WIDX_TITLE_EDITOR_MOVE_DOWN:
if (window_title_editor_check_can_edit())
{
if (w->selected_list_item != -1
&& w->selected_list_item < static_cast<int16_t>(_editingTitleSequence->NumCommands) - 1)
2018-06-22 23:21:44 +02:00
{
TitleCommand* a = &_editingTitleSequence->Commands[w->selected_list_item];
TitleCommand* b = &_editingTitleSequence->Commands[w->selected_list_item + 1];
TitleCommand tmp = *a;
*a = *b;
*b = tmp;
w->selected_list_item++;
TitleSequenceSave(_editingTitleSequence);
}
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_MOVE_UP:
if (window_title_editor_check_can_edit())
{
if (w->selected_list_item > 0
&& w->selected_list_item < static_cast<int16_t>(_editingTitleSequence->NumCommands))
2018-06-22 23:21:44 +02:00
{
TitleCommand* a = &_editingTitleSequence->Commands[w->selected_list_item - 1];
TitleCommand* b = &_editingTitleSequence->Commands[w->selected_list_item];
TitleCommand tmp = *b;
*b = *a;
*a = tmp;
w->selected_list_item--;
TitleSequenceSave(_editingTitleSequence);
}
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_REPLAY:
if (title_is_previewing_sequence())
{
2018-06-22 23:21:44 +02:00
auto player = window_title_editor_get_player();
player->Reset();
player->Update();
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-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_STOP:
if (title_is_previewing_sequence())
{
2018-06-22 23:21:44 +02:00
title_stop_previewing_sequence();
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_PLAY:
if (!title_is_previewing_sequence() || _selectedTitleSequence != title_get_current_sequence())
{
if (!title_preview_sequence(_selectedTitleSequence))
{
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 (title_is_previewing_sequence())
{
auto player = window_title_editor_get_player();
int32_t position = player->GetCurrentPosition() + 1;
if (position >= static_cast<int32_t>(_editingTitleSequence->NumCommands))
2018-06-22 23:21:44 +02:00
{
position = 0;
}
player->Seek(position);
player->Update();
}
break;
}
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_resize(rct_window* w)
2015-10-20 20:16:30 +02:00
{
if (w->selected_tab == WINDOW_TITLE_EDITOR_TAB_PRESETS)
window_set_resize(w, WW, WH2, 500, WH2);
else
window_set_resize(w, WW, WH, 500, 580);
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
2015-06-24 18:22:12 +02:00
{
switch (widgetIndex)
{
2018-06-22 23:21:44 +02:00
case WIDX_TITLE_EDITOR_PRESETS_TAB:
case WIDX_TITLE_EDITOR_SAVES_TAB:
case WIDX_TITLE_EDITOR_SCRIPT_TAB:
{
2018-06-22 23:21:44 +02:00
int32_t newSelectedTab = widgetIndex - WIDX_TITLE_EDITOR_PRESETS_TAB;
if (w->selected_tab != newSelectedTab)
{
w->selected_tab = newSelectedTab;
w->selected_list_item = -1;
_window_title_editor_highlighted_index = -1;
w->scrolls[0].v_top = 0;
w->frame_no = 0;
window_event_resize_call(w);
w->Invalidate();
2018-06-22 23:21:44 +02:00
}
break;
}
2018-06-22 23:21:44 +02:00
case WIDX_TITLE_EDITOR_PRESETS_DROPDOWN:
if (window_find_by_class(WC_TITLE_COMMAND_EDITOR) != nullptr)
{
2018-06-22 23:21:44 +02:00
context_show_error(STR_TITLE_EDITOR_ERR_CANT_CHANGE_WHILE_EDITOR_IS_OPEN, STR_NONE);
}
2018-06-22 23:21:44 +02:00
else
{
int32_t numItems = static_cast<int32_t>(title_sequence_manager_get_count());
2018-06-22 23:21:44 +02:00
for (int32_t i = 0; i < numItems; i++)
{
gDropdownItemsFormat[i] = STR_OPTIONS_DROPDOWN_ITEM;
gDropdownItemsArgs[i] = reinterpret_cast<uintptr_t>(title_sequence_manager_get_name(i));
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
widget--;
window_dropdown_show_text_custom_width(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->bottom - widget->top + 1,
2020-03-01 20:32:35 +01:00
w->colours[1], 0, DROPDOWN_FLAG_STAY_OPEN, numItems, widget->right - widget->left - 3);
dropdown_set_checked(static_cast<int32_t>(_selectedTitleSequence), true);
2018-06-22 23:21:44 +02:00
}
break;
}
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
2015-10-20 20:16:30 +02:00
{
if (dropdownIndex == -1)
return;
2015-06-24 18:22:12 +02:00
if (widgetIndex == WIDX_TITLE_EDITOR_PRESETS_DROPDOWN)
{
window_title_editor_load_sequence(dropdownIndex);
w->Invalidate();
}
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_update(rct_window* w)
2015-06-24 18:22:12 +02:00
{
w->frame_no++;
if (w->frame_no >= window_title_editor_tab_animation_loops[w->selected_tab])
{
w->frame_no = 0;
}
2015-06-24 18:22:12 +02:00
if (!widget_is_highlighted(w, WIDX_TITLE_EDITOR_LIST))
{
_window_title_editor_highlighted_index = -1;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
2015-06-24 18:22:12 +02:00
widget_invalidate(w, WIDX_TITLE_EDITOR_PRESETS_TAB + w->selected_tab);
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height)
2015-06-24 18:22:12 +02:00
{
size_t lineCount = 1;
if (w->selected_tab == WINDOW_TITLE_EDITOR_TAB_SAVES)
lineCount = _editingTitleSequence->NumSaves;
else if (w->selected_tab == WINDOW_TITLE_EDITOR_TAB_SCRIPT)
lineCount = _editingTitleSequence->NumCommands;
*height = static_cast<int32_t>(lineCount * SCROLLABLE_ROW_HEIGHT);
2018-06-22 23:21:44 +02:00
int32_t i = *height - window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].bottom
+ window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].top + 21;
if (i < 0)
{
i = 0;
}
if (i < w->scrolls[0].v_top)
{
w->scrolls[0].v_top = i;
w->Invalidate();
}
*width = SCROLL_WIDTH;
2015-06-24 18:22:12 +02:00
}
static void window_title_editor_scrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
int32_t index = screenCoords.y / SCROLLABLE_ROW_HEIGHT;
w->selected_list_item = -1;
switch (w->selected_tab)
{
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_SAVES:
if (index < static_cast<int32_t>(_editingTitleSequence->NumSaves))
2018-06-22 23:21:44 +02:00
{
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
if (index < static_cast<int32_t>(_editingTitleSequence->NumCommands))
2018-06-22 23:21:44 +02:00
{
w->selected_list_item = index;
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
}
break;
}
2015-06-24 18:22:12 +02:00
}
static void window_title_editor_scrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
int32_t index = screenCoords.y / SCROLLABLE_ROW_HEIGHT;
switch (w->selected_tab)
{
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_SAVES:
if (index < static_cast<int32_t>(_editingTitleSequence->NumSaves))
_window_title_editor_highlighted_index = static_cast<int16_t>(index);
2018-06-22 23:21:44 +02:00
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
if (index < static_cast<int32_t>(_editingTitleSequence->NumCommands))
_window_title_editor_highlighted_index = static_cast<int16_t>(index);
2018-06-22 23:21:44 +02:00
break;
}
widget_invalidate(w, WIDX_TITLE_EDITOR_LIST);
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_textinput(rct_window* w, rct_widgetindex widgetIndex, char* text)
2015-06-24 18:22:12 +02:00
{
if (str_is_null_or_empty(text))
return;
switch (widgetIndex)
{
2018-06-22 23:21:44 +02:00
case WIDX_TITLE_EDITOR_NEW_BUTTON:
case WIDX_TITLE_EDITOR_DUPLICATE_BUTTON:
case WIDX_TITLE_EDITOR_RENAME_BUTTON:
if (filename_valid_characters(text))
{
2018-06-22 23:21:44 +02:00
if (title_sequence_manager_get_index_for_name(text) == SIZE_MAX)
{
2018-06-22 23:21:44 +02:00
if (!title_sequence_manager_is_name_reserved(text))
{
2018-06-22 23:21:44 +02:00
if (widgetIndex == WIDX_TITLE_EDITOR_NEW_BUTTON)
{
size_t newIndex = title_sequence_manager_create(text);
window_title_editor_load_sequence(newIndex);
}
else if (widgetIndex == WIDX_TITLE_EDITOR_DUPLICATE_BUTTON)
{
size_t newIndex = title_sequence_manager_duplicate(_selectedTitleSequence, text);
window_title_editor_load_sequence(newIndex);
}
else
{
size_t newIndex = title_sequence_manager_rename(_selectedTitleSequence, text);
window_title_editor_load_sequence(newIndex);
}
config_save_default();
w->Invalidate();
}
else
{
2018-06-22 23:21:44 +02:00
context_show_error(STR_ERROR_RESERVED_NAME, STR_NONE);
}
}
else
{
2018-06-22 23:21:44 +02:00
context_show_error(STR_ERROR_EXISTING_NAME, STR_NONE);
}
}
else
{
2018-06-22 23:21:44 +02:00
context_show_error(STR_ERROR_INVALID_CHARACTERS, STR_NONE);
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_TITLE_EDITOR_RENAME_SAVE:
window_title_editor_rename_park(w->selected_list_item, text);
break;
}
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_invalidate(rct_window* w)
2015-06-24 18:22:12 +02:00
{
2018-06-22 23:21:44 +02:00
int32_t pressed_widgets = w->pressed_widgets
& ~((1LL << WIDX_TITLE_EDITOR_PRESETS_TAB) | (1LL << WIDX_TITLE_EDITOR_SAVES_TAB)
| (1LL << WIDX_TITLE_EDITOR_SCRIPT_TAB));
rct_widgetindex widgetIndex = w->selected_tab + WIDX_TITLE_EDITOR_PRESETS_TAB;
w->pressed_widgets = pressed_widgets | (1 << widgetIndex);
window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS_DROPDOWN].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_NEW_BUTTON].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DUPLICATE_BUTTON].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DELETE_BUTTON].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_RENAME_BUTTON].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_ADD_SAVE].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REMOVE_SAVE].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_RENAME_SAVE].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_LOAD_SAVE].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_INSERT].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_EDIT].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DELETE].type = WWT_EMPTY;
2018-06-22 23:21:44 +02:00
// window_title_editor_widgets[WIDX_TITLE_EDITOR_RELOAD].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP_TO].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_MOVE_UP].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_MOVE_DOWN].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PLAY].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_STOP].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REPLAY].type = WWT_EMPTY;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP].type = WWT_EMPTY;
switch (w->selected_tab)
{
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_PRESETS:
window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].type = WWT_DROPDOWN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS_DROPDOWN].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_NEW_BUTTON].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DUPLICATE_BUTTON].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DELETE_BUTTON].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_RENAME_BUTTON].type = WWT_BUTTON;
break;
case WINDOW_TITLE_EDITOR_TAB_SAVES:
window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].type = WWT_SCROLL;
window_title_editor_widgets[WIDX_TITLE_EDITOR_ADD_SAVE].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REMOVE_SAVE].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_RENAME_SAVE].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_LOAD_SAVE].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PLAY].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_STOP].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REPLAY].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP].type = WWT_IMGBTN;
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].type = WWT_SCROLL;
window_title_editor_widgets[WIDX_TITLE_EDITOR_INSERT].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_EDIT].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_DELETE].type = WWT_BUTTON;
// window_title_editor_widgets[WIDX_TITLE_EDITOR_RELOAD].type = WWT_DROPDOWN_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP_TO].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_MOVE_UP].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_MOVE_DOWN].type = WWT_BUTTON;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PLAY].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_STOP].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REPLAY].type = WWT_IMGBTN;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP].type = WWT_IMGBTN;
break;
}
window_title_editor_widgets[WIDX_TITLE_EDITOR_BACKGROUND].right = w->width - 1;
window_title_editor_widgets[WIDX_TITLE_EDITOR_BACKGROUND].bottom = w->height - 1;
window_title_editor_widgets[WIDX_TITLE_EDITOR_TAB_CONTENT_PANEL].right = w->width - 1;
window_title_editor_widgets[WIDX_TITLE_EDITOR_TAB_CONTENT_PANEL].bottom = w->height - 1;
window_title_editor_widgets[WIDX_TITLE_EDITOR_TITLE].right = w->width - 2;
window_title_editor_widgets[WIDX_TITLE_EDITOR_CLOSE].left = w->width - 2 - 0x0B;
window_title_editor_widgets[WIDX_TITLE_EDITOR_CLOSE].right = w->width - 2 - 0x0B + 0x0A;
window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].right = w->width - 4;
window_title_editor_widgets[WIDX_TITLE_EDITOR_LIST].bottom = w->height - 16;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REPLAY].top = w->height - 32;
window_title_editor_widgets[WIDX_TITLE_EDITOR_REPLAY].bottom = w->height - 16;
window_title_editor_widgets[WIDX_TITLE_EDITOR_STOP].top = w->height - 32;
window_title_editor_widgets[WIDX_TITLE_EDITOR_STOP].bottom = w->height - 16;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PLAY].top = w->height - 32;
window_title_editor_widgets[WIDX_TITLE_EDITOR_PLAY].bottom = w->height - 16;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP].top = w->height - 32;
window_title_editor_widgets[WIDX_TITLE_EDITOR_SKIP].bottom = w->height - 16;
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) && gScreenFlags != SCREEN_FLAGS_PLAYING)
w->disabled_widgets |= (1 << WIDX_TITLE_EDITOR_PLAY);
else
w->disabled_widgets &= ~(1 << WIDX_TITLE_EDITOR_PLAY);
if (!title_is_previewing_sequence())
2018-06-22 23:21:44 +02:00
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
2018-06-22 23:21:44 +02:00
w->disabled_widgets &= ~(
(1 << WIDX_TITLE_EDITOR_REPLAY) | (1 << WIDX_TITLE_EDITOR_STOP) | (1 << WIDX_TITLE_EDITOR_SKIP)
| (1 << WIDX_TITLE_EDITOR_SKIP_TO));
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
// Widgets
window_draw_widgets(w, dpi);
window_title_editor_draw_tab_images(dpi, w);
// Draw strings
switch (w->selected_tab)
{
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_PRESETS:
2020-06-03 00:40:47 +02:00
{
auto ft = Formatter::Common();
ft.Add<const char*>(_sequenceName);
2018-06-22 23:21:44 +02:00
gfx_draw_string_left(
dpi, STR_TITLE_SEQUENCE, nullptr, w->colours[1],
w->windowPos + ScreenCoordsXY{ 10, window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].top + 1 });
2018-06-22 23:21:44 +02:00
gfx_draw_string_left_clipped(
dpi, STR_STRING, gCommonFormatArgs, w->colours[1],
{ w->windowPos.x + window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].left + 1,
w->windowPos.y + window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].top },
2020-03-01 20:32:35 +01:00
w->windowPos.x + window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS_DROPDOWN].left
2018-06-22 23:21:44 +02:00
- window_title_editor_widgets[WIDX_TITLE_EDITOR_PRESETS].left - 4);
break;
2020-06-03 00:40:47 +02:00
}
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_SAVES:
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
break;
}
2015-06-24 18:22:12 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex)
2015-06-24 18:22:12 +02:00
{
gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light);
switch (w->selected_tab)
{
2018-06-22 23:21:44 +02:00
case WINDOW_TITLE_EDITOR_TAB_SAVES:
window_title_editor_scrollpaint_saves(w, dpi);
break;
case WINDOW_TITLE_EDITOR_TAB_SCRIPT:
window_title_editor_scrollpaint_commands(w, dpi);
break;
}
}
2015-06-24 18:22:12 +02:00
2018-06-22 23:21:44 +02:00
static void window_title_editor_scrollpaint_saves(rct_window* w, rct_drawpixelinfo* dpi)
{
int32_t currentSaveIndex = -1;
auto screenCoords = ScreenCoordsXY{ 0, 0 };
if (_editingTitleSequence == nullptr)
return;
for (int32_t i = 0; i < static_cast<int32_t>(_editingTitleSequence->NumSaves); i++, screenCoords.y += SCROLLABLE_ROW_HEIGHT)
{
bool selected = false;
bool hover = false;
if (i == w->selected_list_item)
{
selected = true;
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].dark);
}
else if (i == _window_title_editor_highlighted_index || i == currentSaveIndex)
{
hover = true;
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark);
}
else if (i & 1)
{
2018-06-22 23:21:44 +02:00
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
}
char buffer[256];
auto ft = Formatter::Common();
ft.Add<const char*>(_editingTitleSequence->Saves[i]);
if (selected || hover)
{
format_string(buffer, 256, STR_STRING, gCommonFormatArgs);
}
else
{
format_string(buffer + 1, 255, STR_STRING, gCommonFormatArgs);
buffer[0] = static_cast<utf8>(static_cast<uint8_t>(FORMAT_BLACK));
}
ft = Formatter::Common();
ft.Add<const char*>(&buffer);
gfx_draw_string_left(dpi, STR_STRING, gCommonFormatArgs, w->colours[1], screenCoords + ScreenCoordsXY{ 5, 0 });
}
}
2015-06-24 18:22:12 +02:00
2018-06-22 23:21:44 +02:00
static void window_title_editor_scrollpaint_commands(rct_window* w, rct_drawpixelinfo* dpi)
{
int32_t position = -1;
if (title_is_previewing_sequence() && _selectedTitleSequence == title_get_current_sequence())
{
auto player = window_title_editor_get_player();
position = player->GetCurrentPosition();
}
auto screenCoords = ScreenCoordsXY{ 0, 0 };
for (int32_t i = 0; i < static_cast<int32_t>(_editingTitleSequence->NumCommands);
i++, screenCoords.y += SCROLLABLE_ROW_HEIGHT)
{
2018-06-22 23:21:44 +02:00
TitleCommand* command = &_editingTitleSequence->Commands[i];
bool selected = false;
bool hover = false;
bool error = false;
if (i == w->selected_list_item)
{
selected = true;
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].dark);
}
else if (i == static_cast<int32_t>(_window_title_editor_highlighted_index) || i == position)
{
hover = true;
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark);
}
else if (i & 1)
{
2018-06-22 23:21:44 +02:00
gfx_fill_rect(
dpi, screenCoords.x, screenCoords.y, screenCoords.x + SCROLL_WIDTH + 100,
screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
}
auto ft = Formatter::Common();
rct_string_id commandName = STR_NONE;
switch (command->Type)
{
2018-06-22 23:21:44 +02:00
case TITLE_SCRIPT_LOAD:
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_FILE;
if (command->SaveIndex == SAVE_INDEX_INVALID)
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_NO_SAVE;
error = true;
}
else
{
ft.Add<const char*>(_editingTitleSequence->Saves[command->SaveIndex]);
2018-06-22 23:21:44 +02:00
}
break;
case TITLE_SCRIPT_LOCATION:
commandName = STR_TITLE_EDITOR_COMMAND_LOCATION;
ft.Add<uint16_t>(command->X);
ft.Add<uint16_t>(command->Y);
2018-06-22 23:21:44 +02:00
break;
case TITLE_SCRIPT_ROTATE:
commandName = STR_TITLE_EDITOR_COMMAND_ROTATE;
ft.Add<uint16_t>(command->Rotations);
2018-06-22 23:21:44 +02:00
break;
case TITLE_SCRIPT_ZOOM:
commandName = STR_TITLE_EDITOR_COMMAND_ZOOM;
ft.Add<uint16_t>(command->Zoom);
2018-06-22 23:21:44 +02:00
break;
case TITLE_SCRIPT_SPEED:
commandName = STR_TITLE_EDITOR_COMMAND_SPEED;
ft.Add<rct_string_id>(SpeedNames[command->Speed - 1]);
2018-06-22 23:21:44 +02:00
break;
case TITLE_SCRIPT_FOLLOW:
commandName = STR_TITLE_EDITOR_COMMAND_FOLLOW;
if (command->SpriteIndex == SPRITE_INDEX_NULL)
{
commandName = STR_TITLE_EDITOR_COMMAND_FOLLOW_NO_SPRITE;
}
else
{
ft.Add<uintptr_t>(reinterpret_cast<uintptr_t>(command->SpriteName));
2018-06-22 23:21:44 +02:00
}
break;
case TITLE_SCRIPT_WAIT:
commandName = STR_TITLE_EDITOR_COMMAND_WAIT;
ft.Add<uint16_t>(command->Milliseconds);
2018-06-22 23:21:44 +02:00
break;
case TITLE_SCRIPT_RESTART:
commandName = STR_TITLE_EDITOR_RESTART;
break;
case TITLE_SCRIPT_END:
commandName = STR_TITLE_EDITOR_END;
break;
case TITLE_SCRIPT_LOADSC:
{
2018-06-22 23:21:44 +02:00
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_FILE;
const char* name = "";
auto scenario = GetScenarioRepository()->GetByInternalName(command->Scenario);
if (command->Scenario[0] == '\0')
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_NO_SCENARIO;
}
else if (scenario != nullptr)
{
name = scenario->name;
}
else
{
commandName = STR_TITLE_EDITOR_COMMAND_LOAD_MISSING_SCENARIO;
}
ft.Add<const char*>(name);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
default:
log_warning("Unknown command %d", command->Type);
}
char buffer[256];
if ((selected || hover) && !error)
{
format_string(buffer, 256, commandName, gCommonFormatArgs);
}
else
{
format_string(buffer + 1, 255, commandName, gCommonFormatArgs);
2020-04-19 14:08:22 +02:00
buffer[0] = static_cast<utf8>(error ? ((selected || hover) ? FORMAT_LIGHTPINK : FORMAT_RED) : FORMAT_BLACK);
}
ft = Formatter::Common();
ft.Add<const char*>(&buffer);
gfx_draw_string_left(dpi, STR_STRING, gCommonFormatArgs, w->colours[1], screenCoords + ScreenCoordsXY{ 5, 0 });
}
}
2015-06-24 18:22:12 +02:00
2018-06-22 23:21:44 +02:00
static void window_title_editor_draw_tab_images(rct_drawpixelinfo* dpi, rct_window* w)
{
for (int32_t i = 0; i < WINDOW_TITLE_EDITOR_TAB_COUNT; i++)
{
int32_t x = 0;
int32_t y = 0;
int32_t spriteId = window_title_editor_tab_sprites[i];
if (w->selected_tab == i)
{
spriteId += w->frame_no / window_title_editor_tab_animation_divisor[w->selected_tab];
}
if (i == 1)
{
x = 4;
y = 1;
}
2018-06-22 23:21:44 +02:00
gfx_draw_sprite(
2020-03-01 20:32:35 +01:00
dpi, spriteId, w->windowPos.x + w->widgets[WIDX_TITLE_EDITOR_PRESETS_TAB + i].left + x,
w->windowPos.y + w->widgets[WIDX_TITLE_EDITOR_PRESETS_TAB + i].top + y, 0);
}
2015-07-13 11:56:58 +02:00
}
2016-11-27 15:47:02 +01:00
static void window_title_editor_load_sequence(size_t index)
{
if (index >= title_sequence_manager_get_count())
return;
2018-06-22 23:21:44 +02:00
const char* path = title_sequence_manager_get_path(index);
TitleSequence* titleSequence = LoadTitleSequence(path);
if (titleSequence == nullptr)
{
context_show_error(STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA, STR_NONE);
return;
}
_selectedTitleSequence = index;
size_t predefinedIndex = title_sequence_manager_get_predefined_index(index);
_isSequenceReadOnly = (predefinedIndex != SIZE_MAX);
_sequenceName = title_sequence_manager_get_name(index);
FreeTitleSequence(_editingTitleSequence);
_editingTitleSequence = titleSequence;
window_close_by_class(WC_TITLE_COMMAND_EDITOR);
2016-11-26 16:32:49 +01:00
}
2018-06-22 23:21:44 +02:00
static ITitleSequencePlayer* window_title_editor_get_player()
2016-11-26 16:32:49 +01:00
{
return static_cast<ITitleSequencePlayer*>(title_get_sequence_player());
}
2016-11-27 15:47:02 +01:00
static bool window_title_editor_check_can_edit()
{
2017-08-15 10:07:44 +02:00
bool commandEditorOpen = (window_find_by_class(WC_TITLE_COMMAND_EDITOR) != nullptr);
if (_isSequenceReadOnly)
context_show_error(STR_ERROR_CANT_CHANGE_TITLE_SEQUENCE, STR_NONE);
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);
else
return true;
return false;
2016-11-27 15:47:02 +01:00
}
2018-06-22 23:21:44 +02:00
static bool save_filename_exists(const utf8* filename)
{
2018-06-22 23:21:44 +02:00
TitleSequence* seq = _editingTitleSequence;
for (size_t i = 0; i < seq->NumSaves; i++)
{
2018-06-22 23:21:44 +02:00
const utf8* savePath = seq->Saves[i];
if (_stricmp(savePath, filename) == 0)
return true;
}
return false;
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_add_park_callback(int32_t result, const utf8* path)
{
uint32_t extension = get_file_extension_type(path);
if (extension != FILE_EXTENSION_SV4 && extension != FILE_EXTENSION_SV6)
return;
2018-06-22 23:21:44 +02:00
const utf8* filename = path_get_filename(path);
if (save_filename_exists(filename))
{
free(_renameSavePath);
_renameSavePath = _strdup(filename);
2018-06-22 23:21:44 +02:00
rct_window* w = window_find_by_class(WC_TITLE_EDITOR);
window_text_input_open(
w, WIDX_TITLE_EDITOR_RENAME_SAVE, STR_FILEBROWSER_RENAME_SAVE_TITLE, STR_ERROR_EXISTING_NAME, STR_STRING,
reinterpret_cast<uintptr_t>(_renameSavePath), 52 - 1);
return;
}
TitleSequenceAddPark(_editingTitleSequence, path, filename);
}
2018-06-22 23:21:44 +02:00
static void window_title_editor_rename_park(size_t index, const utf8* name)
{
if (!filename_valid_characters(name))
{
context_show_error(STR_ERROR_INVALID_CHARACTERS, STR_NONE);
return;
}
for (size_t i = 0; i < _editingTitleSequence->NumSaves; i++)
{
if (i != index)
{
2018-06-22 23:21:44 +02:00
const utf8* savePath = _editingTitleSequence->Saves[i];
if (_strcmpi(savePath, name) == 0)
{
context_show_error(STR_ERROR_EXISTING_NAME, STR_NONE);
return;
}
}
}
if (TitleSequenceRenamePark(_editingTitleSequence, index, name))
{
TitleSequenceSave(_editingTitleSequence);
}
}