From caf9bd9939f0df582235954c6db54006cfe985ef Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 29 Jan 2016 19:39:31 +0000 Subject: [PATCH] get game working with new theme manager Theme editor currently unavailable. --- src/config.c | 391 -------------------------- src/config.h | 21 -- src/core/Guard.hpp | 34 ++- src/core/List.hpp | 12 + src/core/Path.cpp | 9 + src/core/Path.hpp | 1 + src/core/String.cpp | 2 +- src/core/String.hpp | 2 + src/interface/Theme.cpp | 119 +++++++- src/interface/themes.c | 4 + src/interface/themes.h | 35 ++- src/localisation/localisation.c | 6 +- src/openrct2.c | 4 +- src/windows/editor_object_selection.c | 5 +- src/windows/options.c | 31 +- src/windows/park.c | 2 +- src/windows/ride.c | 4 +- src/windows/ride_construction.c | 1 + src/windows/ride_list.c | 2 +- src/windows/server_list.c | 1 + src/windows/themes.c | 8 + src/windows/title_scenarioselect.c | 6 +- 22 files changed, 233 insertions(+), 467 deletions(-) diff --git a/src/config.c b/src/config.c index e0982e42ae..2eb1f44c9a 100644 --- a/src/config.c +++ b/src/config.c @@ -299,7 +299,6 @@ sound_configuration gConfigSound; twitch_configuration gConfigTwitch; network_configuration gConfigNetwork; notification_configuration gConfigNotifications; -themes_configuration gConfigThemes; title_sequences_configuration gConfigTitleSequences; static bool config_open(const utf8string path); @@ -1044,396 +1043,6 @@ bool config_shortcut_keys_save() #pragma endregion - -#pragma region Themes - -typedef struct { - size_t offset; - const_utf8string property_name; - uint8 type; - value_union default_value; - config_enum_definition *enum_definitions; -} theme_property_definition; - -typedef struct { - size_t offset; - const_utf8string section_name; - theme_property_definition *property_definitions; - int property_definitions_count; -} theme_section_definition; - - -theme_property_definition _themeWindowDefinitions[] = { - { offsetof(theme_window, colours[0]), "colour_0", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[1]), "colour_1", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[2]), "colour_2", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[3]), "colour_3", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[4]), "colour_4", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[5]), "colour_5", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, -}; - -theme_property_definition _themeFeaturesDefinitions[] = { - { offsetof(theme_features, rct1_ride_lights), "rct1_ride_lights", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(theme_features, rct1_park_lights), "rct1_park_lights", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(theme_features, rct1_scenario_font), "rct1_scenario_font", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, -}; - - -theme_section_definition _themeSectionDefinitions[] = { - // Special definition for theme windows - { 0, "", _themeWindowDefinitions, countof(_themeWindowDefinitions) }, - { offsetof(theme_preset, features), "features", _themeFeaturesDefinitions, countof(_themeFeaturesDefinitions) }, -}; - -static bool themes_open(const_utf8string path); -static bool themes_save(const_utf8string path, int preset); -static void themes_read_properties(theme_preset *theme, theme_section_definition **currentSection, utf8string line); -static void themes_set_property(theme_preset *theme, const theme_section_definition *section, const theme_property_definition *property, utf8string value, int valueSize); -static theme_section_definition* themes_get_section_def(utf8string name, int size); -static theme_property_definition *themes_get_property_def(theme_section_definition *section, utf8string name, int size); - -void themes_set_default() -{ - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, "themes"); - platform_ensure_directory_exists(path); - - gConfigThemes.num_presets = 2; - gConfigThemes.presets = malloc(sizeof(theme_preset) * gConfigThemes.num_presets); - - // Set RCT2 theme - safe_strcpy(gConfigThemes.presets[0].name, language_get_string(2741), THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[0].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - - // Define the defaults for RCT2 here - gConfigThemes.presets[0].features.rct1_ride_lights = false; - gConfigThemes.presets[0].features.rct1_park_lights = false; - gConfigThemes.presets[0].features.rct1_scenario_font = false; - - - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[0].windows[i] = gThemeWindowDefinitions[i].window; - } - - // Set RCT1 theme - safe_strcpy(gConfigThemes.presets[1].name, language_get_string(2740), THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[1].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - - // Define the defaults for RCT1 here - gConfigThemes.presets[1].features.rct1_ride_lights = true; - gConfigThemes.presets[1].features.rct1_park_lights = true; - gConfigThemes.presets[1].features.rct1_scenario_font = true; - - - for (int i = 0; i < (int)gNumThemeWindows; i++) { - uint8 changed_colour = 0xFF; - for (int k = 0; gThemeWindowsRCT1[k].classification != 0xFF; k++) { - if (gThemeWindowsRCT1[k].classification == gThemeWindowDefinitions[i].classification) { - changed_colour = (uint8)k; - break; - } - } - gConfigThemes.presets[1].windows[i] = (changed_colour != 0xFF ? gThemeWindowsRCT1[changed_colour].window : gThemeWindowDefinitions[i].window); - } - } - -void themes_load_presets() -{ - utf8 path[MAX_PATH]; - file_info file; - int fileEnumHandle, i; - - platform_get_user_directory(path, "themes"); - strcat(path, "*.ini"); - fileEnumHandle = platform_enumerate_files_begin(path); - while (platform_enumerate_files_next(fileEnumHandle, &file)) { - platform_get_user_directory(path, "themes"); - strcat(path, file.path); - themes_open(path); - } - platform_enumerate_files_end(fileEnumHandle); - - if (strcmp(gConfigInterface.current_theme_preset, "*RCT2") == 0) { - theme_change_preset(0); - } - else if (strcmp(gConfigInterface.current_theme_preset, "*RCT1") == 0) { - theme_change_preset(1); - } - else { - for (i = 2; i < gConfigThemes.num_presets; i++) { - if (strcmp(gConfigInterface.current_theme_preset, gConfigThemes.presets[i].name) == 0) { - theme_change_preset(i); - break; - } - } - if (i == gConfigThemes.num_presets) { - theme_change_preset(0); - } - } -} - -bool themes_save_preset(int preset) -{ - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, "themes"); - strcat(path, gConfigThemes.presets[preset].name); - strcat(path, ".ini"); - if (themes_save(path, preset)) { - return true; - } - - return false; -} - -bool themes_open(const_utf8string path) -{ - SDL_RWops *file; - utf8string lineBuffer; - size_t lineBufferCapacity; - size_t lineLength; - int c, preset; - theme_section_definition *currentSection; - - file = SDL_RWFromFile(path, "rb"); - if (file == NULL) - return false; - - // Check if the colour scheme is already loaded - // No nead to read the first two presets as they're hardcoded in - for (preset = 2; preset < gConfigThemes.num_presets; preset++) { - if (strcmp(path, gConfigThemes.presets[preset].name) == 0) { - break; - } - } - // Otherwise allocate one - if (preset == gConfigThemes.num_presets) { - gConfigThemes.num_presets++; - gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - safe_strcpy(gConfigThemes.presets[preset].name, path_get_filename(path), THEME_PRESET_NAME_SIZE); - path_remove_extension(gConfigThemes.presets[preset].name); - gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - gConfigThemes.presets[preset].features.rct1_ride_lights = false; - gConfigThemes.presets[preset].features.rct1_park_lights = false; - gConfigThemes.presets[preset].features.rct1_scenario_font = false; - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[preset].windows[i] = gThemeWindowDefinitions[i].window; - } - } - - currentSection = NULL; - lineBufferCapacity = 64; - lineBuffer = malloc(lineBufferCapacity); - lineLength = 0; - - // Skim UTF-8 byte order mark - SDL_RWread(file, lineBuffer, 3, 1); - if (!(lineBuffer[0] == (utf8)0xEF && lineBuffer[1] == (utf8)0xBB && lineBuffer[2] == (utf8)0xBF)) - SDL_RWseek(file, 0, SEEK_SET); - - while ((c = rwopsreadc(file)) != EOF) { - if (c == '\n' || c == '\r') { - lineBuffer[lineLength++] = 0; - themes_read_properties(&gConfigThemes.presets[preset], ¤tSection, (utf8string)lineBuffer); - lineLength = 0; - } - else { - lineBuffer[lineLength++] = c; - } - - if (lineLength >= lineBufferCapacity) { - lineBufferCapacity *= 2; - lineBuffer = realloc(lineBuffer, lineBufferCapacity); - } - } - - if (lineLength > 0) { - lineBuffer[lineLength++] = 0; - themes_read_properties(&gConfigThemes.presets[preset], ¤tSection, lineBuffer); - } - - free(lineBuffer); - SDL_RWclose(file); - return true; -} - -static bool themes_save(const_utf8string path, int preset) -{ - SDL_RWops *file; - int i, j; - value_union *value; - - file = SDL_RWFromFile(path, "wb"); - if (file == NULL) { - log_error("Unable to write to theme file."); - return false; - } - - // Skip the window definition, we'll do that after - for (i = 1; i < countof(_themeSectionDefinitions); i++) { - theme_section_definition *section = &_themeSectionDefinitions[i]; - - rwopswritec(file, '['); - rwopswritestr(file, section->section_name); - rwopswritec(file, ']'); - rwopswritenewline(file); - - for (j = 0; j < section->property_definitions_count; j++) { - theme_property_definition *property = §ion->property_definitions[j]; - - rwopswritestr(file, property->property_name); - rwopswritestr(file, " = "); - - value = (value_union*)((size_t)&gConfigThemes.presets[preset] + (size_t)section->offset + (size_t)property->offset); - - if (property->enum_definitions != NULL) - config_write_enum(file, property->type, value, property->enum_definitions); - else - config_save_property_value(file, property->type, value); - rwopswritenewline(file); - } - rwopswritenewline(file); - } - - for (i = 0; i < (int)gNumThemeWindows; i++) { - theme_section_definition *section = &_themeSectionDefinitions[0]; - - rwopswritec(file, '['); - rwopswritestr(file, gThemeWindowDefinitions[i].section_name); - rwopswritec(file, ']'); - rwopswritenewline(file); - - for (j = 0; j < section->property_definitions_count; j++) { - theme_property_definition *property = §ion->property_definitions[j]; - - rwopswritestr(file, property->property_name); - rwopswritestr(file, " = "); - - value = (value_union*)((size_t)gConfigThemes.presets[preset].windows + (size_t)(sizeof(theme_window) * i) + (size_t)property->offset); - - if (property->enum_definitions != NULL) - config_write_enum(file, property->type, value, property->enum_definitions); - else - config_save_property_value(file, property->type, value); - rwopswritenewline(file); - } - } - - SDL_RWclose(file); - return true; -} - - -static void themes_read_properties(theme_preset *theme, theme_section_definition **currentSection, utf8string line) -{ - utf8 *ch = (utf8*)line; - utf8_skip_whitespace(&ch); - - if (*ch == '[') { - const utf8 *sectionName; - int sectionNameSize; - if (config_get_section(ch, §ionName, §ionNameSize)) - *currentSection = themes_get_section_def((utf8string)sectionName, sectionNameSize); - } else { - if (*currentSection != NULL) { - utf8 *propertyName, *value; - int propertyNameSize, valueSize; - if (config_get_property_name_value(ch, &propertyName, &propertyNameSize, &value, &valueSize)) { - theme_property_definition *property; - property = themes_get_property_def(*currentSection, propertyName, propertyNameSize); - if (property != NULL) - themes_set_property(theme, *currentSection, property, value, valueSize); - } - } - } -} -static void themes_set_property(theme_preset *theme, const theme_section_definition *section, const theme_property_definition *property, utf8string value, int valueSize) -{ - value_union *destValue = (value_union*)((size_t)theme + (size_t)section->offset + (size_t)property->offset); - - // Get getting the address from the windows pointer instead - if (section == &_themeSectionDefinitions[0]) - destValue = (value_union*)((size_t)theme->windows + (size_t)section->offset + (size_t)property->offset); - - if (property->enum_definitions != NULL) - if (config_read_enum(destValue, _configValueTypeSize[property->type], value, valueSize, property->enum_definitions)) - return; - - switch (property->type) { - case CONFIG_VALUE_TYPE_BOOLEAN: - if (_strnicmp(value, "false", valueSize) == 0) destValue->value_boolean = false; - else if (_strnicmp(value, "true", valueSize) == 0) destValue->value_boolean = true; - else destValue->value_boolean = strtol(value, NULL, 0) != 0; - break; - case CONFIG_VALUE_TYPE_UINT8: - destValue->value_uint8 = (uint8)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_UINT16: - destValue->value_uint16 = (uint16)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_UINT32: - destValue->value_uint32 = (uint32)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT8: - destValue->value_sint8 = (sint8)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT16: - destValue->value_sint16 = (sint16)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT32: - destValue->value_sint32 = (sint32)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_FLOAT: - destValue->value_float = strtof(value, NULL); - break; - case CONFIG_VALUE_TYPE_DOUBLE: - destValue->value_double = strtod(value, NULL); - break; - case CONFIG_VALUE_TYPE_STRING: - SafeFree(destValue->value_string); - destValue->value_string = malloc(valueSize + 1); - memcpy(destValue->value_string, value, valueSize); - destValue->value_string[valueSize] = 0; - break; - } -} -static theme_section_definition* themes_get_section_def(utf8string name, int size) -{ - int i; - - // Skip the special definition - for (i = 1; i < countof(_themeSectionDefinitions); i++) { - const_utf8string sectionName = _themeSectionDefinitions[i].section_name; - if (sectionName[size] == 0 && _strnicmp(sectionName, name, size) == 0) - return &_themeSectionDefinitions[i]; - } - // Check for window definitions - for (i = 0; i < (int)gNumThemeWindows; i++) { - const_utf8string sectionName = gThemeWindowDefinitions[i].section_name; - if (sectionName[size] == 0 && _strnicmp(sectionName, name, size) == 0) { - _themeSectionDefinitions[0].offset = (size_t)(sizeof(theme_window) * i); - return &_themeSectionDefinitions[0]; - } - } - - return NULL; - } -static theme_property_definition *themes_get_property_def(theme_section_definition *section, utf8string name, int size) -{ - int i; - - for (i = 0; i < section->property_definitions_count; i++) { - const_utf8string propertyName = section->property_definitions[i].property_name; - if (propertyName[size] == 0 && _strnicmp(propertyName, name, size) == 0) - return §ion->property_definitions[i]; - } - - return NULL; -} - -#pragma endregion - #pragma region Title Sequences static void title_sequence_open(const char *path, const char *customName); diff --git a/src/config.h b/src/config.h index b94fcb2b22..60f733f26c 100644 --- a/src/config.h +++ b/src/config.h @@ -267,22 +267,6 @@ typedef struct { uint8 rct1_scenario_font; } theme_features; -#define THEME_PRESET_NAME_SIZE 256 - -typedef struct theme_preset { - char name[THEME_PRESET_NAME_SIZE]; - theme_window *windows; - - // Add structures for any other settings here - theme_features features; - -} theme_preset; - -typedef struct { - theme_preset *presets; - uint16 num_presets; -} themes_configuration; - #define TITLE_SEQUENCE_MAX_SAVE_LENGTH 51 typedef struct { @@ -327,7 +311,6 @@ extern sound_configuration gConfigSound; extern twitch_configuration gConfigTwitch; extern network_configuration gConfigNetwork; extern notification_configuration gConfigNotifications; -extern themes_configuration gConfigThemes; extern title_sequences_configuration gConfigTitleSequences; extern uint16 gShortcutKeys[SHORTCUT_COUNT]; @@ -346,10 +329,6 @@ bool config_shortcut_keys_save(); bool config_find_or_browse_install_directory(); -void themes_set_default(); -void themes_load_presets(); -bool themes_save_preset(int preset); - void title_sequences_set_default(); void title_sequences_load_presets(); void title_sequence_save_preset_script(int preset); diff --git a/src/core/Guard.hpp b/src/core/Guard.hpp index 1f8cff8033..8556ce215a 100644 --- a/src/core/Guard.hpp +++ b/src/core/Guard.hpp @@ -3,6 +3,7 @@ #include #include +#include "Console.hpp" #include "Diagnostics.hpp" /** @@ -10,13 +11,30 @@ */ namespace Guard { - template - void ArgumentInRange(T argument, T min, T max, const char *message = nullptr) - { - Debug::Break(); + void Assert(bool expression, const char * message = nullptr) + { + if (expression) return; - fputs(message, stderr); - fputc('\n', stderr); - assert(argument < min || argument > max); - } + if (message != nullptr) + { + Console::Error::WriteLine(message); + } + +#if DEBUG + Debug::Break(); +#endif + assert(false); + } + + template + void ArgumentNotNull(T * argument, const char * message = nullptr) + { + Assert(argument != nullptr, message); + } + + template + void ArgumentInRange(T argument, T min, T max, const char * message = nullptr) + { + Assert(argument >= min && argument <= max, message); + } }; diff --git a/src/core/List.hpp b/src/core/List.hpp index 0d8385238e..2c750f4833 100644 --- a/src/core/List.hpp +++ b/src/core/List.hpp @@ -73,4 +73,16 @@ public: { return Memory::DuplicateArray(this->data(), this->size()); } + + const_reference operator[](size_t index) const + { + Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); + return std::vector::operator[](index); + } + + reference operator[](size_t index) + { + Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); + return std::vector::operator[](index); + } }; diff --git a/src/core/Path.cpp b/src/core/Path.cpp index 67c60e59ec..90b8e0f031 100644 --- a/src/core/Path.cpp +++ b/src/core/Path.cpp @@ -73,4 +73,13 @@ namespace Path } #endif } + + bool Equals(const utf8 * a, const utf8 * b) + { + bool ignoreCase = false; +#if __WINDOWS__ + ignoreCase = true; +#endif + return String::Equals(a, b, ignoreCase); + } } diff --git a/src/core/Path.hpp b/src/core/Path.hpp index 5d35ee6d65..1186f86e51 100644 --- a/src/core/Path.hpp +++ b/src/core/Path.hpp @@ -10,4 +10,5 @@ namespace Path utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); 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 4252cab76c..ba000bc7f7 100644 --- a/src/core/String.cpp +++ b/src/core/String.cpp @@ -144,7 +144,7 @@ namespace String utf8 * SkipBOM(utf8 * buffer) { - return (utf8*)SkipBOM(buffer); + return (utf8*)SkipBOM((const utf8 *)buffer); } const utf8 * SkipBOM(const utf8 * buffer) diff --git a/src/core/String.hpp b/src/core/String.hpp index f60998ce19..c286ebd27e 100644 --- a/src/core/String.hpp +++ b/src/core/String.hpp @@ -7,6 +7,8 @@ extern "C" namespace String { + constexpr utf8 * Empty = ""; + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false); bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase = false); diff --git a/src/interface/Theme.cpp b/src/interface/Theme.cpp index 52f52b9265..f40961a88c 100644 --- a/src/interface/Theme.cpp +++ b/src/interface/Theme.cpp @@ -3,6 +3,7 @@ extern "C" { #include "../common.h" + #include "themes.h" #include "window.h" } @@ -19,13 +20,6 @@ struct WindowThemeDesc; // Don't try to load theme files that exceed 64 MiB constexpr uint64 MAX_THEME_SIZE = 64 * 1024 * 1024; -enum { - UITHEME_FLAG_PREDEFINED = 1 << 0, - UITHEME_FLAG_USE_LIGHTS_RIDE = 1 << 1, - UITHEME_FLAG_USE_LIGHTS_PARK = 1 << 2, - UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT = 1 << 3, -}; - /** * Represents a window theming style such as the colour scheme. */ @@ -473,17 +467,35 @@ UITheme UITheme::CreatePredefined(const utf8 * name, const UIThemeWindowEntry * namespace ThemeManager { - const utf8 * CurrentThemePath; - UITheme * CurrentTheme; - struct AvailableTheme { utf8 Path[MAX_PATH]; utf8 Name[64]; }; + const utf8 * CurrentThemePath; + UITheme * CurrentTheme; + List AvailableThemes; + size_t ActiveAvailableThemeIndex = SIZE_MAX; + size_t NumPredefinedThemes = 0; + void GetAvailableThemes(List * outThemes) { + Guard::ArgumentNotNull(outThemes); + + outThemes->Clear(); + + NumPredefinedThemes = 0; + for (const UITheme * * predefinedTheme = PredefinedThemes; *predefinedTheme != nullptr; predefinedTheme++) + { + AvailableTheme theme; + String::Set(theme.Path, sizeof(theme.Path), String::Empty); + String::Set(theme.Name, sizeof(theme.Name), (*predefinedTheme)->Name); + outThemes->Add(theme); + + NumPredefinedThemes++; + } + utf8 themesPattern[MAX_PATH]; platform_get_user_directory(themesPattern, "themes"); Path::Append(themesPattern, sizeof(themesPattern), "*.json"); @@ -496,12 +508,99 @@ namespace ThemeManager String::Set(theme.Path, sizeof(theme.Path), path); Path::GetFileNameWithoutExtension(theme.Path, sizeof(theme.Path), path); outThemes->Add(theme); + + if (Path::Equals(CurrentThemePath, path)) + { + ActiveAvailableThemeIndex = outThemes->GetCount() - 1; + } } } + + void LoadTheme(UITheme * theme) + { + if (CurrentTheme != nullptr) + { + if (!(theme->Flags & UITHEME_FLAG_PREDEFINED)) + { + delete CurrentTheme; + } + } + + CurrentTheme = theme; + + gfx_invalidate_screen(); + } + + void LoadTheme(const utf8 * path) + { + UITheme * theme = UITheme::FromFile(path); + if (theme == nullptr) + { + // Fall-back to default + theme = (UITheme *)&PredefinedThemeRCT2; + } + LoadTheme(theme); + } + + void Initialise() + { + ThemeManager::GetAvailableThemes(&ThemeManager::AvailableThemes); + LoadTheme((UITheme *)&PredefinedThemeRCT2); + ActiveAvailableThemeIndex = 1; + } } extern "C" { + void theme_manager_load_available_themes() + { + ThemeManager::GetAvailableThemes(&ThemeManager::AvailableThemes); + } + + size_t theme_manager_get_num_available_themes() + { + return ThemeManager::AvailableThemes.GetCount(); + } + + const utf8 * theme_manager_get_available_theme_path(size_t index) + { + return ThemeManager::AvailableThemes[index].Path; + } + + const utf8 * theme_manager_get_available_theme_name(size_t index) + { + return ThemeManager::AvailableThemes[index].Name; + } + + size_t theme_manager_get_active_available_theme_index() + { + return ThemeManager::ActiveAvailableThemeIndex; + } + + void theme_manager_set_active_available_theme(size_t index) + { + if (index < ThemeManager::NumPredefinedThemes) + { + ThemeManager::LoadTheme((UITheme *)PredefinedThemes[index]); + } + else + { + const utf8 * path = ThemeManager::AvailableThemes[index].Path; + ThemeManager::LoadTheme(path); + } + ThemeManager::ActiveAvailableThemeIndex = index; + } + + uint8 theme_get_flags() + { + return ThemeManager::CurrentTheme->Flags; + } + + void theme_manager_initialise() + { + ThemeManager::Initialise(); + } + 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 index 54d1891b58..2fb4d36e5a 100644 --- a/src/interface/themes.c +++ b/src/interface/themes.c @@ -1,3 +1,5 @@ +#if 0 + /***************************************************************************** * Copyright (c) 2014 Ted John, Peter Hill * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. @@ -249,3 +251,5 @@ void theme_rename_preset(int preset, const char *newName) } } } + +#endif diff --git a/src/interface/themes.h b/src/interface/themes.h index 2c9acd3671..fb5feda672 100644 --- a/src/interface/themes.h +++ b/src/interface/themes.h @@ -18,11 +18,37 @@ * along with this program. If not, see . *****************************************************************************/ -#ifndef _COLOUR_SCHEMES_H_ -#define _COLOUR_SCHEMES_H_ +#ifndef _THEMES_H_ +#define _THEMES_H_ #include "../common.h" #include "window.h" + +enum { + UITHEME_FLAG_PREDEFINED = 1 << 0, + UITHEME_FLAG_USE_LIGHTS_RIDE = 1 << 1, + UITHEME_FLAG_USE_LIGHTS_PARK = 1 << 2, + UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT = 1 << 3, +}; + +void colour_scheme_update(rct_window *window); +void colour_scheme_update_by_class(rct_window *window, rct_windowclass classification); + +void theme_manager_initialise(); +void theme_manager_load_available_themes(); +size_t theme_manager_get_num_available_themes(); +const utf8 * theme_manager_get_available_theme_path(size_t index); +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 { @@ -52,13 +78,12 @@ 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 colour_scheme_update(rct_window *window); -void colour_scheme_update_by_class(rct_window *window, 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 + #endif diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index 42ec0dcfd1..40b5760184 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -662,8 +662,10 @@ void format_string_code(unsigned int format_code, char **dest, char **args) value = *((uint32*)*args); *args += 4; - strcpy(*dest, (char*)value); - *dest += strlen(*dest); + if (value != 0) { + strcpy(*dest, (char*)value); + *dest += strlen(*dest); + } break; case FORMAT_MONTHYEAR: // Pop argument diff --git a/src/openrct2.c b/src/openrct2.c index 8cc31ed9bb..b550d93581 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -26,6 +26,7 @@ #include "game.h" #include "hook.h" #include "interface/chat.h" +#include "interface/themes.h" #include "interface/window.h" #include "interface/viewport.h" #include "localisation/localisation.h" @@ -229,8 +230,7 @@ bool openrct2_initialise() } http_init(); - themes_set_default(); - themes_load_presets(); + theme_manager_initialise(); title_sequences_set_default(); title_sequences_load_presets(); diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 9c81989ef7..2d0476f39a 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../audio/audio.h" +#include "../config.h" #include "../game.h" #include "../interface/themes.h" #include "../interface/widget.h" @@ -33,10 +34,10 @@ #include "../ride/ride_data.h" #include "../ride/track.h" #include "../scenario.h" -#include "dropdown.h" -#include "error.h" #include "../util/util.h" #include "../world/footpath.h" +#include "dropdown.h" +#include "error.h" enum { FILTER_RCT2 = (1 << 0), diff --git a/src/windows/options.c b/src/windows/options.c index f7224468b4..960fcf8bff 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -989,16 +989,12 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* case WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE: switch (widgetIndex) { case WIDX_THEMES_DROPDOWN: - num_items = gConfigThemes.num_presets; + theme_manager_get_num_available_themes(); + num_items = (int)theme_manager_get_num_available_themes(); - 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( @@ -1009,13 +1005,10 @@ static void window_options_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); + widget_invalidate(w, WIDX_THEMES_DROPDOWN); break; case WIDX_SCENARIO_GROUPING_DROPDOWN: @@ -1243,9 +1236,7 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown switch (widgetIndex) { case WIDX_THEMES_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; @@ -1642,7 +1633,11 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) break; case WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE: gfx_draw_string_left(dpi, STR_SHOW_TOOLBAR_BUTTONS_FOR, w, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_TOOLBAR_BUTTONS_GROUP].top + 15); - 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_options_controls_and_interface_widgets[WIDX_THEMES].top + 1); gfx_draw_string_left_clipped( dpi, diff --git a/src/windows/park.c b/src/windows/park.c index f8f408f14d..00923ef1f7 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -979,7 +979,7 @@ static void window_park_entrance_invalidate(rct_window *w) window_park_entrance_widgets[WIDX_STATUS].top = w->height - 13; window_park_entrance_widgets[WIDX_STATUS].bottom = w->height - 3; - if (theme_get_preset()->features.rct1_park_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_PARK) { window_park_entrance_widgets[WIDX_OPEN_OR_CLOSE].type = WWT_EMPTY; if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_GUESTS_AND_RATING) { window_park_entrance_widgets[WIDX_CLOSE_LIGHT].type = WWT_FLATBTN; diff --git a/src/windows/ride.c b/src/windows/ride.c index 2d47e7bbb4..5d9dfe3d96 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1696,7 +1696,7 @@ static void window_ride_main_resize(rct_window *w) w->flags |= WF_RESIZABLE; int minHeight = 180; - if (theme_get_preset()->features.rct1_ride_lights) + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) minHeight = 200 + RCT1_LIGHT_OFFSET - (ride_type_has_flag(get_ride(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0); window_set_resize(w, 316, minHeight, 500, 450); @@ -2037,7 +2037,7 @@ static void window_ride_main_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); - if (theme_get_preset()->features.rct1_ride_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) { window_ride_main_widgets[WIDX_OPEN].type = WWT_EMPTY; window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN; window_ride_main_widgets[WIDX_TEST_LIGHT].type = (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? WWT_EMPTY : WWT_IMGBTN); diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c index 60766f810a..0481b677ae 100644 --- a/src/windows/ride_construction.c +++ b/src/windows/ride_construction.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../audio/audio.h" #include "../cheats.h" +#include "../config.h" #include "../drawing/drawing.h" #include "../game.h" #include "../input.h" diff --git a/src/windows/ride_list.c b/src/windows/ride_list.c index 928dcf8184..a716625af6 100644 --- a/src/windows/ride_list.c +++ b/src/windows/ride_list.c @@ -403,7 +403,7 @@ static void window_ride_list_invalidate(rct_window *w) w->widgets[WIDX_OPEN_LIGHT].right = w->width - 7; w->widgets[WIDX_OPEN_LIGHT].left = w->width - 20; - if (theme_get_preset()->features.rct1_ride_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) { w->widgets[WIDX_OPEN_CLOSE_ALL].type = WWT_EMPTY; w->widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN; w->widgets[WIDX_OPEN_LIGHT].type = WWT_IMGBTN; diff --git a/src/windows/server_list.c b/src/windows/server_list.c index 062288c5d1..8d17f43184 100644 --- a/src/windows/server_list.c +++ b/src/windows/server_list.c @@ -18,6 +18,7 @@ * along with this program. If not, see . *****************************************************************************/ +#include "../config.h" #include "../interface/colour.h" #include "../interface/themes.h" #include "../interface/widget.h" diff --git a/src/windows/themes.c b/src/windows/themes.c index 51694d493d..6e9da3803d 100644 --- a/src/windows/themes.c +++ b/src/windows/themes.c @@ -36,6 +36,8 @@ #include "error.h" #include "../util/util.h" +#if 0 + enum { WINDOW_THEMES_TAB_SETTINGS, WINDOW_THEMES_TAB_MAIN_UI, @@ -891,3 +893,9 @@ void window_themes_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scroll y += _row_height; } } + +#endif + +void window_themes_open() +{ +} diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 021d63548e..40b21a6fa4 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -351,7 +351,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); - format = (theme_get_preset()->features.rct1_scenario_font) ? 5138 : 1193; + format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? 5138 : 1193; // Text for each tab for (i = 0; i < 8; i++) { @@ -426,8 +426,8 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * colour = (colour << 24) | (colour << 16) | (colour << 8) | colour; gfx_clear(dpi, colour); - int highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193; - int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191; + int highlighted_format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? 5139 : 1193; + int unhighlighted_format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? 5139 : 1191; bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN;