diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 16dfe52ca6..73fe4a6021 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -53,7 +53,6 @@ - @@ -110,6 +109,7 @@ + @@ -179,7 +179,6 @@ - diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index df0b6eb8d6..3fddff8512 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -453,12 +453,6 @@ Source\Network - - Source\Interface - - - Source\Windows - Source\Windows @@ -586,6 +580,7 @@ Source\Interface + diff --git a/src/config.h b/src/config.h index 60f733f26c..6372bfeecd 100644 --- a/src/config.h +++ b/src/config.h @@ -253,13 +253,6 @@ typedef struct { bool guest_died; } notification_configuration; -typedef struct theme_window { - uint8 colours[6]; - - // Define any other settings for all windows here - -} theme_window; - // Define structures for any other settings here typedef struct { uint8 rct1_ride_lights; diff --git a/src/core/Path.cpp b/src/core/Path.cpp index 90b8e0f031..514f53ddeb 100644 --- a/src/core/Path.cpp +++ b/src/core/Path.cpp @@ -18,11 +18,26 @@ namespace Path return safe_strcat_path(buffer, src, bufferSize); } + utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path) + { + const char pathSeperator = platform_get_path_separator(); + size_t lastPathSepIndex = String::LastIndexOf(path, pathSeperator); + if (lastPathSepIndex == SIZE_MAX) + { + return String::Set(buffer, bufferSize, String::Empty); + } + + size_t copyLength = Math::Min(lastPathSepIndex, bufferSize - 1); + Memory::Copy(buffer, path, copyLength); + buffer[copyLength] = '\0'; + return buffer; + } + utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path) { const utf8 * lastDot = nullptr; const utf8 * ch = path; - for (; ch != '\0'; ch++) + for (; *ch != '\0'; ch++) { if (*ch == '.') { diff --git a/src/core/Path.hpp b/src/core/Path.hpp index 1186f86e51..b3aa163f72 100644 --- a/src/core/Path.hpp +++ b/src/core/Path.hpp @@ -8,6 +8,7 @@ extern "C" namespace Path { utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path); utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path); utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath); bool Equals(const utf8 * a, const utf8 * b); diff --git a/src/core/String.cpp b/src/core/String.cpp index ba000bc7f7..ca1a7f97a9 100644 --- a/src/core/String.cpp +++ b/src/core/String.cpp @@ -10,6 +10,11 @@ extern "C" namespace String { + bool IsNullOrEmpty(const utf8 * str) + { + return str == nullptr || str[0] == '\0'; + } + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase) { if (a == b) return true; @@ -51,6 +56,28 @@ namespace String } } + size_t LastIndexOf(const utf8 * str, utf8 match) + { + const utf8 * lastOccurance = nullptr; + const utf8 * ch = str; + for (; ch != '\0'; ch++) + { + if (*ch == match) + { + lastOccurance = ch; + } + } + + if (lastOccurance == nullptr) + { + return SIZE_MAX; + } + else + { + return (size_t)(lastOccurance - str); + } + } + size_t LengthOf(const utf8 * str) { return utf8_length(str); @@ -137,7 +164,7 @@ namespace String return replacement; } - utf8 * DiscardDuplicate(utf8 * * ptr, utf8 * replacement) + utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement) { return DiscardUse(ptr, String::Duplicate(replacement)); } diff --git a/src/core/String.hpp b/src/core/String.hpp index c286ebd27e..7af30db4f4 100644 --- a/src/core/String.hpp +++ b/src/core/String.hpp @@ -9,8 +9,10 @@ namespace String { constexpr utf8 * Empty = ""; + bool IsNullOrEmpty(const utf8 * str); bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false); bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase = false); + size_t LastIndexOf(const utf8 * str, utf8 match); /** * Gets the length of the given string in codepoints. @@ -37,7 +39,7 @@ namespace String /** * Helper method to free the string a string pointer points to and set it to a copy of a replacement string. */ - utf8 * DiscardDuplicate(utf8 * * ptr, utf8 * replacement); + utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement); utf8 * SkipBOM(utf8 * buffer); const utf8 * SkipBOM(const utf8 * buffer); diff --git a/src/interface/Theme.cpp b/src/interface/Theme.cpp index f40961a88c..6459751713 100644 --- a/src/interface/Theme.cpp +++ b/src/interface/Theme.cpp @@ -3,6 +3,7 @@ extern "C" { #include "../common.h" + #include "../config.h" #include "themes.h" #include "window.h" } @@ -55,6 +56,7 @@ public: UITheme(const UITheme & name); ~UITheme(); + void SetName(const utf8 * name); const UIThemeWindowEntry * GetEntry(rct_windowclass windowClass) const; void SetEntry(const UIThemeWindowEntry * entry); void RemoveEntry(rct_windowclass windowClass); @@ -290,6 +292,11 @@ UITheme::~UITheme() Memory::Free(Name); } +void UITheme::SetName(const utf8 * name) +{ + String::DiscardDuplicate(&Name, name); +} + const UIThemeWindowEntry * UITheme::GetEntry(rct_windowclass windowClass) const { for (size_t i = 0; i < Entries.GetCount(); i++) @@ -363,7 +370,7 @@ bool UITheme::WriteToFile(const utf8 * path) const bool result; try { - Json::WriteToFile(path, jsonTheme, JSON_INDENT(4)); + Json::WriteToFile(path, jsonTheme, JSON_INDENT(4) | JSON_PRESERVE_ORDER); result = true; } catch (Exception ex) @@ -386,10 +393,6 @@ UITheme * UITheme::FromJson(const json_t * json) json_t * jsonEntries = json_object_get(json, "entries"); size_t numEntries = json_object_size(jsonEntries); - if (numEntries == 0) - { - ThrowThemeLoadException(); - } UITheme * result = nullptr; try @@ -441,6 +444,7 @@ UITheme * UITheme::FromFile(const utf8 * path) } catch (Exception ex) { + log_error("Unable to read theme: %s", path); result = nullptr; } @@ -470,15 +474,17 @@ namespace ThemeManager struct AvailableTheme { utf8 Path[MAX_PATH]; - utf8 Name[64]; + utf8 Name[96]; }; - const utf8 * CurrentThemePath; + utf8 * CurrentThemePath; UITheme * CurrentTheme; List AvailableThemes; size_t ActiveAvailableThemeIndex = SIZE_MAX; size_t NumPredefinedThemes = 0; + void GetThemeFileName(utf8 * buffer, size_t bufferSize, const utf8 * name); + void GetAvailableThemes(List * outThemes) { Guard::ArgumentNotNull(outThemes); @@ -500,33 +506,44 @@ namespace ThemeManager platform_get_user_directory(themesPattern, "themes"); Path::Append(themesPattern, sizeof(themesPattern), "*.json"); - utf8 path[MAX_PATH]; int handle = platform_enumerate_files_begin(themesPattern); - while (platform_enumerate_directories_next(handle, path)) + if (handle != INVALID_HANDLE) { - AvailableTheme theme; - String::Set(theme.Path, sizeof(theme.Path), path); - Path::GetFileNameWithoutExtension(theme.Path, sizeof(theme.Path), path); - outThemes->Add(theme); - - if (Path::Equals(CurrentThemePath, path)) + file_info fileInfo; + while (platform_enumerate_files_next(handle, &fileInfo)) { - ActiveAvailableThemeIndex = outThemes->GetCount() - 1; + AvailableTheme theme; + Path::GetFileNameWithoutExtension(theme.Name, sizeof(theme.Name), fileInfo.path); + GetThemeFileName(theme.Path, sizeof(theme.Path), theme.Name); + + outThemes->Add(theme); + + if (Path::Equals(CurrentThemePath, fileInfo.path)) + { + ActiveAvailableThemeIndex = outThemes->GetCount() - 1; + } } + platform_enumerate_files_end(handle); } } void LoadTheme(UITheme * theme) { + if (CurrentTheme == theme) + { + return; + } + if (CurrentTheme != nullptr) { - if (!(theme->Flags & UITHEME_FLAG_PREDEFINED)) + if (!(CurrentTheme->Flags & UITHEME_FLAG_PREDEFINED)) { delete CurrentTheme; } } CurrentTheme = theme; + String::DiscardUse(&CurrentThemePath, nullptr); gfx_invalidate_screen(); } @@ -538,8 +555,35 @@ namespace ThemeManager { // Fall-back to default theme = (UITheme *)&PredefinedThemeRCT2; + LoadTheme(theme); } - LoadTheme(theme); + else + { + LoadTheme(theme); + String::DiscardDuplicate(&CurrentThemePath, path); + } + } + + bool LoadThemeByName(const utf8 * name) + { + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (String::Equals(name, ThemeManager::AvailableThemes[i].Name)) + { + const utf8 * path = ThemeManager::AvailableThemes[i].Path; + if (String::IsNullOrEmpty(path)) + { + LoadTheme((UITheme *)PredefinedThemes[i]); + } + else + { + LoadTheme(ThemeManager::AvailableThemes[i].Path); + } + ActiveAvailableThemeIndex = i; + return true; + } + } + return false; } void Initialise() @@ -547,6 +591,27 @@ namespace ThemeManager ThemeManager::GetAvailableThemes(&ThemeManager::AvailableThemes); LoadTheme((UITheme *)&PredefinedThemeRCT2); ActiveAvailableThemeIndex = 1; + + bool configValid = false; + if (!String::IsNullOrEmpty(gConfigInterface.current_theme_preset)) + { + if (LoadThemeByName(gConfigInterface.current_theme_preset)) + { + configValid = true; + } + } + + if (!configValid) + { + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + } + } + + void GetThemeFileName(utf8 * buffer, size_t bufferSize, const utf8 * name) + { + platform_get_user_directory(buffer, "themes"); + Path::Append(buffer, bufferSize, name); + String::Append(buffer, bufferSize, ".json"); } } @@ -587,8 +652,51 @@ extern "C" { const utf8 * path = ThemeManager::AvailableThemes[index].Path; ThemeManager::LoadTheme(path); + + // HACK Check if theme load failed and fell back to RCT2 + if (ThemeManager::CurrentThemePath == nullptr) + { + index = 1; + } } ThemeManager::ActiveAvailableThemeIndex = index; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(index)); + } + + uint8 theme_get_colour(rct_windowclass wc, uint8 index) + { + const UIThemeWindowEntry * entry = ThemeManager::CurrentTheme->GetEntry(wc); + if (entry == nullptr) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->DefaultTheme.Colours[index]; + } + else + { + return entry->Theme.Colours[index]; + } + } + + void theme_set_colour(rct_windowclass wc, uint8 index, colour_t colour) + { + UIThemeWindowEntry entry; + entry.WindowClass = wc; + + auto currentEntry = (UIThemeWindowEntry *)ThemeManager::CurrentTheme->GetEntry(wc); + if (currentEntry != nullptr) + { + entry.Theme = currentEntry->Theme; + } + else + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + entry.Theme = desc->DefaultTheme; + } + + entry.Theme.Colours[index] = colour; + ThemeManager::CurrentTheme->SetEntry(&entry); + + theme_save(); } uint8 theme_get_flags() @@ -596,11 +704,89 @@ extern "C" return ThemeManager::CurrentTheme->Flags; } + void theme_set_flags(uint8 flags) + { + ThemeManager::CurrentTheme->Flags = flags; + theme_save(); + } + + void theme_save() + { + ThemeManager::CurrentTheme->WriteToFile(ThemeManager::CurrentThemePath); + } + + void theme_rename(const utf8 * name) + { + const utf8 * oldPath = ThemeManager::CurrentThemePath; + utf8 newPath[MAX_PATH]; + + ThemeManager::GetThemeFileName(newPath, sizeof(newPath), name); + platform_file_move(oldPath, newPath); + String::DiscardDuplicate(&ThemeManager::CurrentThemePath, newPath); + + ThemeManager::CurrentTheme->SetName(name); + ThemeManager::CurrentTheme->WriteToFile(ThemeManager::CurrentThemePath); + + theme_manager_load_available_themes(); + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (Path::Equals(newPath, ThemeManager::AvailableThemes[i].Path)) + { + ThemeManager::ActiveAvailableThemeIndex = i; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + break; + } + } + } + + void theme_duplicate(const utf8 * name) + { + utf8 newPath[MAX_PATH]; + + ThemeManager::GetThemeFileName(newPath, sizeof(newPath), name); + String::DiscardDuplicate(&ThemeManager::CurrentThemePath, newPath); + + ThemeManager::CurrentTheme->SetName(name); + ThemeManager::CurrentTheme->Flags &= ~UITHEME_FLAG_PREDEFINED; + ThemeManager::CurrentTheme->WriteToFile(ThemeManager::CurrentThemePath); + + theme_manager_load_available_themes(); + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (Path::Equals(newPath, ThemeManager::AvailableThemes[i].Path)) + { + ThemeManager::ActiveAvailableThemeIndex = i; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(i)); + break; + } + } + } + + void theme_delete() + { + platform_file_delete(ThemeManager::CurrentThemePath); + ThemeManager::LoadTheme((UITheme *)&PredefinedThemeRCT2); + ThemeManager::ActiveAvailableThemeIndex = 1; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + } + void theme_manager_initialise() { ThemeManager::Initialise(); } + uint8 theme_desc_get_num_colours(rct_windowclass wc) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->NumColours; + } + + rct_string_id theme_desc_get_name(rct_windowclass wc) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->WindowName; + } + void colour_scheme_update(rct_window * window) { colour_scheme_update_by_class(window, window->classification); diff --git a/src/interface/themes.c b/src/interface/themes.c deleted file mode 100644 index 2fb4d36e5a..0000000000 --- a/src/interface/themes.c +++ /dev/null @@ -1,255 +0,0 @@ -#if 0 - -/***************************************************************************** -* Copyright (c) 2014 Ted John, Peter Hill -* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. -* -* This file is part of 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. - -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*****************************************************************************/ - -#include "../localisation/string_ids.h" -#include "../util/util.h" -#include "colour.h" -#include "window.h" -#include "themes.h" - -#define COLOURS_1(c0) 1, { { (c0), 0, 0, 0, 0, 0 } } -#define COLOURS_2(c0, c1) 2, { { (c0), (c1), 0, 0, 0, 0 } } -#define COLOURS_3(c0, c1, c2) 3, { { (c0), (c1), (c2), 0, 0, 0 } } -#define COLOURS_4(c0, c1, c2, c3) 4, { { (c0), (c1), (c2), (c3), 0, 0 } } -#define COLOURS_5(c0, c1, c2, c3, c4) 5, { { (c0), (c1), (c2), (c3), (c4), 0 } } -#define COLOURS_6(c0, c1, c2, c3, c4, c5) 6, { { (c0), (c1), (c2), (c3), (c4), (c5) } } - -#define THEME_DEF_END { 0xFF, { 0, 0, 0, 0, 0, 0 } } - -#define TWINDOW(window_class, window_name, window_string_id, theme) { window_class, window_name, window_string_id, theme } - -theme_window_definition gThemeWindowDefinitions[] = { - /* Window Class ini section name stringid window defaults */ - { WC_TOP_TOOLBAR, "top_toolbar", 5245, COLOURS_4(COLOUR_LIGHT_BLUE, COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_GREY ) }, - { WC_BOTTOM_TOOLBAR, "bottom_toolbar", 5246, COLOURS_4(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), COLOUR_BLACK, COLOUR_BRIGHT_GREEN ) }, - { WC_RIDE, "ride", 5203, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_GREY ) }, - { WC_RIDE_CONSTRUCTION, "ride_construction", 5199, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_RIDE_LIST, "ride_list", 5204, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_SAVE_PROMPT, "save_prompt", 5223, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_CONSTRUCT_RIDE, "new_ride", 5201, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_DEMOLISH_RIDE_PROMPT, "demolish_ride_prompt", 5224, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_SCENERY, "scenery", 5197, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, - { WC_OPTIONS, "options", 5219, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_FOOTPATH, "footpath", 5198, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_LAND, "land", 5193, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_WATER, "water", 5194, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_PEEP, "guest", 5205, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, - { WC_GUEST_LIST, "guest_list", 5206, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, - { WC_STAFF_LIST, "staff_list", 5208, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, - { WC_FIRE_PROMPT, "staff_fire_prompt", 5225, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_PARK_INFORMATION, "park_information", 5253, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_FINANCES, "finances", 5187, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_TITLE_MENU, "title_menu", 5249, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_TITLE_EXIT, "title_exit", 5250, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_RECENT_NEWS, "recent_news", 5192, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK ) }, - { WC_SCENARIO_SELECT, "scenario_select", 5252, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_TRACK_DESIGN_LIST, "track_design_list", 5202, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_TRACK_DESIGN_PLACE, "track_design_place", 5200, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_NEW_CAMPAIGN, "new_campaign", 5188, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_KEYBOARD_SHORTCUT_LIST, "keyboard_shortcuts", 5220, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_CHANGE_KEYBOARD_SHORTCUT, "change_keyboard_shortcut", 5221, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_MAP, "map", 5190, COLOURS_2(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN ) }, - { WC_BANNER, "banner", 5209, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_EDITOR_OBJECT_SELECTION, "editor_object_selection", 5210, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDITOR_INVENTION_LIST, "editor_invention_list", 5211, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDITOR_SCENARIO_OPTIONS, "editor_scenario_options", 5212, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDTIOR_OBJECTIVE_OPTIONS, "editor_objection_options", 5213, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_MANAGE_TRACK_DESIGN, "manage_track_design", 5215, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY ) }, - { WC_TRACK_DELETE_PROMPT, "track_delete_prompt", 5226, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_INSTALL_TRACK, "install_track", 5216, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_CLEAR_SCENERY, "clear_scenery", 5195, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_CHEATS, "cheats", 5217, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_RESEARCH, "research", 5189, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_VIEWPORT, "viewport", 5191, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_MAPGEN, "map_generation", 5214, COLOURS_3(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_LOADSAVE, "loadsave", 5222, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_LOADSAVE_OVERWRITE_PROMPT, "loadsave_overwrite_prompt", 5227, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_TITLE_OPTIONS, "title_options", 5251, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_LAND_RIGHTS, "land_rights", 5196, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_THEMES, "themes", 5218, COLOURS_3(COLOUR_GREY, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, - { WC_STAFF, "staff", 5207, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, - { WC_EDITOR_TRACK_BOTTOM_TOOLBAR, "editor_track_bottom_toolbar", 5247, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE) ) }, - { WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR, "editor_scenario_bottom_toolbar", 5248, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_MOSS_GREEN) ) }, - { WC_TITLE_EDITOR, "title_sequences", 5433, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, -}; - -#define COLOURS_RCT1(c0, c1, c2, c3, c4, c5) { { (c0), (c1), (c2), (c3), (c4), (c5) } } - -theme_window_preset gThemeWindowsRCT1[] = { - { WC_TOP_TOOLBAR, COLOURS_RCT1(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_BOTTOM_TOOLBAR, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_YELLOW, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_SATURATED_GREEN, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_RIDE_LIST, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_CONSTRUCT_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_PEEP, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_GUEST_LIST, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_STAFF_LIST, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_FINANCES, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_MENU, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_EXIT, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_NEW_CAMPAIGN, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_OPTIONS, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_STAFF, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - THEME_DEF_END -}; - -uint16 gCurrentTheme = 0; -uint32 gNumThemeWindows = sizeof(gThemeWindowDefinitions) / sizeof(theme_window_definition); - - -theme_preset* theme_get_preset() -{ - return &gConfigThemes.presets[gCurrentTheme]; -} - -theme_window_definition* theme_window_definition_get_by_class(rct_windowclass classification) -{ - for (int i = 0; i < (int)gNumThemeWindows; i++) { - if (gThemeWindowDefinitions[i].classification == classification) { - return &gThemeWindowDefinitions[i]; - } - } - return NULL; -} - -theme_window* theme_window_get_by_class(rct_windowclass classification) -{ - for (int i = 0; i < (int)gNumThemeWindows; i++) { - if (gThemeWindowDefinitions[i].classification == classification) { - return &gConfigThemes.presets[gCurrentTheme].windows[i]; - } - } - return NULL; -} - -void colour_scheme_update(rct_window *window) -{ - theme_window* theme = theme_window_get_by_class(window->classification); - - bool transparent = false; - for (int i = 0; i < 6; i++) { - window->colours[i] = theme->colours[i]; - if (theme->colours[i] & 0x80) { - transparent = true; - } - } - // Some windows need to be transparent even if the colours aren't. - // There doesn't seem to be any side-effects for all windows being transparent - window->flags |= WF_TRANSPARENT; -} - -void colour_scheme_update_by_class(rct_window *window, rct_windowclass classification) -{ - theme_window* theme = theme_window_get_by_class(classification); - - bool transparent = false; - for (int i = 0; i < 6; i++) { - window->colours[i] = theme->colours[i]; - if (theme->colours[i] & 0x80) { - transparent = true; - } - } - // Some windows need to be transparent even if the colours aren't. - // There doesn't seem to be any side-effects for all windows being transparent - window->flags |= WF_TRANSPARENT; -} - -static void theme_set_preset_string(const utf8string preset) -{ - SafeFree(gConfigInterface.current_theme_preset); - gConfigInterface.current_theme_preset = _strdup(preset); -} - -void theme_change_preset(int preset) -{ - if (preset >= 0 && preset < gConfigThemes.num_presets) { - switch (preset) { - case 0: - theme_set_preset_string("*RCT2"); - break; - case 1: - theme_set_preset_string("*RCT1"); - break; - default: - theme_set_preset_string(gConfigThemes.presets[preset].name); - break; - } - gCurrentTheme = preset; - } - window_invalidate_all(); -} - -void theme_create_preset(int duplicate, const char *name) -{ - int preset = gConfigThemes.num_presets; - gConfigThemes.num_presets++; - gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - safe_strcpy(gConfigThemes.presets[preset].name, name, THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[preset].windows[i] = gConfigThemes.presets[duplicate].windows[i]; - } - gConfigThemes.presets[preset].features = gConfigThemes.presets[duplicate].features; - themes_save_preset(preset); - theme_change_preset(preset); -} - -void theme_delete_preset(int preset) -{ - if (preset >= 2) { - utf8 path[MAX_PATH]; - platform_get_user_directory(path, "themes"); - strcat(path, gConfigThemes.presets[preset].name); - strcat(path, ".ini"); - platform_file_delete(path); - - free(gConfigThemes.presets[preset].windows); - - for (int i = preset; i < gConfigThemes.num_presets - 1; i++) { - gConfigThemes.presets[i] = gConfigThemes.presets[i + 1]; - } - gConfigThemes.num_presets--; - theme_change_preset(0); - } -} - -void theme_rename_preset(int preset, const char *newName) -{ - if (preset >= 2) { - utf8 src[MAX_PATH], dest[MAX_PATH]; - platform_get_user_directory(src, "themes"); - platform_get_user_directory(dest, "themes"); - strcat(src, gConfigThemes.presets[preset].name); - strcat(dest, newName); - strcat(src, ".ini"); - strcat(dest, ".ini"); - platform_file_move(src, dest); - - safe_strcpy(gConfigThemes.presets[preset].name, newName, THEME_PRESET_NAME_SIZE); - - if (preset == gCurrentTheme) { - gConfigInterface.current_theme_preset = gConfigThemes.presets[preset].name; - } - } -} - -#endif diff --git a/src/interface/themes.h b/src/interface/themes.h index fb5feda672..3de9401afc 100644 --- a/src/interface/themes.h +++ b/src/interface/themes.h @@ -42,48 +42,16 @@ const utf8 * theme_manager_get_available_theme_name(size_t index); size_t theme_manager_get_active_available_theme_index(); void theme_manager_set_active_available_theme(size_t index); -uint8 theme_get_flags(); - - -#if 0 - - - -#include "../config.h" - -typedef struct { - rct_windowclass classification; - char *section_name; - rct_string_id name; - uint8 num_colours; - theme_window window; -} theme_window_definition; - -typedef struct { - rct_windowclass classification; - theme_window window; -} theme_window_preset; - -// The definitions for window themes as well as the RCT2 preset -extern theme_window_definition gThemeWindowDefinitions[]; -// The preset for RCT1 window themes -extern theme_window_preset gThemeWindowsRCT1[]; - -// The index of the current theme -extern uint16 gCurrentTheme; -// The number of theme-able windows -extern uint32 gNumThemeWindows; - -theme_preset* theme_get_preset(); -theme_window_definition* theme_window_definition_get_by_class(rct_windowclass classification); -theme_window* theme_window_get_by_class(rct_windowclass classification); - -void theme_change_preset(int preset); -void theme_create_preset(int duplicate, const char *name); -void theme_delete_preset(int preset); -void theme_rename_preset(int preset, const char *newName); - -#endif +colour_t theme_get_colour(rct_windowclass wc, uint8 index); +void theme_set_colour(rct_windowclass wc, uint8 index, colour_t colour); +uint8 theme_get_flags(); +void theme_set_flags(uint8 flags); +void theme_save(); +void theme_rename(const utf8 * name); +void theme_duplicate(const utf8 * name); +void theme_delete(); +uint8 theme_desc_get_num_colours(rct_windowclass wc); +rct_string_id theme_desc_get_name(rct_windowclass wc); #endif diff --git a/src/windows/themes.c b/src/windows/themes.c index 6e9da3803d..eddb70fe94 100644 --- a/src/windows/themes.c +++ b/src/windows/themes.c @@ -36,8 +36,6 @@ #include "error.h" #include "../util/util.h" -#if 0 - enum { WINDOW_THEMES_TAB_SETTINGS, WINDOW_THEMES_TAB_MAIN_UI, @@ -256,6 +254,17 @@ static rct_windowclass window_themes_tab_7_classes[] = { WC_LOADSAVE_OVERWRITE_PROMPT }; +static rct_windowclass *window_themes_tab_classes[] = { + NULL, + 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 _selected_tab = 0; static sint16 _color_index_1 = -1; static sint8 _color_index_2 = -1; @@ -269,57 +278,10 @@ void window_themes_init_vars() _selected_tab = WINDOW_THEMES_TAB_SETTINGS; } -static theme_window_definition* get_colour_scheme_tab_definition() +static rct_windowclass get_window_class_tab_index(int index) { - switch (_selected_tab) { - case 1: return theme_window_definition_get_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_definition_get_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_definition_get_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_definition_get_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_definition_get_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_definition_get_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_definition_get_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return NULL; -} -static theme_window_definition* get_colour_scheme_tab_definition_by_index(int index) -{ - switch (_selected_tab) { - case 1: return theme_window_definition_get_by_class(window_themes_tab_1_classes[index]); - case 2: return theme_window_definition_get_by_class(window_themes_tab_2_classes[index]); - case 3: return theme_window_definition_get_by_class(window_themes_tab_3_classes[index]); - case 4: return theme_window_definition_get_by_class(window_themes_tab_4_classes[index]); - case 5: return theme_window_definition_get_by_class(window_themes_tab_5_classes[index]); - case 6: return theme_window_definition_get_by_class(window_themes_tab_6_classes[index]); - case 7: return theme_window_definition_get_by_class(window_themes_tab_7_classes[index]); - } - return NULL; -} -static theme_window* get_colour_scheme_tab() -{ - switch (_selected_tab) { - case 1: return theme_window_get_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_get_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_get_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_get_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_get_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_get_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_get_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return NULL; -} -static theme_window* get_colour_scheme_tab_by_index(int index) -{ - switch (_selected_tab) { - case 1: return theme_window_get_by_class(window_themes_tab_1_classes[index]); - case 2: return theme_window_get_by_class(window_themes_tab_2_classes[index]); - case 3: return theme_window_get_by_class(window_themes_tab_3_classes[index]); - case 4: return theme_window_get_by_class(window_themes_tab_4_classes[index]); - case 5: return theme_window_get_by_class(window_themes_tab_5_classes[index]); - case 6: return theme_window_get_by_class(window_themes_tab_6_classes[index]); - case 7: return theme_window_get_by_class(window_themes_tab_7_classes[index]); - } - return NULL; + rct_windowclass * classes = window_themes_tab_classes[_selected_tab]; + return classes[index]; } static int get_colour_scheme_tab_count() @@ -336,19 +298,6 @@ static int get_colour_scheme_tab_count() return 0; } -/*static int get_colour_scheme_index() { - switch (_selected_tab) { - case 1: return theme_window_get_index_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_get_index_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_get_index_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_get_index_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_get_index_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_get_index_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_get_index_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return -1; -}*/ - static void window_themes_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) { int sprite_idx; @@ -407,27 +356,32 @@ void window_themes_open() static void window_themes_mouseup(rct_window *w, int widgetIndex) { + int activeAvailableThemeIndex; + const utf8 * activeThemeName; + switch (widgetIndex) { case WIDX_THEMES_CLOSE: window_close(w); break; - case WIDX_THEMES_DUPLICATE_BUTTON: - window_text_input_open(w, widgetIndex, 5239, 5240, 1170, (uint32)&gConfigThemes.presets[gCurrentTheme].name, 64); + case WIDX_THEMES_DUPLICATE_BUTTON:; + activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + window_text_input_open(w, widgetIndex, 5239, 5240, 1170, (uint32)activeThemeName, 64); break; case WIDX_THEMES_DELETE_BUTTON: - if (gCurrentTheme >= 2) { - theme_delete_preset(gCurrentTheme); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_delete(); } break; case WIDX_THEMES_RENAME_BUTTON: - if (gCurrentTheme >= 2) { - window_text_input_open(w, widgetIndex, 3348, 5240, 1170, (uint32)&gConfigThemes.presets[gCurrentTheme].name, 64); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + window_text_input_open(w, widgetIndex, 3348, 5240, 1170, (uint32)activeThemeName, 64); } break; } @@ -509,7 +463,7 @@ static void window_themes_resize(rct_window *w) static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) { short newSelectedTab; - int num_items, i; + int num_items; switch (widgetIndex) { case WIDX_THEMES_SETTINGS_TAB: @@ -531,19 +485,15 @@ static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* window_invalidate(w); break; case WIDX_THEMES_PRESETS_DROPDOWN: - num_items = gConfigThemes.num_presets; + theme_manager_load_available_themes(); + num_items = (int)theme_manager_get_num_available_themes(); widget--; - gDropdownItemsFormat[0] = 2777; - gDropdownItemsArgs[0] = (uint32)&gConfigThemes.presets[1].name; - gDropdownItemsFormat[1] = 2777; - gDropdownItemsArgs[1] = (uint32)&gConfigThemes.presets[0].name; - - for (i = 2; i < num_items; i++) { + for (int i = 0; i < num_items; i++) { gDropdownItemsFormat[i] = 2777; - gDropdownItemsArgs[i] = (uint32)&gConfigThemes.presets[i].name; + gDropdownItemsArgs[i] = (uint32)theme_manager_get_available_theme_name(i); } - + window_dropdown_show_text_custom_width( w->x + widget->left, w->y + widget->top, @@ -552,42 +502,35 @@ static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* DROPDOWN_FLAG_STAY_OPEN, num_items, widget->right - widget->left - 3 - ); + ); - if (gCurrentTheme == 0 || gCurrentTheme == 1) { - dropdown_set_checked(gCurrentTheme ^ 1, true); - } else { - dropdown_set_checked(gCurrentTheme, true); - } + dropdown_set_checked(theme_manager_get_active_available_theme_index(), true); break; case WIDX_THEMES_RCT1_RIDE_LIGHTS: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_ride_lights ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_LIGHTS_RIDE); + theme_save(); + window_invalidate_all(); } break; case WIDX_THEMES_RCT1_PARK_LIGHTS: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_park_lights ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_LIGHTS_PARK); + theme_save(); + window_invalidate_all(); } break; case WIDX_THEMES_RCT1_SCENARIO_FONT: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_scenario_font ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT); + theme_save(); + window_invalidate_all(); } break; } @@ -598,22 +541,22 @@ static void window_themes_dropdown(rct_window *w, int widgetIndex, int dropdownI switch (widgetIndex) { case WIDX_THEMES_LIST: if (dropdownIndex != -1) { - get_colour_scheme_tab()->colours[_color_index_2] = dropdownIndex | (get_colour_scheme_tab()->colours[_color_index_2] & 0x80); + rct_windowclass wc = get_window_class_tab_index(_color_index_1); + uint8 colour = theme_get_colour(wc, _color_index_2); + colour = (colour & COLOUR_FLAG_TRANSLUCENT) | dropdownIndex; + theme_set_colour(wc, _color_index_2, colour); window_invalidate_all(); _color_index_1 = -1; _color_index_2 = -1; - if (gCurrentTheme >= 2) - themes_save_preset(gCurrentTheme); + // if (gCurrentTheme >= 2) + // themes_save_preset(gCurrentTheme); } break; case WIDX_THEMES_PRESETS_DROPDOWN: if (dropdownIndex != -1) { - if (dropdownIndex == 0 || dropdownIndex == 1) - dropdownIndex ^= 1; - theme_change_preset(dropdownIndex); + theme_manager_set_active_available_theme(dropdownIndex); } - config_save_default(); break; } @@ -653,33 +596,36 @@ void window_themes_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) int y2 = y % _row_height; _color_index_1 = y / _row_height; _color_index_2 = ((x - _button_offset_x) / 12); - if (_color_index_2 < get_colour_scheme_tab_definition()->num_colours) { + + rct_windowclass wc = get_window_class_tab_index(_color_index_1); + int numColours = theme_desc_get_num_colours(wc); + if (_color_index_2 < numColours) { if (x >= _button_offset_x && x < _button_offset_x + 12 * 6 && y2 >= _button_offset_y && y2 < _button_offset_y + 11) { - if (gCurrentTheme >= 2) { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { + window_error_open(5241, 5256); + } else { window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].left = _button_offset_x + _color_index_2 * 12 + window_themes_widgets[WIDX_THEMES_LIST].left; window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].top = _color_index_1 * _row_height + _button_offset_y - w->scrolls[0].v_top + window_themes_widgets[WIDX_THEMES_LIST].top; window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].right = window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].left + 12; window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].bottom = window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].top + 12; - window_dropdown_show_colour(w, &(window_themes_widgets[WIDX_THEMES_COLORBTN_MASK]), w->colours[1], get_colour_scheme_tab()->colours[_color_index_2]); + + uint8 colour = theme_get_colour(wc, _color_index_2); + window_dropdown_show_colour(w, &(window_themes_widgets[WIDX_THEMES_COLORBTN_MASK]), w->colours[1], colour); widget_invalidate(w, WIDX_THEMES_LIST); } - else { - window_error_open(5241, 5256); - } } else if (x >= _button_offset_x && x < _button_offset_x + 12 * 6 - 1 && y2 >= _check_offset_y && y2 < _check_offset_y + 11) { - if (gCurrentTheme >= 2) { - if (get_colour_scheme_tab()->colours[_color_index_2] & 0x80) { - get_colour_scheme_tab()->colours[_color_index_2] &= 0x7F; - } - else { - get_colour_scheme_tab()->colours[_color_index_2] |= 0x80; - } - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, 5256); + } else { + uint8 colour = theme_get_colour(wc, _color_index_2); + if (colour & COLOUR_FLAG_TRANSLUCENT) { + colour &= ~COLOUR_FLAG_TRANSLUCENT; + } else { + colour |= COLOUR_FLAG_TRANSLUCENT; + } + theme_set_colour(wc, _color_index_2, colour); + window_invalidate_all(); } } } @@ -702,25 +648,26 @@ static void window_themes_textinput(rct_window *w, int widgetIndex, char *text) case WIDX_THEMES_RENAME_BUTTON: if (filename_valid_characters(text)) { bool nameTaken = false; - for (int i = 0; i < gConfigThemes.num_presets; i++) { - if (strcmp(gConfigThemes.presets[i].name, text) == 0) { - window_error_open(5242, STR_NONE); + int numAvailableThemes = (int)theme_manager_get_num_available_themes(); + for (int i = 0; i < numAvailableThemes; i++) { + const utf8 * themeName = theme_manager_get_available_theme_name(i); + if (strcmp(themeName, text) == 0) { + if (widgetIndex != WIDX_THEMES_RENAME_BUTTON) { + window_error_open(5242, STR_NONE); + } nameTaken = true; break; } } if (!nameTaken) { if (widgetIndex == WIDX_THEMES_DUPLICATE_BUTTON) { - theme_create_preset(gCurrentTheme, text); + theme_duplicate(text); + } else { + theme_rename(text); } - else { - theme_rename_preset(gCurrentTheme, text); - } - config_save_default(); window_invalidate(w); } - } - else { + } else { window_error_open(5243, STR_NONE); } break; @@ -789,9 +736,9 @@ void window_themes_invalidate(rct_window *w) window_themes_widgets[WIDX_THEMES_PRESETS].type = WWT_EMPTY; window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WWT_EMPTY; - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_RIDE_LIGHTS, theme_get_preset()->features.rct1_ride_lights); - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_PARK_LIGHTS, theme_get_preset()->features.rct1_park_lights); - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_SCENARIO_FONT, theme_get_preset()->features.rct1_scenario_font); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_RIDE_LIGHTS, theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_PARK_LIGHTS, theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_PARK); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_SCENARIO_FONT, theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT); } else { window_themes_widgets[WIDX_THEMES_LIST].type = WWT_SCROLL; @@ -813,7 +760,9 @@ void window_themes_paint(rct_window *w, rct_drawpixelinfo *dpi) window_themes_draw_tab_images(dpi, w); if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS) { - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigThemes.presets[gCurrentTheme].name; + int activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + const utf8 * activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)activeThemeName; gfx_draw_string_left(dpi, 5238, NULL, w->colours[1], w->x + 10, w->y + window_themes_widgets[WIDX_THEMES_PRESETS].top + 1); gfx_draw_string_left_clipped( dpi, @@ -823,7 +772,7 @@ void window_themes_paint(rct_window *w, rct_drawpixelinfo *dpi) w->x + window_themes_widgets[WIDX_THEMES_PRESETS].left + 1, w->y + window_themes_widgets[WIDX_THEMES_PRESETS].top, w->x + window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].left - window_themes_widgets[WIDX_THEMES_PRESETS].left - 4 - ); + ); } else if (_selected_tab == WINDOW_THEMES_TAB_FEATURES) { @@ -871,18 +820,20 @@ void window_themes_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scroll } } - for (int j = 0; j < get_colour_scheme_tab_definition_by_index(i)->num_colours; j++) { + rct_windowclass wc = get_window_class_tab_index(i); + int numColours = theme_desc_get_num_colours(wc); + for (uint8 j = 0; j < numColours; j++) { + gfx_draw_string_left(dpi, theme_desc_get_name(wc), NULL, w->colours[1], 2, y + 4); - gfx_draw_string_left(dpi, get_colour_scheme_tab_definition_by_index(i)->name, NULL, w->colours[1], 2, y + 4); - - uint32 image = ((get_colour_scheme_tab_by_index(i)->colours[j] & 0x7F) << 19) + 0x600013C3; + uint8 colour = theme_get_colour(wc, j); + uint32 image = ((colour & ~COLOUR_FLAG_TRANSLUCENT) << 19) + 0x600013C3; if (i == _color_index_1 && j == _color_index_2) { - image = ((get_colour_scheme_tab_by_index(i)->colours[j] & 0x7F) << 19) + 0x600013C4; + image = ((colour & ~COLOUR_FLAG_TRANSLUCENT) << 19) + 0x600013C4; } gfx_draw_sprite(dpi, image, _button_offset_x + 12 * j, y + _button_offset_y, 0); gfx_fill_rect_inset(dpi, _button_offset_x + 12 * j, y + _check_offset_y, _button_offset_x + 12 * j + 9, y + _check_offset_y + 10, w->colours[1], 0xE0); - if (get_colour_scheme_tab_by_index(i)->colours[j] & 0x80) { + if (colour & COLOUR_FLAG_TRANSLUCENT) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1] & 0x7F, _button_offset_x + 12 * j, y + _check_offset_y); } @@ -893,9 +844,3 @@ void window_themes_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scroll y += _row_height; } } - -#endif - -void window_themes_open() -{ -}