mirror of https://github.com/OpenRCT2/OpenRCT2.git
916 lines
36 KiB
C++
916 lines
36 KiB
C++
/*****************************************************************************
|
|
* 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.
|
|
*****************************************************************************/
|
|
|
|
#include "../interface/Theme.h"
|
|
|
|
#include <openrct2-ui/interface/Dropdown.h>
|
|
#include <openrct2-ui/interface/Widget.h>
|
|
#include <openrct2-ui/windows/Window.h>
|
|
#include <openrct2/Context.h>
|
|
#include <openrct2/Game.h>
|
|
#include <openrct2/Input.h>
|
|
#include <openrct2/config/Config.h>
|
|
#include <openrct2/drawing/Drawing.h>
|
|
#include <openrct2/localisation/Formatter.h>
|
|
#include <openrct2/localisation/Localisation.h>
|
|
#include <openrct2/platform/Platform.h>
|
|
#include <openrct2/sprites.h>
|
|
|
|
enum
|
|
{
|
|
WINDOW_THEMES_TAB_SETTINGS,
|
|
WINDOW_THEMES_TAB_MAIN_UI,
|
|
WINDOW_THEMES_TAB_PARK,
|
|
WINDOW_THEMES_TAB_TOOLS,
|
|
WINDOW_THEMES_TAB_RIDES_PEEPS,
|
|
WINDOW_THEMES_TAB_EDITORS,
|
|
WINDOW_THEMES_TAB_MISC,
|
|
WINDOW_THEMES_TAB_PROMPTS,
|
|
WINDOW_THEMES_TAB_FEATURES,
|
|
WINDOW_THEMES_TAB_COUNT
|
|
};
|
|
|
|
static void WindowThemesMouseup(rct_window* w, rct_widgetindex widgetIndex);
|
|
static void WindowThemesResize(rct_window* w);
|
|
static void WindowThemesMousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget);
|
|
static void WindowThemesDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
|
|
static void WindowThemesUpdate(rct_window* w);
|
|
static void WindowThemesScrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height);
|
|
static void WindowThemesScrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
|
static void WindowThemesScrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
|
|
static void WindowThemesTextinput(rct_window* w, rct_widgetindex widgetIndex, char* text);
|
|
static void WindowThemesInvalidate(rct_window* w);
|
|
static void WindowThemesPaint(rct_window* w, rct_drawpixelinfo* dpi);
|
|
static void WindowThemesScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex);
|
|
static void WindowThemesDrawTabImages(rct_drawpixelinfo* dpi, rct_window* w);
|
|
|
|
static rct_window_event_list window_themes_events([](auto& events) {
|
|
events.mouse_up = &WindowThemesMouseup;
|
|
events.resize = &WindowThemesResize;
|
|
events.mouse_down = &WindowThemesMousedown;
|
|
events.dropdown = &WindowThemesDropdown;
|
|
events.update = &WindowThemesUpdate;
|
|
events.get_scroll_size = &WindowThemesScrollgetsize;
|
|
events.scroll_mousedown = &WindowThemesScrollmousedown;
|
|
events.scroll_mouseover = &WindowThemesScrollmouseover;
|
|
events.text_input = &WindowThemesTextinput;
|
|
events.invalidate = &WindowThemesInvalidate;
|
|
events.paint = &WindowThemesPaint;
|
|
events.scroll_paint = &WindowThemesScrollpaint;
|
|
});
|
|
|
|
enum WindowThemesWidgetIdx
|
|
{
|
|
WIDX_THEMES_BACKGROUND,
|
|
WIDX_THEMES_TITLE,
|
|
WIDX_THEMES_CLOSE,
|
|
WIDX_THEMES_TAB_CONTENT_PANEL,
|
|
WIDX_THEMES_SETTINGS_TAB,
|
|
WIDX_THEMES_MAIN_UI_TAB,
|
|
WIDX_THEMES_PARK_TAB,
|
|
WIDX_THEMES_TOOLS_TAB,
|
|
WIDX_THEMES_RIDE_PEEPS_TAB,
|
|
WIDX_THEMES_EDITORS_TAB,
|
|
WIDX_THEMES_MISC_TAB,
|
|
WIDX_THEMES_PROMPTS_TAB,
|
|
WIDX_THEMES_FEATURES_TAB,
|
|
WIDX_THEMES_HEADER_WINDOW,
|
|
WIDX_THEMES_HEADER_PALETTE,
|
|
WIDX_THEMES_PRESETS,
|
|
WIDX_THEMES_PRESETS_DROPDOWN,
|
|
WIDX_THEMES_DUPLICATE_BUTTON,
|
|
WIDX_THEMES_DELETE_BUTTON,
|
|
WIDX_THEMES_RENAME_BUTTON,
|
|
WIDX_THEMES_COLOURBTN_MASK,
|
|
WIDX_THEMES_LIST,
|
|
WIDX_THEMES_RCT1_RIDE_LIGHTS,
|
|
WIDX_THEMES_RCT1_PARK_LIGHTS,
|
|
WIDX_THEMES_RCT1_SCENARIO_FONT,
|
|
WIDX_THEMES_RCT1_BOTTOM_TOOLBAR
|
|
};
|
|
|
|
static constexpr const rct_string_id WINDOW_TITLE = STR_THEMES_TITLE;
|
|
static constexpr const int32_t WW = 320;
|
|
static constexpr const int32_t WH = 107;
|
|
|
|
// clang-format off
|
|
static rct_widget window_themes_widgets[] = {
|
|
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
|
|
MakeWidget({ 0, 43}, {320, 64}, WindowWidgetType::Resize, WindowColour::Secondary ), // tab content panel
|
|
MakeTab ({ 3, 17}, STR_THEMES_TAB_SETTINGS_TIP ), // settings tab
|
|
MakeTab ({ 34, 17}, STR_THEMES_TAB_MAIN_TIP ), // main ui tab
|
|
MakeTab ({ 65, 17}, STR_THEMES_TAB_PARK_TIP ), // park tab
|
|
MakeTab ({ 96, 17}, STR_THEMES_TAB_TOOLS_TIP ), // tools tab
|
|
MakeTab ({127, 17}, STR_THEMES_TAB_RIDES_AND_GUESTS_TIP), // rides and peeps tab
|
|
MakeTab ({158, 17}, STR_THEMES_TAB_EDITORS_TIP ), // editors tab
|
|
MakeTab ({189, 17}, STR_THEMES_TAB_MISC_TIP ), // misc tab
|
|
MakeTab ({220, 17}, STR_THEMES_TAB_PROMPTS_TIP ), // prompts tab
|
|
MakeTab ({251, 17}, STR_THEMES_TAB_FEATURES_TIP ), // features tab
|
|
MakeWidget({ 5, 46}, {214, 15}, WindowWidgetType::TableHeader, WindowColour::Secondary, STR_THEMES_HEADER_WINDOW ), // Window header
|
|
MakeWidget({219, 46}, { 97, 15}, WindowWidgetType::TableHeader, WindowColour::Secondary, STR_THEMES_HEADER_PALETTE ), // Palette header
|
|
MakeWidget({125, 60}, {175, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary ), // Preset colour schemes
|
|
MakeWidget({288, 61}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH ),
|
|
MakeWidget({ 10, 82}, { 91, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_THEMES_ACTION_DUPLICATE, STR_THEMES_ACTION_DUPLICATE_TIP ), // Duplicate button
|
|
MakeWidget({110, 82}, { 91, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_TRACK_MANAGE_DELETE, STR_THEMES_ACTION_DELETE_TIP ), // Delete button
|
|
MakeWidget({210, 82}, { 91, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_TRACK_MANAGE_RENAME, STR_THEMES_ACTION_RENAME_TIP ), // Rename button
|
|
MakeWidget({ 0, 0}, { 1, 1}, WindowWidgetType::ColourBtn, WindowColour::Secondary ), // colour button mask
|
|
MakeWidget({ 3, 60}, {314, 44}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL ), // staff list
|
|
MakeWidget({ 10, 54}, {290, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_THEMES_OPTION_RCT1_RIDE_CONTROLS ), // rct1 ride lights
|
|
MakeWidget({ 10, 69}, {290, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_THEMES_OPTION_RCT1_PARK_CONTROLS ), // rct1 park lights
|
|
MakeWidget({ 10, 84}, {290, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_THEMES_OPTION_RCT1_SCENARIO_SELECTION_FONT ), // rct1 scenario font
|
|
MakeWidget({ 10, 99}, {290, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_THEMES_OPTION_RCT1_BOTTOM_TOOLBAR ), // rct1 bottom toolbar
|
|
WIDGETS_END,
|
|
};
|
|
|
|
static int32_t window_themes_tab_animation_loops[] = {
|
|
32,
|
|
32,
|
|
1,
|
|
1,
|
|
64,
|
|
32,
|
|
8,
|
|
14,
|
|
38,
|
|
};
|
|
static int32_t window_themes_tab_animation_divisor[] = {
|
|
4,
|
|
4,
|
|
1,
|
|
1,
|
|
4,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
};
|
|
static int32_t window_themes_tab_sprites[] = {
|
|
SPR_TAB_PAINT_0,
|
|
SPR_TAB_KIOSKS_AND_FACILITIES_0,
|
|
SPR_TAB_PARK_ENTRANCE,
|
|
SPR_G2_TAB_LAND,
|
|
SPR_TAB_RIDE_0,
|
|
SPR_TAB_WRENCH_0,
|
|
SPR_TAB_GEARS_0,
|
|
SPR_TAB_STAFF_OPTIONS_0,
|
|
SPR_TAB_FINANCES_MARKETING_0,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_1_classes[] = {
|
|
WC_TOP_TOOLBAR,
|
|
WC_BOTTOM_TOOLBAR,
|
|
WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR,
|
|
WC_EDITOR_TRACK_BOTTOM_TOOLBAR,
|
|
WC_TITLE_MENU,
|
|
WC_TITLE_EXIT,
|
|
WC_TITLE_OPTIONS,
|
|
WC_SCENARIO_SELECT,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_2_classes[] = {
|
|
WC_PARK_INFORMATION,
|
|
WC_FINANCES,
|
|
WC_NEW_CAMPAIGN,
|
|
WC_RESEARCH,
|
|
WC_MAP,
|
|
WC_VIEWPORT,
|
|
WC_RECENT_NEWS,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_3_classes[] = {
|
|
WC_LAND,
|
|
WC_WATER,
|
|
WC_CLEAR_SCENERY,
|
|
WC_LAND_RIGHTS,
|
|
WC_SCENERY,
|
|
WC_SCENERY_SCATTER,
|
|
WC_FOOTPATH,
|
|
WC_RIDE_CONSTRUCTION,
|
|
WC_TRACK_DESIGN_PLACE,
|
|
WC_CONSTRUCT_RIDE,
|
|
WC_TRACK_DESIGN_LIST,
|
|
WC_PATROL_AREA,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_4_classes[] = {
|
|
WC_RIDE,
|
|
WC_RIDE_LIST,
|
|
WC_PEEP,
|
|
WC_GUEST_LIST,
|
|
WC_STAFF,
|
|
WC_STAFF_LIST,
|
|
WC_BANNER,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_5_classes[] = {
|
|
WC_EDITOR_OBJECT_SELECTION,
|
|
WC_EDITOR_INVENTION_LIST,
|
|
WC_EDITOR_SCENARIO_OPTIONS,
|
|
WC_EDITOR_OBJECTIVE_OPTIONS,
|
|
WC_MAPGEN,
|
|
WC_MANAGE_TRACK_DESIGN,
|
|
WC_INSTALL_TRACK,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_6_classes[] = {
|
|
WC_CHEATS,
|
|
WC_TILE_INSPECTOR,
|
|
WC_VIEW_CLIPPING,
|
|
WC_TRANSPARENCY,
|
|
WC_THEMES,
|
|
WC_OPTIONS,
|
|
WC_KEYBOARD_SHORTCUT_LIST,
|
|
WC_CHANGE_KEYBOARD_SHORTCUT,
|
|
WC_LOADSAVE,
|
|
WC_ABOUT,
|
|
WC_CHANGELOG,
|
|
WC_SERVER_LIST,
|
|
WC_MULTIPLAYER,
|
|
WC_PLAYER,
|
|
WC_CHAT,
|
|
WC_CONSOLE,
|
|
};
|
|
|
|
static rct_windowclass window_themes_tab_7_classes[] = {
|
|
WC_SAVE_PROMPT,
|
|
WC_DEMOLISH_RIDE_PROMPT,
|
|
WC_FIRE_PROMPT,
|
|
WC_TRACK_DELETE_PROMPT,
|
|
WC_LOADSAVE_OVERWRITE_PROMPT,
|
|
WC_NETWORK_STATUS,
|
|
};
|
|
// clang-format on
|
|
|
|
static rct_windowclass* window_themes_tab_classes[] = {
|
|
nullptr,
|
|
window_themes_tab_1_classes,
|
|
window_themes_tab_2_classes,
|
|
window_themes_tab_3_classes,
|
|
window_themes_tab_4_classes,
|
|
window_themes_tab_5_classes,
|
|
window_themes_tab_6_classes,
|
|
window_themes_tab_7_classes,
|
|
};
|
|
|
|
static uint8_t _selected_tab = 0;
|
|
static int16_t _colour_index_1 = -1;
|
|
static int8_t _colour_index_2 = -1;
|
|
static constexpr const uint8_t _row_height = 32;
|
|
static constexpr const uint8_t _button_offset_x = 220;
|
|
static constexpr const uint8_t _button_offset_y = 3;
|
|
static constexpr const uint8_t _check_offset_y = 3 + 12 + 2;
|
|
|
|
static void WindowThemesInitVars()
|
|
{
|
|
_selected_tab = WINDOW_THEMES_TAB_SETTINGS;
|
|
}
|
|
|
|
static rct_windowclass GetWindowClassTabIndex(int32_t index)
|
|
{
|
|
rct_windowclass* classes = window_themes_tab_classes[_selected_tab];
|
|
return classes[index];
|
|
}
|
|
|
|
static int32_t GetColourSchemeTabCount()
|
|
{
|
|
switch (_selected_tab)
|
|
{
|
|
case 1:
|
|
return sizeof(window_themes_tab_1_classes);
|
|
case 2:
|
|
return sizeof(window_themes_tab_2_classes);
|
|
case 3:
|
|
return sizeof(window_themes_tab_3_classes);
|
|
case 4:
|
|
return sizeof(window_themes_tab_4_classes);
|
|
case 5:
|
|
return sizeof(window_themes_tab_5_classes);
|
|
case 6:
|
|
return sizeof(window_themes_tab_6_classes);
|
|
case 7:
|
|
return sizeof(window_themes_tab_7_classes);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void WindowThemesDrawTabImages(rct_drawpixelinfo* dpi, rct_window* w)
|
|
{
|
|
for (int32_t i = 0; i < WINDOW_THEMES_TAB_COUNT; i++)
|
|
{
|
|
int32_t sprite_idx = window_themes_tab_sprites[i];
|
|
if (_selected_tab == i)
|
|
sprite_idx += w->frame_no / window_themes_tab_animation_divisor[_selected_tab];
|
|
gfx_draw_sprite(
|
|
dpi, sprite_idx,
|
|
w->windowPos
|
|
+ ScreenCoordsXY{ w->widgets[WIDX_THEMES_SETTINGS_TAB + i].left, w->widgets[WIDX_THEMES_SETTINGS_TAB + i].top },
|
|
0);
|
|
}
|
|
}
|
|
|
|
rct_window* WindowThemesOpen()
|
|
{
|
|
rct_window* window;
|
|
|
|
// Check if window is already open
|
|
window = window_bring_to_front_by_class(WC_THEMES);
|
|
if (window != nullptr)
|
|
return window;
|
|
|
|
window = WindowCreateAutoPos(320, 107, &window_themes_events, WC_THEMES, WF_10 | WF_RESIZABLE);
|
|
window->widgets = window_themes_widgets;
|
|
|
|
WindowThemesInitVars();
|
|
|
|
WindowInitScrollWidgets(*window);
|
|
window->list_information_type = 0;
|
|
_colour_index_1 = -1;
|
|
_colour_index_2 = -1;
|
|
window->min_width = 320;
|
|
window->min_height = 107;
|
|
window->max_width = 320;
|
|
window->max_height = 107;
|
|
|
|
return window;
|
|
}
|
|
|
|
static void WindowThemesMouseup(rct_window* w, rct_widgetindex widgetIndex)
|
|
{
|
|
size_t activeAvailableThemeIndex;
|
|
const utf8* activeThemeName;
|
|
|
|
switch (widgetIndex)
|
|
{
|
|
case WIDX_THEMES_CLOSE:
|
|
window_close(w);
|
|
break;
|
|
case WIDX_THEMES_DUPLICATE_BUTTON:;
|
|
activeAvailableThemeIndex = ThemeManagerGetAvailableThemeIndex();
|
|
activeThemeName = ThemeManagerGetAvailableThemeName(activeAvailableThemeIndex);
|
|
WindowTextInputOpen(
|
|
w, widgetIndex, STR_THEMES_ACTION_DUPLICATE, STR_THEMES_PROMPT_ENTER_THEME_NAME, {}, STR_STRING,
|
|
reinterpret_cast<uintptr_t>(activeThemeName), 64);
|
|
break;
|
|
case WIDX_THEMES_DELETE_BUTTON:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
ThemeDelete();
|
|
}
|
|
break;
|
|
case WIDX_THEMES_RENAME_BUTTON:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
activeAvailableThemeIndex = ThemeManagerGetAvailableThemeIndex();
|
|
activeThemeName = ThemeManagerGetAvailableThemeName(activeAvailableThemeIndex);
|
|
WindowTextInputOpen(
|
|
w, widgetIndex, STR_TRACK_MANAGE_RENAME, STR_THEMES_PROMPT_ENTER_THEME_NAME, {}, STR_STRING,
|
|
reinterpret_cast<uintptr_t>(activeThemeName), 64);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void WindowThemesResize(rct_window* w)
|
|
{
|
|
if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS)
|
|
{
|
|
w->min_width = 320;
|
|
w->min_height = 107;
|
|
w->max_width = 320;
|
|
w->max_height = 107;
|
|
|
|
if (w->width < w->min_width)
|
|
{
|
|
w->width = w->min_width;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->height < w->min_height)
|
|
{
|
|
w->height = w->min_height;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->width > w->max_width)
|
|
{
|
|
w->width = w->max_width;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->height > w->max_height)
|
|
{
|
|
w->height = w->max_height;
|
|
gfx_invalidate_screen();
|
|
}
|
|
}
|
|
else if (_selected_tab == WINDOW_THEMES_TAB_FEATURES)
|
|
{
|
|
w->min_width = 320;
|
|
w->min_height = 122;
|
|
w->max_width = 320;
|
|
w->max_height = 122;
|
|
|
|
if (w->width < w->min_width)
|
|
{
|
|
w->width = w->min_width;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->height < w->min_height)
|
|
{
|
|
w->height = w->min_height;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->width > w->max_width)
|
|
{
|
|
w->width = w->max_width;
|
|
gfx_invalidate_screen();
|
|
}
|
|
if (w->height > w->max_height)
|
|
{
|
|
w->height = w->max_height;
|
|
gfx_invalidate_screen();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
w->min_width = 320;
|
|
w->min_height = 270;
|
|
w->max_width = 320;
|
|
w->max_height = 450;
|
|
|
|
if (w->width < w->min_width)
|
|
{
|
|
w->width = w->min_width;
|
|
w->Invalidate();
|
|
}
|
|
if (w->height < w->min_height)
|
|
{
|
|
w->height = w->min_height;
|
|
w->Invalidate();
|
|
}
|
|
if (w->width > w->max_width)
|
|
{
|
|
w->width = w->max_width;
|
|
w->Invalidate();
|
|
}
|
|
if (w->height > w->max_height)
|
|
{
|
|
w->height = w->max_height;
|
|
w->Invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void WindowThemesMousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
|
|
{
|
|
int16_t newSelectedTab;
|
|
int32_t num_items;
|
|
|
|
switch (widgetIndex)
|
|
{
|
|
case WIDX_THEMES_SETTINGS_TAB:
|
|
case WIDX_THEMES_MAIN_UI_TAB:
|
|
case WIDX_THEMES_PARK_TAB:
|
|
case WIDX_THEMES_TOOLS_TAB:
|
|
case WIDX_THEMES_RIDE_PEEPS_TAB:
|
|
case WIDX_THEMES_EDITORS_TAB:
|
|
case WIDX_THEMES_MISC_TAB:
|
|
case WIDX_THEMES_PROMPTS_TAB:
|
|
case WIDX_THEMES_FEATURES_TAB:
|
|
newSelectedTab = widgetIndex - WIDX_THEMES_SETTINGS_TAB;
|
|
if (_selected_tab == newSelectedTab)
|
|
break;
|
|
_selected_tab = static_cast<uint8_t>(newSelectedTab);
|
|
w->scrolls[0].v_top = 0;
|
|
w->frame_no = 0;
|
|
window_event_resize_call(w);
|
|
w->Invalidate();
|
|
break;
|
|
case WIDX_THEMES_PRESETS_DROPDOWN:
|
|
ThemeManagerLoadAvailableThemes();
|
|
num_items = static_cast<int32_t>(ThemeManagerGetNumAvailableThemes());
|
|
|
|
widget--;
|
|
for (int32_t i = 0; i < num_items; i++)
|
|
{
|
|
gDropdownItems[i].Format = STR_OPTIONS_DROPDOWN_ITEM;
|
|
gDropdownItems[i].Args = reinterpret_cast<uintptr_t>(ThemeManagerGetAvailableThemeName(i));
|
|
}
|
|
|
|
WindowDropdownShowTextCustomWidth(
|
|
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1], 0,
|
|
Dropdown::Flag::StayOpen, num_items, widget->width() - 3);
|
|
|
|
Dropdown::SetChecked(static_cast<int32_t>(ThemeManagerGetAvailableThemeIndex()), true);
|
|
break;
|
|
case WIDX_THEMES_RCT1_RIDE_LIGHTS:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
ThemeSetFlags(ThemeGetFlags() ^ UITHEME_FLAG_USE_LIGHTS_RIDE);
|
|
ThemeSave();
|
|
window_invalidate_all();
|
|
}
|
|
break;
|
|
case WIDX_THEMES_RCT1_PARK_LIGHTS:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
ThemeSetFlags(ThemeGetFlags() ^ UITHEME_FLAG_USE_LIGHTS_PARK);
|
|
ThemeSave();
|
|
window_invalidate_all();
|
|
}
|
|
break;
|
|
case WIDX_THEMES_RCT1_SCENARIO_FONT:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
ThemeSetFlags(ThemeGetFlags() ^ UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT);
|
|
ThemeSave();
|
|
window_invalidate_all();
|
|
}
|
|
break;
|
|
case WIDX_THEMES_RCT1_BOTTOM_TOOLBAR:
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_NONE, {});
|
|
}
|
|
else
|
|
{
|
|
ThemeSetFlags(ThemeGetFlags() ^ UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR);
|
|
ThemeSave();
|
|
window_invalidate_all();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void WindowThemesDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
|
|
{
|
|
switch (widgetIndex)
|
|
{
|
|
case WIDX_THEMES_LIST:
|
|
if (dropdownIndex != -1)
|
|
{
|
|
rct_windowclass wc = GetWindowClassTabIndex(_colour_index_1);
|
|
uint8_t colour = ThemeGetColour(wc, _colour_index_2);
|
|
colour = (colour & COLOUR_FLAG_TRANSLUCENT) | dropdownIndex;
|
|
ThemeSetColour(wc, _colour_index_2, colour);
|
|
ColourSchemeUpdateAll();
|
|
window_invalidate_all();
|
|
_colour_index_1 = -1;
|
|
_colour_index_2 = -1;
|
|
}
|
|
break;
|
|
case WIDX_THEMES_PRESETS_DROPDOWN:
|
|
if (dropdownIndex != -1)
|
|
{
|
|
ThemeManagerSetActiveAvailableTheme(dropdownIndex);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WindowThemesUpdate(rct_window* w)
|
|
{
|
|
w->frame_no++;
|
|
if (w->frame_no >= window_themes_tab_animation_loops[_selected_tab])
|
|
w->frame_no = 0;
|
|
|
|
widget_invalidate(w, WIDX_THEMES_SETTINGS_TAB + _selected_tab);
|
|
}
|
|
|
|
void WindowThemesScrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height)
|
|
{
|
|
if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS || _selected_tab == WINDOW_THEMES_TAB_FEATURES)
|
|
return;
|
|
|
|
int32_t scrollHeight = GetColourSchemeTabCount() * _row_height;
|
|
int32_t i = scrollHeight - window_themes_widgets[WIDX_THEMES_LIST].bottom + window_themes_widgets[WIDX_THEMES_LIST].top
|
|
+ 21;
|
|
if (i < 0)
|
|
i = 0;
|
|
if (i < w->scrolls[0].v_top)
|
|
{
|
|
w->scrolls[0].v_top = i;
|
|
w->Invalidate();
|
|
}
|
|
|
|
*width = 420;
|
|
*height = scrollHeight;
|
|
}
|
|
|
|
void WindowThemesScrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
|
|
{
|
|
if (screenCoords.y / _row_height < GetColourSchemeTabCount())
|
|
{
|
|
int32_t y2 = screenCoords.y % _row_height;
|
|
_colour_index_1 = screenCoords.y / _row_height;
|
|
_colour_index_2 = ((screenCoords.x - _button_offset_x) / 12);
|
|
|
|
rct_windowclass wc = GetWindowClassTabIndex(_colour_index_1);
|
|
int32_t numColours = ThemeDescGetNumColours(wc);
|
|
if (_colour_index_2 < numColours)
|
|
{
|
|
if (screenCoords.x >= _button_offset_x && screenCoords.x < _button_offset_x + 12 * 6 && y2 >= _button_offset_y
|
|
&& y2 < _button_offset_y + 11)
|
|
{
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_THEMES_DESC_CANT_CHANGE_THIS_THEME, {});
|
|
}
|
|
else
|
|
{
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WindowWidgetType::ColourBtn;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].left = _button_offset_x + _colour_index_2 * 12
|
|
+ window_themes_widgets[WIDX_THEMES_LIST].left;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].top = _colour_index_1 * _row_height + _button_offset_y
|
|
- w->scrolls[0].v_top + window_themes_widgets[WIDX_THEMES_LIST].top;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].right = window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK]
|
|
.left
|
|
+ 12;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].bottom = window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK]
|
|
.top
|
|
+ 12;
|
|
|
|
uint8_t colour = ThemeGetColour(wc, _colour_index_2);
|
|
WindowDropdownShowColour(w, &(window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK]), w->colours[1], colour);
|
|
widget_invalidate(w, WIDX_THEMES_LIST);
|
|
}
|
|
}
|
|
else if (
|
|
screenCoords.x >= _button_offset_x && screenCoords.x < _button_offset_x + 12 * 6 - 1 && y2 >= _check_offset_y
|
|
&& y2 < _check_offset_y + 11)
|
|
{
|
|
if (ThemeGetFlags() & UITHEME_FLAG_PREDEFINED)
|
|
{
|
|
context_show_error(STR_THEMES_ERR_CANT_CHANGE_THIS_THEME, STR_THEMES_DESC_CANT_CHANGE_THIS_THEME, {});
|
|
}
|
|
else
|
|
{
|
|
uint8_t colour = ThemeGetColour(wc, _colour_index_2);
|
|
if (colour & COLOUR_FLAG_TRANSLUCENT)
|
|
{
|
|
colour &= ~COLOUR_FLAG_TRANSLUCENT;
|
|
}
|
|
else
|
|
{
|
|
colour |= COLOUR_FLAG_TRANSLUCENT;
|
|
}
|
|
ThemeSetColour(wc, _colour_index_2, colour);
|
|
ColourSchemeUpdateAll();
|
|
window_invalidate_all();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WindowThemesScrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
|
|
{
|
|
}
|
|
|
|
static void WindowThemesTextinput(rct_window* w, rct_widgetindex widgetIndex, char* text)
|
|
{
|
|
if (text == nullptr || text[0] == 0)
|
|
return;
|
|
|
|
switch (widgetIndex)
|
|
{
|
|
case WIDX_THEMES_DUPLICATE_BUTTON:
|
|
case WIDX_THEMES_RENAME_BUTTON:
|
|
if (Platform::IsFilenameValid(text))
|
|
{
|
|
if (ThemeGetIndexForName(text) == SIZE_MAX)
|
|
{
|
|
if (widgetIndex == WIDX_THEMES_DUPLICATE_BUTTON)
|
|
{
|
|
ThemeDuplicate(text);
|
|
}
|
|
else
|
|
{
|
|
ThemeRename(text);
|
|
}
|
|
w->Invalidate();
|
|
}
|
|
else
|
|
{
|
|
context_show_error(STR_THEMES_ERR_NAME_ALREADY_EXISTS, STR_NONE, {});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
context_show_error(STR_ERROR_INVALID_CHARACTERS, STR_NONE, {});
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WindowThemesInvalidate(rct_window* w)
|
|
{
|
|
int32_t pressed_widgets = w->pressed_widgets
|
|
& ~((1LL << WIDX_THEMES_SETTINGS_TAB) | (1LL << WIDX_THEMES_MAIN_UI_TAB) | (1LL << WIDX_THEMES_PARK_TAB)
|
|
| (1LL << WIDX_THEMES_TOOLS_TAB) | (1LL << WIDX_THEMES_RIDE_PEEPS_TAB) | (1LL << WIDX_THEMES_EDITORS_TAB)
|
|
| (1LL << WIDX_THEMES_MISC_TAB) | (1LL << WIDX_THEMES_PROMPTS_TAB) | (1LL << WIDX_THEMES_FEATURES_TAB));
|
|
rct_widgetindex widgetIndex = _selected_tab + WIDX_THEMES_SETTINGS_TAB;
|
|
|
|
w->pressed_widgets = pressed_widgets | (1 << widgetIndex);
|
|
|
|
if (window_find_by_class(WC_DROPDOWN) == nullptr)
|
|
{
|
|
_colour_index_1 = -1;
|
|
_colour_index_2 = -1;
|
|
}
|
|
|
|
window_themes_widgets[WIDX_THEMES_BACKGROUND].right = w->width - 1;
|
|
window_themes_widgets[WIDX_THEMES_BACKGROUND].bottom = w->height - 1;
|
|
window_themes_widgets[WIDX_THEMES_TAB_CONTENT_PANEL].right = w->width - 1;
|
|
window_themes_widgets[WIDX_THEMES_TAB_CONTENT_PANEL].bottom = w->height - 1;
|
|
window_themes_widgets[WIDX_THEMES_TITLE].right = w->width - 2;
|
|
window_themes_widgets[WIDX_THEMES_CLOSE].left = w->width - 2 - 0x0B;
|
|
window_themes_widgets[WIDX_THEMES_CLOSE].right = w->width - 2 - 0x0B + 0x0A;
|
|
window_themes_widgets[WIDX_THEMES_LIST].right = w->width - 4;
|
|
window_themes_widgets[WIDX_THEMES_LIST].bottom = w->height - 0x0F;
|
|
|
|
if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS)
|
|
{
|
|
window_themes_widgets[WIDX_THEMES_HEADER_WINDOW].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_HEADER_PALETTE].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_LIST].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_RIDE_LIGHTS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_PARK_LIGHTS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_SCENARIO_FONT].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_BOTTOM_TOOLBAR].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_DUPLICATE_BUTTON].type = WindowWidgetType::Button;
|
|
window_themes_widgets[WIDX_THEMES_DELETE_BUTTON].type = WindowWidgetType::Button;
|
|
window_themes_widgets[WIDX_THEMES_RENAME_BUTTON].type = WindowWidgetType::Button;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS].type = WindowWidgetType::DropdownMenu;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WindowWidgetType::Button;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WindowWidgetType::Empty;
|
|
}
|
|
else if (_selected_tab == WINDOW_THEMES_TAB_FEATURES)
|
|
{
|
|
window_themes_widgets[WIDX_THEMES_HEADER_WINDOW].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_HEADER_PALETTE].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_LIST].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_RIDE_LIGHTS].type = WindowWidgetType::Checkbox;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_PARK_LIGHTS].type = WindowWidgetType::Checkbox;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_SCENARIO_FONT].type = WindowWidgetType::Checkbox;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_BOTTOM_TOOLBAR].type = WindowWidgetType::Checkbox;
|
|
window_themes_widgets[WIDX_THEMES_DUPLICATE_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_DELETE_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RENAME_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WindowWidgetType::Empty;
|
|
|
|
WidgetSetCheckboxValue(*w, WIDX_THEMES_RCT1_RIDE_LIGHTS, ThemeGetFlags() & UITHEME_FLAG_USE_LIGHTS_RIDE);
|
|
WidgetSetCheckboxValue(*w, WIDX_THEMES_RCT1_PARK_LIGHTS, ThemeGetFlags() & UITHEME_FLAG_USE_LIGHTS_PARK);
|
|
WidgetSetCheckboxValue(
|
|
*w, WIDX_THEMES_RCT1_SCENARIO_FONT, ThemeGetFlags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT);
|
|
WidgetSetCheckboxValue(*w, WIDX_THEMES_RCT1_BOTTOM_TOOLBAR, ThemeGetFlags() & UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR);
|
|
}
|
|
else
|
|
{
|
|
window_themes_widgets[WIDX_THEMES_HEADER_WINDOW].type = WindowWidgetType::TableHeader;
|
|
window_themes_widgets[WIDX_THEMES_HEADER_PALETTE].type = WindowWidgetType::TableHeader;
|
|
window_themes_widgets[WIDX_THEMES_LIST].type = WindowWidgetType::Scroll;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_RIDE_LIGHTS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_PARK_LIGHTS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_SCENARIO_FONT].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RCT1_BOTTOM_TOOLBAR].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_DUPLICATE_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_DELETE_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_RENAME_BUTTON].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WindowWidgetType::Empty;
|
|
window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WindowWidgetType::Empty;
|
|
}
|
|
}
|
|
|
|
void WindowThemesPaint(rct_window* w, rct_drawpixelinfo* dpi)
|
|
{
|
|
// Widgets
|
|
WindowDrawWidgets(*w, dpi);
|
|
WindowThemesDrawTabImages(dpi, w);
|
|
|
|
if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS)
|
|
{
|
|
DrawTextBasic(
|
|
dpi, w->windowPos + ScreenCoordsXY{ 10, window_themes_widgets[WIDX_THEMES_PRESETS].top + 1 },
|
|
STR_THEMES_LABEL_CURRENT_THEME, {}, { w->colours[1] });
|
|
|
|
size_t activeAvailableThemeIndex = ThemeManagerGetAvailableThemeIndex();
|
|
const utf8* activeThemeName = ThemeManagerGetAvailableThemeName(activeAvailableThemeIndex);
|
|
auto ft = Formatter();
|
|
ft.Add<const utf8*>(activeThemeName);
|
|
|
|
auto screenPos = w->windowPos
|
|
+ ScreenCoordsXY{ window_themes_widgets[WIDX_THEMES_PRESETS].left + 1,
|
|
window_themes_widgets[WIDX_THEMES_PRESETS].top };
|
|
auto width = w->windowPos.x + window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].left
|
|
- window_themes_widgets[WIDX_THEMES_PRESETS].left - 4;
|
|
|
|
DrawTextEllipsised(dpi, screenPos, width, STR_STRING, ft, { w->colours[1] });
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BD785
|
|
*/
|
|
void WindowThemesScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex)
|
|
{
|
|
ScreenCoordsXY screenCoords;
|
|
|
|
if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS || _selected_tab == WINDOW_THEMES_TAB_FEATURES)
|
|
return;
|
|
|
|
if ((w->colours[1] & 0x80) == 0)
|
|
// gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1,
|
|
// ColourMapA[w->colours[1]].mid_light);
|
|
gfx_clear(dpi, ColourMapA[w->colours[1]].mid_light);
|
|
screenCoords.y = 0;
|
|
for (int32_t i = 0; i < GetColourSchemeTabCount(); i++)
|
|
{
|
|
if (screenCoords.y > dpi->y + dpi->height)
|
|
{
|
|
break;
|
|
}
|
|
if (screenCoords.y + _row_height >= dpi->y)
|
|
{
|
|
if (i + 1 < GetColourSchemeTabCount())
|
|
{
|
|
int32_t colour = w->colours[1];
|
|
|
|
auto leftTop = ScreenCoordsXY{ 0, screenCoords.y + _row_height - 2 };
|
|
auto rightBottom = ScreenCoordsXY{ window_themes_widgets[WIDX_THEMES_LIST].right,
|
|
screenCoords.y + _row_height - 2 };
|
|
auto yPixelOffset = ScreenCoordsXY{ 0, 1 };
|
|
|
|
if (colour & COLOUR_FLAG_TRANSLUCENT)
|
|
{
|
|
translucent_window_palette windowPalette = TranslucentWindowPalettes[BASE_COLOUR(colour)];
|
|
|
|
gfx_filter_rect(dpi, { leftTop, rightBottom }, windowPalette.highlight);
|
|
gfx_filter_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, windowPalette.shadow);
|
|
}
|
|
else
|
|
{
|
|
colour = ColourMapA[w->colours[1]].mid_dark;
|
|
gfx_fill_rect(dpi, { leftTop, rightBottom }, colour);
|
|
|
|
colour = ColourMapA[w->colours[1]].lightest;
|
|
gfx_fill_rect(dpi, { leftTop + yPixelOffset, rightBottom + yPixelOffset }, colour);
|
|
}
|
|
}
|
|
|
|
rct_windowclass wc = GetWindowClassTabIndex(i);
|
|
int32_t numColours = ThemeDescGetNumColours(wc);
|
|
for (uint8_t j = 0; j < numColours; j++)
|
|
{
|
|
DrawTextBasic(dpi, { 2, screenCoords.y + 4 }, ThemeDescGetName(wc), {}, { w->colours[1] });
|
|
|
|
uint8_t colour = ThemeGetColour(wc, j);
|
|
uint32_t image = SPRITE_ID_PALETTE_COLOUR_1(colour & ~COLOUR_FLAG_TRANSLUCENT) | SPR_PALETTE_BTN;
|
|
if (i == _colour_index_1 && j == _colour_index_2)
|
|
{
|
|
image = SPRITE_ID_PALETTE_COLOUR_1(colour & ~COLOUR_FLAG_TRANSLUCENT) | SPR_PALETTE_BTN_PRESSED;
|
|
}
|
|
gfx_draw_sprite(dpi, image, { _button_offset_x + 12 * j, screenCoords.y + _button_offset_y }, 0);
|
|
|
|
ScreenCoordsXY topLeft{ _button_offset_x + 12 * j, screenCoords.y + _check_offset_y };
|
|
ScreenCoordsXY bottomRight{ _button_offset_x + 12 * j + 9, screenCoords.y + _check_offset_y + 10 };
|
|
gfx_fill_rect_inset(dpi, { topLeft, bottomRight }, w->colours[1], INSET_RECT_F_E0);
|
|
if (colour & COLOUR_FLAG_TRANSLUCENT)
|
|
{
|
|
gfx_draw_string(
|
|
dpi, topLeft, static_cast<const char*>(CheckBoxMarkString),
|
|
{ static_cast<colour_t>(w->colours[1] & 0x7F), FontSpriteBase::MEDIUM_DARK });
|
|
}
|
|
}
|
|
}
|
|
|
|
screenCoords.y += _row_height;
|
|
}
|
|
}
|