1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 20:43:04 +01:00
Files
OpenRCT2/src/openrct2-ui/windows/TitleCommandEditor.cpp
Hielke Morsink 55979a3fff Remove and replace C typedefs
`typedef struct/union/enum name { ... } name_again;` is not needed whe compiling C++, moving the name at the back to be in front of the object and removing `typedef` makes it usable the very same way.
This also replaces typedefs with the using keyword. They have better readability, especially for function pointer types, and would allow more flexibility when used with templates.
2018-02-14 09:42:26 +01:00

885 lines
32 KiB
C++

#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include <openrct2/OpenRCT2.h>
#include <openrct2/title/TitleSequence.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2/core/Util.hpp>
#include <openrct2/interface/themes.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/sprites.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Dropdown.h>
struct TITLE_COMMAND_ORDER {
// originally a uint8, but the new millisecond wait times require a uint16.
uint16 command;
rct_string_id nameStringId;
rct_string_id descStringId;
};
static TITLE_COMMAND_ORDER _window_title_command_editor_orders[] = {
{ TITLE_SCRIPT_LOAD, STR_TITLE_EDITOR_ACTION_LOAD_SAVE, STR_TITLE_EDITOR_ARGUMENT_SAVEFILE },
{ TITLE_SCRIPT_LOADSC, STR_TITLE_EDITOR_ACTION_LOAD_SCENARIO, STR_TITLE_EDITOR_ARGUMENT_SCENARIO },
{ TITLE_SCRIPT_LOCATION, STR_TITLE_EDITOR_COMMAND_TYPE_LOCATION, STR_TITLE_EDITOR_ARGUMENT_COORDINATES },
{ TITLE_SCRIPT_ROTATE, STR_TITLE_EDITOR_COMMAND_TYPE_ROTATE, STR_TITLE_EDITOR_ARGUMENT_ROTATIONS },
{ TITLE_SCRIPT_ZOOM, STR_TITLE_EDITOR_COMMAND_TYPE_ZOOM, STR_TITLE_EDITOR_ARGUMENT_ZOOM_LEVEL },
{ TITLE_SCRIPT_SPEED, STR_TITLE_EDITOR_COMMAND_TYPE_SPEED, STR_TITLE_EDITOR_ARGUMENT_SPEED },
{ TITLE_SCRIPT_FOLLOW, STR_TITLE_EDITOR_COMMAND_TYPE_FOLLOW, STR_NONE },
{ TITLE_SCRIPT_WAIT, STR_TITLE_EDITOR_COMMAND_TYPE_WAIT, STR_TITLE_EDITOR_ARGUMENT_WAIT_SECONDS },
{ TITLE_SCRIPT_RESTART, STR_TITLE_EDITOR_RESTART, STR_NONE },
{ TITLE_SCRIPT_END, STR_TITLE_EDITOR_END, STR_NONE },
};
#define NUM_COMMANDS Util::CountOf(_window_title_command_editor_orders)
enum WINDOW_WATER_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_COMMAND,
WIDX_COMMAND_DROPDOWN,
WIDX_TEXTBOX_FULL,
WIDX_TEXTBOX_X,
WIDX_TEXTBOX_Y,
WIDX_INPUT,
WIDX_INPUT_DROPDOWN,
WIDX_GET,
WIDX_SELECT_SCENARIO,
WIDX_SELECT_SPRITE,
WIDX_VIEWPORT,
WIDX_OKAY,
WIDX_CANCEL
};
#define WW 200
#define WH 120
#define BY 32
#define BY2 70
#define WS 16
#define WHA ((WW-WS*2)/2)
static bool _window_title_command_editor_insert;
static sint32 _window_title_command_editor_index;
#define BUF_SIZE 50
static char textbox1Buffer[BUF_SIZE];
static char textbox2Buffer[BUF_SIZE];
static TitleCommand command = { TITLE_SCRIPT_LOAD, { 0 } };
static TitleSequence * _sequence = nullptr;
static rct_widget window_title_command_editor_widgets[] = {
{ WWT_FRAME, 1, 0, WW-1, 0, WH-1, 0xFFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 1, 1, WW-2, 1, 14, STR_TITLE_COMMAND_EDITOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 1, WW-13, WW-3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_DROPDOWN, 1, WS, WW-WS-1, BY, BY+11, STR_NONE, STR_NONE }, // Command dropdown
{ WWT_BUTTON, 1, WW-WS-12, WW-WS-2, BY+1, BY+10, STR_DROPDOWN_GLYPH, STR_NONE },
{ WWT_TEXT_BOX, 1, WS, WW-WS-1, BY2, BY2+11, STR_NONE, STR_NONE }, // full textbox
{ WWT_TEXT_BOX, 1, WS, WS+WHA-4, BY2, BY2+11, STR_NONE, STR_NONE }, // x textbox
{ WWT_TEXT_BOX, 1, WS+WHA+3, WW-WS-1, BY2, BY2+11, STR_NONE, STR_NONE }, // y textbox
{ WWT_DROPDOWN, 1, 16, WW-17, BY2, BY2+11, STR_NONE, STR_NONE }, // Save dropdown
{ WWT_BUTTON, 1, WW-28, WW-18, BY2+1, BY2+10, STR_DROPDOWN_GLYPH, STR_NONE },
{ WWT_BUTTON, 1, WS+WHA+3, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_ACTION_GET_LOCATION, STR_NONE }, // Get location/zoom/etc
{ WWT_BUTTON, 1, WS+WHA+12, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_ACTION_SELECT_SCENARIO, STR_NONE }, // Select scenario
{ WWT_BUTTON, 1, WS, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_SELECT_SPRITE, STR_NONE }, // Select sprite
{ WWT_VIEWPORT, 1, WS, WW-WS-1, BY2, BY2+22, STR_NONE, STR_NONE }, // Viewport
{ WWT_BUTTON, 1, 10, 80, WH-21, WH-10, STR_OK, STR_NONE }, // OKAY
{ WWT_BUTTON, 1, WW-80, WW-10, WH-21, WH-10, STR_CANCEL, STR_NONE }, // Cancel
{ WIDGETS_END },
};
static void window_title_command_editor_close(rct_window * w);
static void window_title_command_editor_mouseup(rct_window * w, rct_widgetindex widgetIndex);
static void window_title_command_editor_mousedown(rct_window * w, rct_widgetindex widgetIndex, rct_widget * widget);
static void window_title_command_editor_dropdown(rct_window * w, rct_widgetindex widgetIndex, sint32 dropdownIndex);
static void window_title_command_editor_update(rct_window * w);
static void window_title_command_editor_tool_down(rct_window * w, rct_widgetindex widgetIndex, sint32 x, sint32 y);
static void window_title_command_editor_invalidate(rct_window * w);
static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo * dpi);
static void window_title_command_editor_textinput(rct_window * w, rct_widgetindex widgetIndex, char * text);
static void window_title_command_editor_inputsize(rct_window * w);
static void scenario_select_callback(const utf8 * path);
static sint32 get_command_info_index(sint32 index);
static TITLE_COMMAND_ORDER get_command_info(sint32 index);
static LocationXY16 get_location();
static uint8 get_zoom();
static rct_window_event_list window_title_command_editor_events = {
window_title_command_editor_close,
window_title_command_editor_mouseup,
nullptr,
window_title_command_editor_mousedown,
window_title_command_editor_dropdown,
nullptr,
window_title_command_editor_update,
nullptr,
nullptr,
nullptr,
window_title_command_editor_tool_down,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_title_command_editor_textinput,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_title_command_editor_invalidate,
window_title_command_editor_paint,
nullptr
};
static void scenario_select_callback(const utf8 * path)
{
if (command.Type == TITLE_SCRIPT_LOADSC)
{
const utf8 * fileName = path_get_filename(path);
auto scenario = GetScenarioRepository()->GetByFilename(fileName);
safe_strcpy(command.Scenario, scenario->internal_name, sizeof(command.Scenario));
}
}
static sint32 get_command_info_index(sint32 index)
{
for (sint32 i = 0; i < (sint32)NUM_COMMANDS; i++)
{
if (_window_title_command_editor_orders[i].command == index)
return i;
}
return 0;
}
static TITLE_COMMAND_ORDER get_command_info(sint32 index)
{
for (sint32 i = 0; i < (sint32)NUM_COMMANDS; i++)
{
if (_window_title_command_editor_orders[i].command == index)
return _window_title_command_editor_orders[i];
}
return _window_title_command_editor_orders[0];
}
static LocationXY16 get_location()
{
LocationXY16 mapCoord = { 0 };
rct_window * w = window_get_main();
if (w != nullptr)
{
sint32 interactionType;
rct_tile_element * tileElement;
get_map_coordinates_from_pos_window(w, w->viewport->view_width / 2, w->viewport->view_height / 2, VIEWPORT_INTERACTION_MASK_TERRAIN, &mapCoord.x, &mapCoord.y, &interactionType, &tileElement, nullptr);
mapCoord.x -= 16;
mapCoord.x /= 32;
mapCoord.y -= 16;
mapCoord.y /= 32;
mapCoord.x++;
mapCoord.y++;
}
return mapCoord;
}
static uint8 get_zoom()
{
uint8 zoom = 0;
rct_window * w = window_get_main();
if (w != nullptr)
{
zoom = w->viewport->zoom;
}
return zoom;
}
static bool sprite_selector_tool_is_active()
{
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
return false;
if (gCurrentToolWidget.window_classification != WC_TITLE_COMMAND_EDITOR)
return false;
return true;
}
void window_title_command_editor_open(TitleSequence * sequence, sint32 index, bool insert)
{
_sequence = sequence;
// Check if window is already open
if (window_find_by_class(WC_TITLE_COMMAND_EDITOR) != nullptr)
return;
rct_window * window = window_create_centred(
WW,
WH,
&window_title_command_editor_events,
WC_TITLE_COMMAND_EDITOR,
WF_STICK_TO_FRONT
);
window_title_command_editor_widgets[WIDX_TEXTBOX_FULL].string = textbox1Buffer;
window_title_command_editor_widgets[WIDX_TEXTBOX_X].string = textbox1Buffer;
window_title_command_editor_widgets[WIDX_TEXTBOX_Y].string = textbox2Buffer;
window->widgets = window_title_command_editor_widgets;
window->enabled_widgets =
(1 << WIDX_CLOSE) |
(1 << WIDX_COMMAND) |
(1 << WIDX_COMMAND_DROPDOWN) |
(1 << WIDX_TEXTBOX_FULL) |
(1 << WIDX_TEXTBOX_X) |
(1 << WIDX_TEXTBOX_Y) |
(1 << WIDX_INPUT) |
(1 << WIDX_INPUT_DROPDOWN) |
(1 << WIDX_GET) |
(1 << WIDX_SELECT_SCENARIO) |
(1 << WIDX_SELECT_SPRITE) |
(1 << WIDX_OKAY) |
(1 << WIDX_CANCEL);
window_init_scroll_widgets(window);
rct_widget *const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT];
viewport_create(window, window->x + viewportWidget->left + 1, window->y + viewportWidget->top + 1, viewportWidget->right - viewportWidget->left - 1, viewportWidget->bottom - viewportWidget->top - 1, 0, 0, 0, 0, 0, -1);
_window_title_command_editor_index = index;
_window_title_command_editor_insert = insert;
if (!insert)
{
command = _sequence->Commands[index];
}
switch (command.Type)
{
case TITLE_SCRIPT_LOAD:
if (command.SaveIndex >= _sequence->NumSaves)
command.SaveIndex = SAVE_INDEX_INVALID;
break;
case TITLE_SCRIPT_LOCATION:
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.X);
snprintf(textbox2Buffer, BUF_SIZE, "%d", command.Y);
break;
case TITLE_SCRIPT_ROTATE:
case TITLE_SCRIPT_ZOOM:
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Rotations);
break;
case TITLE_SCRIPT_WAIT:
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Milliseconds);
break;
case TITLE_SCRIPT_FOLLOW:
if (command.SpriteIndex != SPRITE_INDEX_NULL)
{
window_follow_sprite(window, (size_t)command.SpriteIndex);
}
break;
}
}
static void window_title_command_editor_close(rct_window * w)
{
if (sprite_selector_tool_is_active())
{
tool_cancel();
}
}
static void window_title_command_editor_mouseup(rct_window * w, rct_widgetindex widgetIndex)
{
switch (widgetIndex)
{
case WIDX_CLOSE:
case WIDX_CANCEL:
window_close(w);
break;
case WIDX_TEXTBOX_FULL:
// The only commands that use TEXTBOX_FULL currently are Wait, Rotate, and Zoom. Rotate and Zoom have single-digit maximum values, while Wait has 5-digit maximum values.
if (command.Type == TITLE_SCRIPT_WAIT)
{
window_start_textbox(w, widgetIndex, STR_STRING, textbox1Buffer, 6);
}
else
{
window_start_textbox(w, widgetIndex, STR_STRING, textbox1Buffer, 2);
}
break;
case WIDX_TEXTBOX_X:
window_start_textbox(w, widgetIndex, STR_STRING, textbox1Buffer, 4);
break;
case WIDX_TEXTBOX_Y:
window_start_textbox(w, widgetIndex, STR_STRING, textbox2Buffer, 4);
break;
case WIDX_GET:
if (command.Type == TITLE_SCRIPT_LOCATION)
{
LocationXY16 mapCoord = get_location();
command.X = (uint8)mapCoord.x;
command.Y = (uint8)mapCoord.y;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.X);
snprintf(textbox2Buffer, BUF_SIZE, "%d", command.Y);
}
else if (command.Type == TITLE_SCRIPT_ZOOM)
{
uint8 zoom = get_zoom();
command.Zoom = zoom;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Zoom);
}
window_invalidate(w);
break;
case WIDX_SELECT_SCENARIO:
window_scenarioselect_open(scenario_select_callback, true);
break;
case WIDX_SELECT_SPRITE:
if (!sprite_selector_tool_is_active())
{
tool_set(w, WIDX_BACKGROUND, TOOL_CROSSHAIR);
}
else
{
tool_cancel();
}
break;
case WIDX_OKAY:
if (_window_title_command_editor_insert)
{
size_t insertIndex = _window_title_command_editor_index;
_sequence->NumCommands++;
_sequence->Commands = Memory::ReallocateArray(_sequence->Commands, _sequence->NumCommands);
for (size_t i = _sequence->NumCommands - 1; i > insertIndex; i--)
{
_sequence->Commands[i] = _sequence->Commands[i - 1];
}
_sequence->Commands[insertIndex] = command;
}
else
{
_sequence->Commands[_window_title_command_editor_index] = command;
TitleSequenceSave(_sequence);
}
TitleSequenceSave(_sequence);
rct_window * title_editor_w = window_find_by_class(WC_TITLE_EDITOR);
if (title_editor_w != nullptr)
{
title_editor_w->selected_list_item = _window_title_command_editor_index;
}
window_close(w);
break;
}
}
static void window_title_command_editor_mousedown(rct_window * w, rct_widgetindex widgetIndex, rct_widget * widget)
{
widget--;
switch (widgetIndex)
{
case WIDX_COMMAND_DROPDOWN:
{
size_t numItems = NUM_COMMANDS;
for (size_t i = 0; i < numItems; i++)
{
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = _window_title_command_editor_orders[i].nameStringId;
}
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - widget->left - 3);
dropdown_set_checked(get_command_info_index(command.Type), true);
break;
}
case WIDX_INPUT_DROPDOWN:
if (command.Type == TITLE_SCRIPT_SPEED)
{
sint32 numItems = 4;
for (sint32 i = 0; i < numItems; i++)
{
gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[i] = SpeedNames[i];
}
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - widget->left - 3);
dropdown_set_checked(command.Speed - 1, true);
}
else if (command.Type == TITLE_SCRIPT_LOAD)
{
sint32 numItems = (sint32)_sequence->NumSaves;
for (sint32 i = 0; i < numItems; i++)
{
gDropdownItemsFormat[i] = STR_OPTIONS_DROPDOWN_ITEM;
gDropdownItemsArgs[i] = (uintptr_t)_sequence->Saves[i];
}
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - widget->left - 3);
dropdown_set_checked(command.SaveIndex, true);
}
break;
}
}
static void window_title_command_editor_dropdown(rct_window * w, rct_widgetindex widgetIndex, sint32 dropdownIndex)
{
if (dropdownIndex == -1)
return;
// Cancel sprite selector tool if it's active
if (sprite_selector_tool_is_active())
{
tool_cancel();
}
switch (widgetIndex)
{
case WIDX_COMMAND_DROPDOWN:
if (command.SpriteIndex != SPRITE_INDEX_NULL)
{
window_unfollow_sprite(w);
}
if (dropdownIndex == get_command_info_index(command.Type))
{
break;
}
command.Type = _window_title_command_editor_orders[dropdownIndex].command;
switch (command.Type)
{
case TITLE_SCRIPT_LOCATION:
{
LocationXY16 mapCoord = get_location();
command.X = (uint8)mapCoord.x;
command.Y = (uint8)mapCoord.y;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.X);
snprintf(textbox2Buffer, BUF_SIZE, "%d", command.Y);
break;
}
case TITLE_SCRIPT_ROTATE:
command.Rotations = 1;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Rotations);
break;
case TITLE_SCRIPT_ZOOM:
command.Zoom = 0;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Zoom);
break;
case TITLE_SCRIPT_FOLLOW:
command.SpriteIndex = SPRITE_INDEX_NULL;
command.SpriteName[0] = '\0';
window_unfollow_sprite(w);
w->viewport->flags &= ~VIEWPORT_FOCUS_TYPE_SPRITE;
break;
case TITLE_SCRIPT_SPEED:
command.Speed = 1;
break;
case TITLE_SCRIPT_WAIT:
command.Milliseconds = 10000;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Milliseconds);
break;
case TITLE_SCRIPT_LOAD:
command.SaveIndex = 0;
if (command.SaveIndex >= _sequence->NumSaves)
{
command.SaveIndex = 0xFF;
}
break;
case TITLE_SCRIPT_LOADSC:
command.Scenario[0] = '\0';
}
window_invalidate(w);
break;
case WIDX_INPUT_DROPDOWN:
switch (command.Type)
{
case TITLE_SCRIPT_SPEED:
if (dropdownIndex != command.Speed - 1)
{
command.Speed = (uint8)(dropdownIndex + 1);
window_invalidate(w);
}
break;
case TITLE_SCRIPT_LOAD:
if (dropdownIndex != command.SaveIndex)
{
command.SaveIndex = (uint8)dropdownIndex;
window_invalidate(w);
}
break;
}
break;
}
}
static void window_title_command_editor_textinput(rct_window * w, rct_widgetindex widgetIndex, char * text)
{
char * end;
sint32 value = strtol(widgetIndex != WIDX_TEXTBOX_Y ? textbox1Buffer : textbox2Buffer, &end, 10);
if (value < 0) value = 0;
// The Wait command is the only one with acceptable values greater than 255.
if (value > 255 && command.Type != TITLE_SCRIPT_WAIT) value = 255;
switch (widgetIndex)
{
case WIDX_TEXTBOX_FULL:
if (text == nullptr)
{
if (*end == '\0')
{
if (command.Type == TITLE_SCRIPT_WAIT)
{
if (value < 100) value = 100;
if (value > 65000) value = 65000;
command.Milliseconds = (uint16)value;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Milliseconds);
}
else
{
// Both Rotate and Zoom have a maximum value of 3, but Rotate has a min value of 1 not 0.
if (value > 3) value = 3;
if (value < 1 && command.Type == TITLE_SCRIPT_ROTATE) value = 1;
command.Rotations = (uint8)value;
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Rotations);
}
}
window_invalidate(w);
}
else
{
safe_strcpy(textbox1Buffer, text, sizeof(textbox1Buffer));
}
break;
case WIDX_TEXTBOX_X:
if (text == nullptr)
{
if (*end == '\0')
{
command.X = (uint8)value;
}
snprintf(textbox1Buffer, BUF_SIZE, "%d", command.X);
window_invalidate(w);
}
else
{
safe_strcpy(textbox1Buffer, text, sizeof(textbox1Buffer));
}
break;
case WIDX_TEXTBOX_Y:
if (text == nullptr)
{
if (*end == '\0')
{
command.Y = (uint8)value;
}
snprintf(textbox2Buffer, BUF_SIZE, "%d", command.Y);
window_invalidate(w);
}
else
{
safe_strcpy(textbox2Buffer, text, sizeof(textbox2Buffer));
}
break;
}
}
static void window_title_command_editor_update(rct_window * w)
{
if (gCurrentTextBox.window.classification == w->classification &&
gCurrentTextBox.window.number == w->number)
{
window_update_textbox_caret();
widget_invalidate(w, gCurrentTextBox.widget_index);
}
}
static void window_title_command_editor_tool_down(rct_window * w, rct_widgetindex widgetIndex, sint32 x, sint32 y)
{
viewport_interaction_info info;
viewport_interaction_get_item_left(x, y, &info);
if (info.type == VIEWPORT_INTERACTION_ITEM_SPRITE)
{
uint16 spriteIndex = info.sprite->unknown.sprite_index;
uint16 spriteIdentifier = info.sprite->unknown.sprite_identifier;
bool validSprite = false;
if (spriteIdentifier == SPRITE_IDENTIFIER_PEEP)
{
validSprite = true;
rct_peep * peep = GET_PEEP(spriteIndex);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, peep->name_string_idx, &peep->id);
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_VEHICLE)
{
validSprite = true;
rct_vehicle * vehicle = GET_VEHICLE(spriteIndex);
Ride * ride = get_ride(vehicle->ride);
set_format_arg(16, uint32, ride->name_arguments);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, ride->name, &ride->name_arguments);
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_LITTER)
{
rct_litter * litter = &(get_sprite(spriteIndex)->litter);
if (litter->type < Util::CountOf(litterNames))
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, litterNames[litter->type], nullptr);
}
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_MISC)
{
if (info.sprite->IsBalloon())
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_SHOP_ITEM_SINGULAR_BALLOON, nullptr);
}
else if (info.sprite->IsDuck())
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_DUCK, nullptr);
}
}
if (validSprite)
{
command.SpriteIndex = spriteIndex;
window_follow_sprite(w, (size_t)command.SpriteIndex);
tool_cancel();
window_invalidate(w);
}
}
}
static void window_title_command_editor_invalidate(rct_window * w)
{
colour_scheme_update_by_class(w, WC_TITLE_EDITOR);
window_title_command_editor_widgets[WIDX_TEXTBOX_FULL].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_TEXTBOX_X].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_TEXTBOX_Y].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_INPUT_DROPDOWN].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_GET].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_SELECT_SCENARIO].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_SELECT_SPRITE].type = WWT_EMPTY;
window_title_command_editor_widgets[WIDX_VIEWPORT].type = WWT_EMPTY;
switch (command.Type)
{
case TITLE_SCRIPT_LOAD:
case TITLE_SCRIPT_SPEED:
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_DROPDOWN;
window_title_command_editor_widgets[WIDX_INPUT_DROPDOWN].type = WWT_BUTTON;
break;
case TITLE_SCRIPT_LOADSC:
window_title_command_editor_widgets[WIDX_INPUT].type = WWT_DROPDOWN;
window_title_command_editor_widgets[WIDX_SELECT_SCENARIO].type = WWT_BUTTON;
break;
case TITLE_SCRIPT_LOCATION:
window_title_command_editor_widgets[WIDX_TEXTBOX_X].type = WWT_TEXT_BOX;
window_title_command_editor_widgets[WIDX_TEXTBOX_Y].type = WWT_TEXT_BOX;
window_title_command_editor_widgets[WIDX_GET].type = WWT_BUTTON;
break;
case TITLE_SCRIPT_ROTATE:
case TITLE_SCRIPT_WAIT:
window_title_command_editor_widgets[WIDX_TEXTBOX_FULL].type = WWT_TEXT_BOX;
break;
case TITLE_SCRIPT_ZOOM:
window_title_command_editor_widgets[WIDX_GET].type = WWT_BUTTON;
window_title_command_editor_widgets[WIDX_TEXTBOX_FULL].type = WWT_TEXT_BOX;
break;
case TITLE_SCRIPT_FOLLOW:
window_title_command_editor_widgets[WIDX_SELECT_SPRITE].type = WWT_BUTTON;
window_title_command_editor_widgets[WIDX_VIEWPORT].type = WWT_VIEWPORT;
// Draw button pressed while the tool is active
if (sprite_selector_tool_is_active())
w->pressed_widgets |= (1 << WIDX_SELECT_SPRITE);
else
w->pressed_widgets &= ~(1 << WIDX_SELECT_SPRITE);
break;
}
if ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO)
{
w->disabled_widgets |= (1 << WIDX_GET) | (1 << WIDX_SELECT_SPRITE);
window_title_command_editor_widgets[WIDX_SELECT_SPRITE].tooltip = STR_TITLE_COMMAND_EDITOR_SELECT_SPRITE_TOOLTIP;
}
else
{
w->disabled_widgets &= ~((1 << WIDX_GET) | (1 << WIDX_SELECT_SPRITE));
window_title_command_editor_widgets[WIDX_SELECT_SPRITE].tooltip = STR_NONE;
}
}
static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo * dpi)
{
window_draw_widgets(w, dpi);
TITLE_COMMAND_ORDER command_info = get_command_info(command.Type);
// "Command:" label
gfx_draw_string_left(dpi, STR_TITLE_COMMAND_EDITOR_COMMAND_LABEL, nullptr, w->colours[1], w->x + WS, w->y + BY - 14);
// Command dropdown name
gfx_draw_string_left_clipped(
dpi,
command_info.nameStringId,
nullptr,
w->colours[1],
w->x + w->widgets[WIDX_COMMAND].left + 1,
w->y + w->widgets[WIDX_COMMAND].top,
w->widgets[WIDX_COMMAND_DROPDOWN].left - w->widgets[WIDX_COMMAND].left - 4);
// Label (e.g. "Location:")
gfx_draw_string_left(dpi, command_info.descStringId, nullptr, w->colours[1], w->x + WS, w->y + BY2 - 14);
if (command.Type == TITLE_SCRIPT_SPEED)
{
gfx_draw_string_left_clipped(
dpi,
SpeedNames[command.Speed - 1],
nullptr,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
if (command.Type == TITLE_SCRIPT_FOLLOW)
{
uint8 colour = COLOUR_BLACK;
rct_string_id spriteString = STR_TITLE_COMMAND_EDITOR_FORMAT_SPRITE_NAME;
if (command.SpriteIndex != SPRITE_INDEX_NULL)
{
window_draw_viewport(dpi, w);
set_format_arg(0, uintptr_t, (uintptr_t)command.SpriteName);
}
else
{
colour = w->colours[1];
spriteString = STR_TITLE_COMMAND_EDITOR_FOLLOW_NO_SPRITE;
}
gfx_set_dirty_blocks(
w->x + w->widgets[WIDX_VIEWPORT].left,
w->y + w->widgets[WIDX_VIEWPORT].top,
w->x + w->widgets[WIDX_VIEWPORT].right,
w->y + w->widgets[WIDX_VIEWPORT].bottom);
gfx_draw_string_left_clipped(
dpi,
spriteString,
gCommonFormatArgs,
colour,
w->x + w->widgets[WIDX_VIEWPORT].left + 2,
w->y + w->widgets[WIDX_VIEWPORT].top + 1,
w->widgets[WIDX_VIEWPORT].right - w->widgets[WIDX_VIEWPORT].left - 2);
}
else if (command.Type == TITLE_SCRIPT_LOAD)
{
if (command.SaveIndex == SAVE_INDEX_INVALID)
{
gfx_draw_string_left_clipped(
dpi,
STR_TITLE_COMMAND_EDITOR_NO_SAVE_SELECTED,
nullptr,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
else
{
set_format_arg(0, uintptr_t, (uintptr_t)_sequence->Saves[command.SaveIndex]);
gfx_draw_string_left_clipped(
dpi,
STR_STRING,
gCommonFormatArgs,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
}
else if (command.Type == TITLE_SCRIPT_LOADSC)
{
if (command.Scenario[0] == '\0')
{
gfx_draw_string_left_clipped(
dpi,
STR_TITLE_COMMAND_EDITOR_NO_SCENARIO_SELECTED,
nullptr,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
else
{
const char * name = "";
rct_string_id nameString = STR_STRING;
auto scenario =
GetScenarioRepository()->GetByInternalName(command.Scenario);
if (scenario != nullptr)
{
name = scenario->name;
}
else
{
nameString = STR_TITLE_COMMAND_EDITOR_MISSING_SCENARIO;
}
set_format_arg(0, uintptr_t, name);
gfx_draw_string_left_clipped(
dpi,
nameString,
gCommonFormatArgs,
w->colours[1],
w->x + w->widgets[WIDX_INPUT].left + 1,
w->y + w->widgets[WIDX_INPUT].top,
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
}
}
}