1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +01:00

get game working with new theme manager

Theme editor currently unavailable.
This commit is contained in:
IntelOrca
2016-01-29 19:39:31 +00:00
parent 0eb57e5fb5
commit caf9bd9939
22 changed files with 233 additions and 467 deletions

View File

@@ -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], &currentSection, (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], &currentSection, 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 = &section->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 = &section->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, &sectionName, &sectionNameSize))
*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 &section->property_definitions[i];
}
return NULL;
}
#pragma endregion
#pragma region Title Sequences
static void title_sequence_open(const char *path, const char *customName);