git repos / blockattack-game

blame: source/code/themes.cpp

normal view · raw

aaba4f1e Poul Sander 2023-07-25 13:34 1
/*
aaba4f1e Poul Sander 2023-07-25 13:34 2
===========================================================================
aaba4f1e Poul Sander 2023-07-25 13:34 3
blockattack - Block Attack - Rise of the Blocks
aaba4f1e Poul Sander 2023-07-25 13:34 4
Copyright (C) 2005-2023 Poul Sander
aaba4f1e Poul Sander 2023-07-25 13:34 5
aaba4f1e Poul Sander 2023-07-25 13:34 6
This program is free software: you can redistribute it and/or modify
aaba4f1e Poul Sander 2023-07-25 13:34 7
it under the terms of the GNU General Public License as published by
aaba4f1e Poul Sander 2023-07-25 13:34 8
the Free Software Foundation, either version 2 of the License, or
aaba4f1e Poul Sander 2023-07-25 13:34 9
(at your option) any later version.
aaba4f1e Poul Sander 2023-07-25 13:34 10
aaba4f1e Poul Sander 2023-07-25 13:34 11
This program is distributed in the hope that it will be useful,
aaba4f1e Poul Sander 2023-07-25 13:34 12
but WITHOUT ANY WARRANTY; without even the implied warranty of
aaba4f1e Poul Sander 2023-07-25 13:34 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
aaba4f1e Poul Sander 2023-07-25 13:34 14
GNU General Public License for more details.
aaba4f1e Poul Sander 2023-07-25 13:34 15
aaba4f1e Poul Sander 2023-07-25 13:34 16
You should have received a copy of the GNU General Public License
aaba4f1e Poul Sander 2023-07-25 13:34 17
along with this program.  If not, see http://www.gnu.org/licenses/
aaba4f1e Poul Sander 2023-07-25 13:34 18
aaba4f1e Poul Sander 2023-07-25 13:34 19
Source information and contacts persons can be found at
aaba4f1e Poul Sander 2023-07-25 13:34 20
https://www.blockattack.net
aaba4f1e Poul Sander 2023-07-25 13:34 21
===========================================================================
aaba4f1e Poul Sander 2023-07-25 13:34 22
*/
aaba4f1e Poul Sander 2023-07-25 13:34 23
aaba4f1e Poul Sander 2023-07-25 13:34 24
aaba4f1e Poul Sander 2023-07-25 13:34 25
#include "themes.hpp"
2660ccea Poul Sander 2023-09-22 19:25 26
#include "sago/SagoMisc.hpp"
727f4a09 Poul Sander 2026-05-24 21:47 27
#include "os.hpp"
aaba4f1e Poul Sander 2023-07-25 13:34 28
#include <vector>
5b5139a9 Poul Sander 2024-02-21 20:32 29
#include <sstream>
00759e5a Poul Sander 2023-09-24 20:01 30
#include <map>
2660ccea Poul Sander 2023-09-22 19:25 31
#include "nlohmann/json.hpp"
b9eda2d4 Poul Sander 2023-10-04 20:16 32
#include <iostream>
b9eda2d4 Poul Sander 2023-10-04 20:16 33
#include "global.hpp"
7d88cb38 Poul Sander 2023-10-05 20:48 34
#include <boost/algorithm/string/predicate.hpp>
68c75938 Poul Sander 2023-11-13 23:03 35
#include <fmt/core.h>
2660ccea Poul Sander 2023-09-22 19:25 36
2660ccea Poul Sander 2023-09-22 19:25 37
using json = nlohmann::json;
2660ccea Poul Sander 2023-09-22 19:25 38
2660ccea Poul Sander 2023-09-22 19:25 39
7602f86d Poul Sander 2024-01-10 21:39 40
const int NUMBER_OF_CUSTOM_SLOTS = 2;
7602f86d Poul Sander 2024-01-10 21:39 41
7602f86d Poul Sander 2024-01-10 21:39 42
b9eda2d4 Poul Sander 2023-10-04 20:16 43
void to_json(json& j, const ImgScale& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 44
	switch (p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 45
	case ImgScale::Stretch:
b9eda2d4 Poul Sander 2023-10-04 20:16 46
		j = "stretch";
b9eda2d4 Poul Sander 2023-10-04 20:16 47
		break;
b9eda2d4 Poul Sander 2023-10-04 20:16 48
	case ImgScale::Tile:
b9eda2d4 Poul Sander 2023-10-04 20:16 49
		j = "tile";
b9eda2d4 Poul Sander 2023-10-04 20:16 50
		break;
b9eda2d4 Poul Sander 2023-10-04 20:16 51
	case ImgScale::Resize:
b9eda2d4 Poul Sander 2023-10-04 20:16 52
		j = "resize";
b9eda2d4 Poul Sander 2023-10-04 20:16 53
		break;
b9eda2d4 Poul Sander 2023-10-04 20:16 54
	case ImgScale::Cut:
b9eda2d4 Poul Sander 2023-10-04 20:16 55
		j = "cut";
b9eda2d4 Poul Sander 2023-10-04 20:16 56
		break;
b9eda2d4 Poul Sander 2023-10-04 20:16 57
	default:
b9eda2d4 Poul Sander 2023-10-04 20:16 58
		j = "stretch";
b9eda2d4 Poul Sander 2023-10-04 20:16 59
		break;
b9eda2d4 Poul Sander 2023-10-04 20:16 60
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 61
}
b9eda2d4 Poul Sander 2023-10-04 20:16 62
b9eda2d4 Poul Sander 2023-10-04 20:16 63
void from_json(const json& j, ImgScale& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 64
	std::string s = j;
b9eda2d4 Poul Sander 2023-10-04 20:16 65
	if (s == "stretch") {
b9eda2d4 Poul Sander 2023-10-04 20:16 66
		p = ImgScale::Stretch;
b9eda2d4 Poul Sander 2023-10-04 20:16 67
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 68
	else if (s == "tile") {
b9eda2d4 Poul Sander 2023-10-04 20:16 69
		p = ImgScale::Tile;
b9eda2d4 Poul Sander 2023-10-04 20:16 70
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 71
	else if (s == "resize") {
b9eda2d4 Poul Sander 2023-10-04 20:16 72
		p = ImgScale::Resize;
b9eda2d4 Poul Sander 2023-10-04 20:16 73
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 74
	else if (s == "cut") {
b9eda2d4 Poul Sander 2023-10-04 20:16 75
		p = ImgScale::Cut;
b9eda2d4 Poul Sander 2023-10-04 20:16 76
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 77
	else {
b9eda2d4 Poul Sander 2023-10-04 20:16 78
		p = ImgScale::Stretch;
b9eda2d4 Poul Sander 2023-10-04 20:16 79
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 80
}
b9eda2d4 Poul Sander 2023-10-04 20:16 81
2660ccea Poul Sander 2023-09-22 19:25 82
void to_json(json& j, const BackGroundData& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 83
	j = json{ {"background_name", p.name}, {"background_sprite", p.background_sprite}, {"background_sprite_16x9", p.background_sprite_16x9}, {"background_scale", p.background_scale}, {"tileMoveSpeedX", p.tileMoveSpeedX}, {"tileMoveSpeedY", p.tileMoveSpeedY} };
2660ccea Poul Sander 2023-09-22 19:25 84
}
2660ccea Poul Sander 2023-09-22 19:25 85
727f4a09 Poul Sander 2026-05-24 21:47 86
void to_json(json& j, const ThemeBorderData& p) {
727f4a09 Poul Sander 2026-05-24 21:47 87
	j = json{
727f4a09 Poul Sander 2026-05-24 21:47 88
		{"border_name", p.name},
727f4a09 Poul Sander 2026-05-24 21:47 89
		{"border_sprite", p.border_sprite},
727f4a09 Poul Sander 2026-05-24 21:47 90
		{"border_sprite_offset", {p.border_sprite_offset.first, p.border_sprite_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 91
		{"score_label_offset", {p.score_label_offset.first, p.score_label_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 92
		{"time_label_offset", {p.time_label_offset.first, p.time_label_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 93
		{"chain_label_offset", {p.chain_label_offset.first, p.chain_label_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 94
		{"speed_label_offset", {p.speed_label_offset.first, p.speed_label_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 95
		{"score_field_offset", {p.score_field_offset.first, p.score_field_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 96
		{"time_field_offset", {p.time_field_offset.first, p.time_field_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 97
		{"chain_field_offset", {p.chain_field_offset.first, p.chain_field_offset.second}},
727f4a09 Poul Sander 2026-05-24 21:47 98
		{"speed_field_offset", {p.speed_field_offset.first, p.speed_field_offset.second}}
727f4a09 Poul Sander 2026-05-24 21:47 99
	};
727f4a09 Poul Sander 2026-05-24 21:47 100
}
727f4a09 Poul Sander 2026-05-24 21:47 101
2660ccea Poul Sander 2023-09-22 19:25 102
void to_json(json& j, const Theme& p) {
173b1d55 Poul Sander 2023-09-23 21:29 103
	j = json{ {"theme_name", p.theme_name}, {"back_board", p.back_board}, {"background_name", p.background.name}, {"decoration_name", p.decoration.name} };
2660ccea Poul Sander 2023-09-22 19:25 104
}
2660ccea Poul Sander 2023-09-22 19:25 105
00759e5a Poul Sander 2023-09-24 20:01 106
void to_json(json& j, const DecorationData& p) {
00759e5a Poul Sander 2023-09-24 20:01 107
	j = json{ {"name", p.name}, {"decoration_sprites", p.decoration_sprites} };
00759e5a Poul Sander 2023-09-24 20:01 108
}
00759e5a Poul Sander 2023-09-24 20:01 109
2660ccea Poul Sander 2023-09-22 19:25 110
void to_json(json& j, const ThemeFileData& p) {
727f4a09 Poul Sander 2026-05-24 21:47 111
	j = json{ {"background_data", p.background_data}, {"decoration_data", p.decoration_data}, {"border_data", p.border_data}, {"themes", p.themes} };
2660ccea Poul Sander 2023-09-22 19:25 112
}
2660ccea Poul Sander 2023-09-22 19:25 113
b9eda2d4 Poul Sander 2023-10-04 20:16 114
void from_json(const json& j, BackGroundData& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 115
	j.at("background_name").get_to(p.name);
b9eda2d4 Poul Sander 2023-10-04 20:16 116
	j.at("background_sprite").get_to(p.background_sprite);
b9eda2d4 Poul Sander 2023-10-04 20:16 117
	j.at("background_sprite_16x9").get_to(p.background_sprite_16x9);
b9eda2d4 Poul Sander 2023-10-04 20:16 118
	j.at("background_scale").get_to(p.background_scale);
b9eda2d4 Poul Sander 2023-10-04 20:16 119
	j.at("tileMoveSpeedX").get_to(p.tileMoveSpeedX);
b9eda2d4 Poul Sander 2023-10-04 20:16 120
	j.at("tileMoveSpeedY").get_to(p.tileMoveSpeedY);
b9eda2d4 Poul Sander 2023-10-04 20:16 121
}
b9eda2d4 Poul Sander 2023-10-04 20:16 122
727f4a09 Poul Sander 2026-05-24 21:47 123
void from_json(const json& j, ThemeBorderData& p) {
727f4a09 Poul Sander 2026-05-24 21:47 124
	j.at("border_name").get_to(p.name);
727f4a09 Poul Sander 2026-05-24 21:47 125
	j.at("border_sprite").get_to(p.border_sprite);
727f4a09 Poul Sander 2026-05-24 21:47 126
	if (j.contains("border_sprite_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 127
		auto offset = j.at("border_sprite_offset");
727f4a09 Poul Sander 2026-05-24 21:47 128
		p.border_sprite_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 129
	}
727f4a09 Poul Sander 2026-05-24 21:47 130
	if (j.contains("score_label_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 131
		auto offset = j.at("score_label_offset");
727f4a09 Poul Sander 2026-05-24 21:47 132
		p.score_label_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 133
	}
727f4a09 Poul Sander 2026-05-24 21:47 134
	if (j.contains("time_label_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 135
		auto offset = j.at("time_label_offset");
727f4a09 Poul Sander 2026-05-24 21:47 136
		p.time_label_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 137
	}
727f4a09 Poul Sander 2026-05-24 21:47 138
	if (j.contains("chain_label_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 139
		auto offset = j.at("chain_label_offset");
727f4a09 Poul Sander 2026-05-24 21:47 140
		p.chain_label_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 141
	}
727f4a09 Poul Sander 2026-05-24 21:47 142
	if (j.contains("speed_label_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 143
		auto offset = j.at("speed_label_offset");
727f4a09 Poul Sander 2026-05-24 21:47 144
		p.speed_label_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 145
	}
727f4a09 Poul Sander 2026-05-24 21:47 146
	if (j.contains("score_field_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 147
		auto offset = j.at("score_field_offset");
727f4a09 Poul Sander 2026-05-24 21:47 148
		p.score_field_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 149
	}
727f4a09 Poul Sander 2026-05-24 21:47 150
	if (j.contains("time_field_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 151
		auto offset = j.at("time_field_offset");
727f4a09 Poul Sander 2026-05-24 21:47 152
		p.time_field_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 153
	}
727f4a09 Poul Sander 2026-05-24 21:47 154
	if (j.contains("chain_field_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 155
		auto offset = j.at("chain_field_offset");
727f4a09 Poul Sander 2026-05-24 21:47 156
		p.chain_field_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 157
	}
727f4a09 Poul Sander 2026-05-24 21:47 158
	if (j.contains("speed_field_offset")) {
727f4a09 Poul Sander 2026-05-24 21:47 159
		auto offset = j.at("speed_field_offset");
727f4a09 Poul Sander 2026-05-24 21:47 160
		p.speed_field_offset = {offset[0], offset[1]};
727f4a09 Poul Sander 2026-05-24 21:47 161
	}
727f4a09 Poul Sander 2026-05-24 21:47 162
}
727f4a09 Poul Sander 2026-05-24 21:47 163
b9eda2d4 Poul Sander 2023-10-04 20:16 164
void from_json(const json& j, Theme& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 165
	j.at("theme_name").get_to(p.theme_name);
b9eda2d4 Poul Sander 2023-10-04 20:16 166
	j.at("back_board").get_to(p.back_board);
b9eda2d4 Poul Sander 2023-10-04 20:16 167
	j.at("background_name").get_to(p.background.name);
b9eda2d4 Poul Sander 2023-10-04 20:16 168
	j.at("decoration_name").get_to(p.decoration.name);
b9eda2d4 Poul Sander 2023-10-04 20:16 169
}
b9eda2d4 Poul Sander 2023-10-04 20:16 170
b9eda2d4 Poul Sander 2023-10-04 20:16 171
void from_json(const json& j, DecorationData& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 172
	j.at("name").get_to(p.name);
b9eda2d4 Poul Sander 2023-10-04 20:16 173
	j.at("decoration_sprites").get_to(p.decoration_sprites);
b9eda2d4 Poul Sander 2023-10-04 20:16 174
}
b9eda2d4 Poul Sander 2023-10-04 20:16 175
b9eda2d4 Poul Sander 2023-10-04 20:16 176
void from_json(const json& j, ThemeFileData& p) {
b9eda2d4 Poul Sander 2023-10-04 20:16 177
	if (j.contains("background_data")) {
b9eda2d4 Poul Sander 2023-10-04 20:16 178
		j.at("background_data").get_to(p.background_data);
b9eda2d4 Poul Sander 2023-10-04 20:16 179
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 180
	if (j.contains("decoration_data")) {
b9eda2d4 Poul Sander 2023-10-04 20:16 181
		j.at("decoration_data").get_to(p.decoration_data);
b9eda2d4 Poul Sander 2023-10-04 20:16 182
	}
727f4a09 Poul Sander 2026-05-24 21:47 183
	if (j.contains("border_data")) {
727f4a09 Poul Sander 2026-05-24 21:47 184
		j.at("border_data").get_to(p.border_data);
727f4a09 Poul Sander 2026-05-24 21:47 185
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 186
	if (j.contains("themes")) {
b9eda2d4 Poul Sander 2023-10-04 20:16 187
		j.at("themes").get_to(p.themes);
b9eda2d4 Poul Sander 2023-10-04 20:16 188
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 189
}
2660ccea Poul Sander 2023-09-22 19:25 190
2660ccea Poul Sander 2023-09-22 19:25 191
aaba4f1e Poul Sander 2023-07-25 13:34 192
aaba4f1e Poul Sander 2023-07-25 13:34 193
static std::vector<Theme> themes(1);
00759e5a Poul Sander 2023-09-24 20:01 194
static std::map<std::string, BackGroundData> background_data;
00759e5a Poul Sander 2023-09-24 20:01 195
static std::map<std::string, DecorationData> decoration_data;
5d5a5e92 Poul Sander 2024-03-06 21:41 196
static std::map<std::string, ThemeBorderData> border_data;
aaba4f1e Poul Sander 2023-07-25 13:34 197
static bool initialized = false;
aaba4f1e Poul Sander 2023-07-25 13:34 198
static size_t current_theme = 0;
aaba4f1e Poul Sander 2023-07-25 13:34 199
2660ccea Poul Sander 2023-09-22 19:25 200
66d6174b Poul Sander 2024-01-13 22:45 201
void ThemesFillMissingFields(Theme& theme) {
1de972a7 Poul Sander 2025-11-11 20:23 202
	if (theme.background.name.empty() || !ThemesBackgroundExists(theme.background.name) ) {
b9eda2d4 Poul Sander 2023-10-04 20:16 203
		//If the theme does not define a background then use the standard.
b9eda2d4 Poul Sander 2023-10-04 20:16 204
		theme.background.name = "standard";
b9eda2d4 Poul Sander 2023-10-04 20:16 205
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 206
	theme.background = background_data[theme.background.name];
b9eda2d4 Poul Sander 2023-10-04 20:16 207
}
b9eda2d4 Poul Sander 2023-10-04 20:16 208
51c4029b Poul Sander 2023-11-15 16:11 209
static void ThemesReadDataFromFile(const std::string& filename) {
b9eda2d4 Poul Sander 2023-10-04 20:16 210
	if (globalData.verboseLevel) {
b9eda2d4 Poul Sander 2023-10-04 20:16 211
		std::cout << "Reading theme data from " << filename << "\n";
b9eda2d4 Poul Sander 2023-10-04 20:16 212
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 213
	std::string s = sago::GetFileContent(filename);
68c75938 Poul Sander 2023-11-13 23:03 214
	if (s.empty()) {
68c75938 Poul Sander 2023-11-13 23:03 215
		std::cout << "File \"" << filename << "\" does not exit!\n";
68c75938 Poul Sander 2023-11-13 23:03 216
		return;
68c75938 Poul Sander 2023-11-13 23:03 217
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 218
	json j = json::parse(s);
b9eda2d4 Poul Sander 2023-10-04 20:16 219
	ThemeFileData tfd = j;
4728de18 Poul Sander 2024-04-14 20:01 220
	for (const auto& bg : tfd.background_data) {
b9eda2d4 Poul Sander 2023-10-04 20:16 221
		background_data[bg.name] = bg;
b9eda2d4 Poul Sander 2023-10-04 20:16 222
	}
4728de18 Poul Sander 2024-04-14 20:01 223
	for (const auto& dec : tfd.decoration_data) {
b9eda2d4 Poul Sander 2023-10-04 20:16 224
		decoration_data[dec.name] = dec;
b9eda2d4 Poul Sander 2023-10-04 20:16 225
	}
727f4a09 Poul Sander 2026-05-24 21:47 226
	for (const auto& border : tfd.border_data) {
727f4a09 Poul Sander 2026-05-24 21:47 227
		border_data[border.name] = border;
727f4a09 Poul Sander 2026-05-24 21:47 228
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 229
	for (const Theme& theme : tfd.themes) {
b9eda2d4 Poul Sander 2023-10-04 20:16 230
		if (globalData.verboseLevel) {
b9eda2d4 Poul Sander 2023-10-04 20:16 231
			std::cout << "Adding theme " << theme.theme_name << "\n";
b9eda2d4 Poul Sander 2023-10-04 20:16 232
		}
b9eda2d4 Poul Sander 2023-10-04 20:16 233
		themes.push_back(theme);
51c4029b Poul Sander 2023-11-15 16:11 234
		ThemesFillMissingFields(themes.back());
b9eda2d4 Poul Sander 2023-10-04 20:16 235
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 236
}
b9eda2d4 Poul Sander 2023-10-04 20:16 237
b9eda2d4 Poul Sander 2023-10-04 20:16 238
51c4029b Poul Sander 2023-11-15 16:11 239
static void ThemesInitBackGroundData() {
081d847a Poul Sander 2023-07-29 19:59 240
	BackGroundData standard;
173b1d55 Poul Sander 2023-09-23 21:29 241
	standard.name = "standard";
081d847a Poul Sander 2023-07-29 19:59 242
	standard.background_sprite = "background";
081d847a Poul Sander 2023-07-29 19:59 243
	standard.background_sprite_16x9 = "background_sixteen_nine";
081d847a Poul Sander 2023-07-29 19:59 244
	standard.background_scale = ImgScale::Stretch;
00759e5a Poul Sander 2023-09-24 20:01 245
	background_data[standard.name] = standard;
00759e5a Poul Sander 2023-09-24 20:01 246
	DecorationData smileys;
00759e5a Poul Sander 2023-09-24 20:01 247
	decoration_data[smileys.name] = smileys;
081d847a Poul Sander 2023-07-29 19:59 248
}
081d847a Poul Sander 2023-07-29 19:59 249
5d5a5e92 Poul Sander 2024-03-06 21:41 250
static void ThemesInitBorderData() {
5d5a5e92 Poul Sander 2024-03-06 21:41 251
	ThemeBorderData standard;
5d5a5e92 Poul Sander 2024-03-06 21:41 252
	standard.name = "standard";
5d5a5e92 Poul Sander 2024-03-06 21:41 253
	standard.border_sprite = "board_back_back";
5d5a5e92 Poul Sander 2024-03-06 21:41 254
	standard.border_sprite_offset = {-60, -68};
5d5a5e92 Poul Sander 2024-03-06 21:41 255
	border_data[standard.name] = standard;
5d5a5e92 Poul Sander 2024-03-06 21:41 256
	ThemeBorderData mirror = standard;
5d5a5e92 Poul Sander 2024-03-06 21:41 257
	mirror.name = "mirror";
5d5a5e92 Poul Sander 2024-03-06 21:41 258
	mirror.border_sprite = "board_back_back_mirror";
5d5a5e92 Poul Sander 2024-03-06 21:41 259
	mirror.border_sprite_offset = {-116, -68};
5d5a5e92 Poul Sander 2024-03-06 21:41 260
	mirror.score_label_offset = {-100, 80};
5d5a5e92 Poul Sander 2024-03-06 21:41 261
	mirror.time_label_offset = {-100,129};
5d5a5e92 Poul Sander 2024-03-06 21:41 262
	mirror.chain_label_offset = {-100, 178};
5d5a5e92 Poul Sander 2024-03-06 21:41 263
	mirror.speed_label_offset = {-100, 227};
727f4a09 Poul Sander 2026-05-24 21:47 264
	mirror.score_field_offset = {-100, 102};
727f4a09 Poul Sander 2026-05-24 21:47 265
	mirror.time_field_offset = {-100, 151};
727f4a09 Poul Sander 2026-05-24 21:47 266
	mirror.chain_field_offset = {-100, 200};
727f4a09 Poul Sander 2026-05-24 21:47 267
	mirror.speed_field_offset = {-100, 249};
5d5a5e92 Poul Sander 2024-03-06 21:41 268
	border_data[mirror.name] = mirror;
5d5a5e92 Poul Sander 2024-03-06 21:41 269
}
5d5a5e92 Poul Sander 2024-03-06 21:41 270
68c75938 Poul Sander 2023-11-13 23:03 271
static bool str_startswith(const std::string& s, const char* prefix) {
68c75938 Poul Sander 2023-11-13 23:03 272
	return (s.rfind(prefix, 0) == 0);
68c75938 Poul Sander 2023-11-13 23:03 273
}
2660ccea Poul Sander 2023-09-22 19:25 274
51c4029b Poul Sander 2023-11-15 16:11 275
static void ThemesDumpData() {
2660ccea Poul Sander 2023-09-22 19:25 276
	ThemeFileData tfd;
2660ccea Poul Sander 2023-09-22 19:25 277
	tfd.themes = themes;
6d46a5a3 Poul Sander 2023-09-23 14:42 278
	for (auto& pair : background_data) {
2660ccea Poul Sander 2023-09-22 19:25 279
		tfd.background_data.push_back(pair.second);
081d847a Poul Sander 2023-07-29 19:59 280
	}
00759e5a Poul Sander 2023-09-24 20:01 281
	for (auto& pair : decoration_data) {
00759e5a Poul Sander 2023-09-24 20:01 282
		tfd.decoration_data.push_back(pair.second);
00759e5a Poul Sander 2023-09-24 20:01 283
	}
727f4a09 Poul Sander 2026-05-24 21:47 284
	for (auto& pair : border_data) {
727f4a09 Poul Sander 2026-05-24 21:47 285
		tfd.border_data.push_back(pair.second);
727f4a09 Poul Sander 2026-05-24 21:47 286
	}
2660ccea Poul Sander 2023-09-22 19:25 287
	json j = tfd;
2660ccea Poul Sander 2023-09-22 19:25 288
	std::string s = j.dump(4);
2660ccea Poul Sander 2023-09-22 19:25 289
	sago::WriteFileContent("themes_dump.json", s);
081d847a Poul Sander 2023-07-29 19:59 290
}
081d847a Poul Sander 2023-07-29 19:59 291
68c75938 Poul Sander 2023-11-13 23:03 292
void ThemesSaveCustomSlots() {
68c75938 Poul Sander 2023-11-13 23:03 293
	ThemeFileData tfd;
68c75938 Poul Sander 2023-11-13 23:03 294
	for (const Theme& theme : themes) {
68c75938 Poul Sander 2023-11-13 23:03 295
		if ( str_startswith(theme.theme_name,"custom_slot_")) {
68c75938 Poul Sander 2023-11-13 23:03 296
			tfd.themes.push_back(theme);
68c75938 Poul Sander 2023-11-13 23:03 297
		}
68c75938 Poul Sander 2023-11-13 23:03 298
	}
68c75938 Poul Sander 2023-11-13 23:03 299
	json j = tfd;
68c75938 Poul Sander 2023-11-13 23:03 300
	std::string s = j.dump(4);
68c75938 Poul Sander 2023-11-13 23:03 301
	sago::WriteFileContent("custom_themes.json", s);
68c75938 Poul Sander 2023-11-13 23:03 302
}
68c75938 Poul Sander 2023-11-13 23:03 303
68c75938 Poul Sander 2023-11-13 23:03 304
static void ThemesAddCustomSlot(std::vector<Theme>& themes, int slot_number) {
68c75938 Poul Sander 2023-11-13 23:03 305
	std::string slot_name = fmt::format("custom_slot_{}", slot_number);
68c75938 Poul Sander 2023-11-13 23:03 306
	for (const Theme& theme : themes) {
68c75938 Poul Sander 2023-11-13 23:03 307
		if (theme.theme_name == slot_name) {
68c75938 Poul Sander 2023-11-13 23:03 308
			//Custom slot already exists
68c75938 Poul Sander 2023-11-13 23:03 309
			return;
68c75938 Poul Sander 2023-11-13 23:03 310
		}
68c75938 Poul Sander 2023-11-13 23:03 311
	}
68c75938 Poul Sander 2023-11-13 23:03 312
	Theme new_theme;
68c75938 Poul Sander 2023-11-13 23:03 313
	new_theme.theme_name = slot_name;
68c75938 Poul Sander 2023-11-13 23:03 314
	themes.push_back(new_theme);
51c4029b Poul Sander 2023-11-15 16:11 315
	ThemesFillMissingFields(themes.back());
68c75938 Poul Sander 2023-11-13 23:03 316
}
68c75938 Poul Sander 2023-11-13 23:03 317
51c4029b Poul Sander 2023-11-15 16:11 318
void ThemesInit() {
aaba4f1e Poul Sander 2023-07-25 13:34 319
	if (initialized) {
aaba4f1e Poul Sander 2023-07-25 13:34 320
		return;
aaba4f1e Poul Sander 2023-07-25 13:34 321
	}
b9eda2d4 Poul Sander 2023-10-04 20:16 322
	initialized = true;
51c4029b Poul Sander 2023-11-15 16:11 323
	ThemesInitBackGroundData();
5b5139a9 Poul Sander 2024-02-21 20:32 324
	ThemesInitCustomBackgrounds();
5d5a5e92 Poul Sander 2024-03-06 21:41 325
	ThemesInitBorderData();
727f4a09 Poul Sander 2026-05-24 21:47 326
	ThemesLoadCustomBorders();
727f4a09 Poul Sander 2026-05-24 21:47 327
	ThemesLoadCustomBackgrounds();
aaba4f1e Poul Sander 2023-07-25 13:34 328
	themes.resize(1);  //Add the default theme
51c4029b Poul Sander 2023-11-15 16:11 329
	ThemesFillMissingFields(themes[0]);
7d88cb38 Poul Sander 2023-10-05 20:48 330
	const std::vector<std::string>& theme_files = sago::GetFileList("themes");
7d88cb38 Poul Sander 2023-10-05 20:48 331
	for (const std::string& filename : theme_files) {
7d88cb38 Poul Sander 2023-10-05 20:48 332
		if (boost::algorithm::ends_with(filename,".json")) {
51c4029b Poul Sander 2023-11-15 16:11 333
			ThemesReadDataFromFile("themes/"+filename);
7d88cb38 Poul Sander 2023-10-05 20:48 334
		}
7d88cb38 Poul Sander 2023-10-05 20:48 335
	}
51c4029b Poul Sander 2023-11-15 16:11 336
	ThemesReadDataFromFile("custom_themes.json");
7602f86d Poul Sander 2024-01-10 21:39 337
	for (int i=1; i <= NUMBER_OF_CUSTOM_SLOTS; ++i) {
68c75938 Poul Sander 2023-11-13 23:03 338
		ThemesAddCustomSlot(themes, i);
68c75938 Poul Sander 2023-11-13 23:03 339
	}
51c4029b Poul Sander 2023-11-15 16:11 340
	ThemesDumpData();
aaba4f1e Poul Sander 2023-07-25 13:34 341
}
aaba4f1e Poul Sander 2023-07-25 13:34 342
51c4029b Poul Sander 2023-11-15 16:11 343
Theme ThemesGetNext() {
51c4029b Poul Sander 2023-11-15 16:11 344
	ThemesInit();
aaba4f1e Poul Sander 2023-07-25 13:34 345
	current_theme++;
aaba4f1e Poul Sander 2023-07-25 13:34 346
	current_theme = current_theme % themes.size();
aaba4f1e Poul Sander 2023-07-25 13:34 347
	return themes.at(current_theme);
aaba4f1e Poul Sander 2023-07-25 13:34 348
}
081d847a Poul Sander 2023-07-29 19:59 349
7602f86d Poul Sander 2024-01-10 21:39 350
Theme& ThemesGet(size_t theme_number) {
51c4029b Poul Sander 2023-11-15 16:11 351
	ThemesInit();
081d847a Poul Sander 2023-07-29 19:59 352
	return themes.at(theme_number % themes.size());
081d847a Poul Sander 2023-07-29 19:59 353
}
7602f86d Poul Sander 2024-01-10 21:39 354
f45790f5 Poul Sander 2024-04-14 19:29 355
size_t ThemesGetNumber(const std::string& name) {
7602f86d Poul Sander 2024-01-10 21:39 356
	size_t ret = 0;  // Default to 0
7602f86d Poul Sander 2024-01-10 21:39 357
	ThemesInit();
7602f86d Poul Sander 2024-01-10 21:39 358
	for (size_t i = 0; i < themes.size(); ++i) {
7602f86d Poul Sander 2024-01-10 21:39 359
		if (themes[i].theme_name == name) {
7602f86d Poul Sander 2024-01-10 21:39 360
			ret = i;
7602f86d Poul Sander 2024-01-10 21:39 361
		}
7602f86d Poul Sander 2024-01-10 21:39 362
	}
7602f86d Poul Sander 2024-01-10 21:39 363
	return ret;
7602f86d Poul Sander 2024-01-10 21:39 364
}
66d6174b Poul Sander 2024-01-13 22:45 365
66d6174b Poul Sander 2024-01-13 22:45 366
void ThemesAddOrReplace(const Theme& theme) {
66d6174b Poul Sander 2024-01-13 22:45 367
	ThemesInit();
66d6174b Poul Sander 2024-01-13 22:45 368
	for (size_t i = 0; i < themes.size(); ++i) {
66d6174b Poul Sander 2024-01-13 22:45 369
		if (themes[i].theme_name == theme.theme_name) {
66d6174b Poul Sander 2024-01-13 22:45 370
			themes[i] = theme;
66d6174b Poul Sander 2024-01-13 22:45 371
			return;
66d6174b Poul Sander 2024-01-13 22:45 372
		}
66d6174b Poul Sander 2024-01-13 22:45 373
	}
66d6174b Poul Sander 2024-01-13 22:45 374
	themes.push_back(theme);
66d6174b Poul Sander 2024-01-13 22:45 375
}
66d6174b Poul Sander 2024-01-13 22:45 376
4728de18 Poul Sander 2024-04-14 20:01 377
bool ThemesBackgroundExists(const std::string& name) {
4728de18 Poul Sander 2024-04-14 20:01 378
	ThemesInit();
4728de18 Poul Sander 2024-04-14 20:01 379
	return background_data.find(name) != background_data.end();
4728de18 Poul Sander 2024-04-14 20:01 380
}
4728de18 Poul Sander 2024-04-14 20:01 381
66d6174b Poul Sander 2024-01-13 22:45 382
BackGroundData ThemesGetNextBackground(const std::string& current) {
66d6174b Poul Sander 2024-01-13 22:45 383
	ThemesInit();
66d6174b Poul Sander 2024-01-13 22:45 384
	BackGroundData ret = background_data["standard"];
66d6174b Poul Sander 2024-01-13 22:45 385
	for (auto& pair : background_data) {
66d6174b Poul Sander 2024-01-13 22:45 386
		if (pair.first == current) {
66d6174b Poul Sander 2024-01-13 22:45 387
			auto it = background_data.find(current);
66d6174b Poul Sander 2024-01-13 22:45 388
			++it;
66d6174b Poul Sander 2024-01-13 22:45 389
			if (it == background_data.end()) {
66d6174b Poul Sander 2024-01-13 22:45 390
				it = background_data.begin();
66d6174b Poul Sander 2024-01-13 22:45 391
			}
66d6174b Poul Sander 2024-01-13 22:45 392
			ret = it->second;
66d6174b Poul Sander 2024-01-13 22:45 393
			break;
66d6174b Poul Sander 2024-01-13 22:45 394
		}
66d6174b Poul Sander 2024-01-13 22:45 395
	}
66d6174b Poul Sander 2024-01-13 22:45 396
	return ret;
66d6174b Poul Sander 2024-01-13 22:45 397
}
de41f458 Poul Sander 2024-01-29 20:53 398
de41f458 Poul Sander 2024-01-29 20:53 399
std::string ThemesGetNextBoardBackground(const std::string& current) {
de41f458 Poul Sander 2024-01-29 20:53 400
	ThemesInit();
de41f458 Poul Sander 2024-01-29 20:53 401
	std::vector<std::string> back_boards = {"back_board", "back_board_sample_snow", "trans_cover"};
de41f458 Poul Sander 2024-01-29 20:53 402
	std::string ret = "back_board";
de41f458 Poul Sander 2024-01-29 20:53 403
	for (size_t i = 0; i < back_boards.size(); ++i) {
de41f458 Poul Sander 2024-01-29 20:53 404
		if (back_boards[i] == current) {
de41f458 Poul Sander 2024-01-29 20:53 405
			ret = back_boards[(i + 1) % back_boards.size()];
de41f458 Poul Sander 2024-01-29 20:53 406
			break;
de41f458 Poul Sander 2024-01-29 20:53 407
		}
de41f458 Poul Sander 2024-01-29 20:53 408
	}
de41f458 Poul Sander 2024-01-29 20:53 409
	return ret;
de41f458 Poul Sander 2024-01-29 20:53 410
}
5b5139a9 Poul Sander 2024-02-21 20:32 411
5d5a5e92 Poul Sander 2024-03-06 21:41 412
ThemeBorderData ThemesGetBorder(const std::string& name) {
5d5a5e92 Poul Sander 2024-03-06 21:41 413
	ThemesInit();
5d5a5e92 Poul Sander 2024-03-06 21:41 414
	auto it = border_data.find(name);
5d5a5e92 Poul Sander 2024-03-06 21:41 415
	if (it == border_data.end()) {
5d5a5e92 Poul Sander 2024-03-06 21:41 416
		return border_data["standard"];
5d5a5e92 Poul Sander 2024-03-06 21:41 417
	}
5d5a5e92 Poul Sander 2024-03-06 21:41 418
	return it->second;
5d5a5e92 Poul Sander 2024-03-06 21:41 419
}
5d5a5e92 Poul Sander 2024-03-06 21:41 420
5d5a5e92 Poul Sander 2024-03-06 21:41 421
ThemeBorderData ThemesGetNextBorder(const std::string& current) {
5d5a5e92 Poul Sander 2024-03-06 21:41 422
	ThemesInit();
5d5a5e92 Poul Sander 2024-03-06 21:41 423
	ThemeBorderData ret = border_data["standard"];
5d5a5e92 Poul Sander 2024-03-06 21:41 424
	for (auto& pair : border_data) {
5d5a5e92 Poul Sander 2024-03-06 21:41 425
		if (pair.first == current) {
5d5a5e92 Poul Sander 2024-03-06 21:41 426
			auto it = border_data.find(current);
5d5a5e92 Poul Sander 2024-03-06 21:41 427
			++it;
5d5a5e92 Poul Sander 2024-03-06 21:41 428
			if (it == border_data.end()) {
5d5a5e92 Poul Sander 2024-03-06 21:41 429
				it = border_data.begin();
5d5a5e92 Poul Sander 2024-03-06 21:41 430
			}
5d5a5e92 Poul Sander 2024-03-06 21:41 431
			ret = it->second;
5d5a5e92 Poul Sander 2024-03-06 21:41 432
			break;
5d5a5e92 Poul Sander 2024-03-06 21:41 433
		}
5d5a5e92 Poul Sander 2024-03-06 21:41 434
	}
5d5a5e92 Poul Sander 2024-03-06 21:41 435
	return ret;
5d5a5e92 Poul Sander 2024-03-06 21:41 436
}
5d5a5e92 Poul Sander 2024-03-06 21:41 437
5b5139a9 Poul Sander 2024-02-21 20:32 438
void ThemesInitCustomBackgrounds() {
5b5139a9 Poul Sander 2024-02-21 20:32 439
	std::vector<std::string> custom_backgrounds = sago::GetFileList("textures/backgrounds");
5b5139a9 Poul Sander 2024-02-21 20:32 440
	std::stringstream sprite_stream;
5b5139a9 Poul Sander 2024-02-21 20:32 441
	sprite_stream << "{\n";
5b5139a9 Poul Sander 2024-02-21 20:32 442
	bool first = true;
5b5139a9 Poul Sander 2024-02-21 20:32 443
	for (const std::string& filename : custom_backgrounds) {
5b5139a9 Poul Sander 2024-02-21 20:32 444
		std::cout << "Found custom background " << filename << "\n";
5b5139a9 Poul Sander 2024-02-21 20:32 445
		if (boost::algorithm::ends_with(filename, ".png") || boost::algorithm::ends_with(filename, ".jpg")) {
5b5139a9 Poul Sander 2024-02-21 20:32 446
			BackGroundData bg;
5b5139a9 Poul Sander 2024-02-21 20:32 447
			bg.name = filename;
5b5139a9 Poul Sander 2024-02-21 20:32 448
			std::string texture_name = fmt::format("custom_background_{}",filename);;
5b5139a9 Poul Sander 2024-02-21 20:32 449
			bg.background_sprite = texture_name;
5b5139a9 Poul Sander 2024-02-21 20:32 450
			bg.background_sprite_16x9 = texture_name;
5b5139a9 Poul Sander 2024-02-21 20:32 451
			bg.background_scale = ImgScale::Resize;
5b5139a9 Poul Sander 2024-02-21 20:32 452
			background_data[bg.name] = bg;
5b5139a9 Poul Sander 2024-02-21 20:32 453
			if (!first) {
5b5139a9 Poul Sander 2024-02-21 20:32 454
				sprite_stream << ",\n";
5b5139a9 Poul Sander 2024-02-21 20:32 455
			}
5b5139a9 Poul Sander 2024-02-21 20:32 456
			sprite_stream << "\"" << texture_name << "\": {\n";
5b5139a9 Poul Sander 2024-02-21 20:32 457
			sprite_stream << "  \"texture\": \"" << "backgrounds/" << filename.substr(0, filename.size()-4) << "\",\n";
5b5139a9 Poul Sander 2024-02-21 20:32 458
			sprite_stream << "  \"topx\": 0,\n";
5b5139a9 Poul Sander 2024-02-21 20:32 459
			sprite_stream << "  \"topy\": 0,\n";
5b5139a9 Poul Sander 2024-02-21 20:32 460
			sprite_stream << "  \"height\": 7680,\n";
5b5139a9 Poul Sander 2024-02-21 20:32 461
			sprite_stream << "  \"width\": 10240,\n";
5b5139a9 Poul Sander 2024-02-21 20:32 462
			sprite_stream << "  \"number_of_frames\": 1,\n";
5b5139a9 Poul Sander 2024-02-21 20:32 463
			sprite_stream << "  \"frame_time\": 1\n";
5b5139a9 Poul Sander 2024-02-21 20:32 464
			sprite_stream << "}\n";
5b5139a9 Poul Sander 2024-02-21 20:32 465
			first = false;
5b5139a9 Poul Sander 2024-02-21 20:32 466
5b5139a9 Poul Sander 2024-02-21 20:32 467
		}
5b5139a9 Poul Sander 2024-02-21 20:32 468
	}
5b5139a9 Poul Sander 2024-02-21 20:32 469
	sprite_stream << "}\n";
5b5139a9 Poul Sander 2024-02-21 20:32 470
	sago::WriteFileContent("sprites/custom_backgrounds.sprite", sprite_stream.str());
727f4a09 Poul Sander 2026-05-24 21:47 471
}
727f4a09 Poul Sander 2026-05-24 21:47 472
727f4a09 Poul Sander 2026-05-24 21:47 473
void ThemesSaveBorderData(const std::string& name, const ThemeBorderData& data) {
727f4a09 Poul Sander 2026-05-24 21:47 474
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 475
	// Create borders directory if it doesn't exist
727f4a09 Poul Sander 2026-05-24 21:47 476
	OsCreateFolder("borders");
727f4a09 Poul Sander 2026-05-24 21:47 477
727f4a09 Poul Sander 2026-05-24 21:47 478
	json j = data;
727f4a09 Poul Sander 2026-05-24 21:47 479
	std::string s = j.dump(4);
727f4a09 Poul Sander 2026-05-24 21:47 480
	std::string filename = fmt::format("borders/{}.json", name);
727f4a09 Poul Sander 2026-05-24 21:47 481
	sago::WriteFileContent(filename.c_str(), s);
727f4a09 Poul Sander 2026-05-24 21:47 482
727f4a09 Poul Sander 2026-05-24 21:47 483
	// Add to the border_data map
727f4a09 Poul Sander 2026-05-24 21:47 484
	border_data[name] = data;
727f4a09 Poul Sander 2026-05-24 21:47 485
}
727f4a09 Poul Sander 2026-05-24 21:47 486
727f4a09 Poul Sander 2026-05-24 21:47 487
void ThemesSaveBackgroundData(const std::string& name, const BackGroundData& data) {
727f4a09 Poul Sander 2026-05-24 21:47 488
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 489
	// Create backgrounds directory if it doesn't exist
727f4a09 Poul Sander 2026-05-24 21:47 490
	OsCreateFolder("backgrounds");
727f4a09 Poul Sander 2026-05-24 21:47 491
727f4a09 Poul Sander 2026-05-24 21:47 492
	json j = data;
727f4a09 Poul Sander 2026-05-24 21:47 493
	std::string s = j.dump(4);
727f4a09 Poul Sander 2026-05-24 21:47 494
	std::string filename = fmt::format("backgrounds/{}.json", name);
727f4a09 Poul Sander 2026-05-24 21:47 495
	sago::WriteFileContent(filename.c_str(), s);
727f4a09 Poul Sander 2026-05-24 21:47 496
727f4a09 Poul Sander 2026-05-24 21:47 497
	// Add to the background_data map
727f4a09 Poul Sander 2026-05-24 21:47 498
	background_data[name] = data;
727f4a09 Poul Sander 2026-05-24 21:47 499
}
727f4a09 Poul Sander 2026-05-24 21:47 500
727f4a09 Poul Sander 2026-05-24 21:47 501
void ThemesLoadCustomBorders() {
727f4a09 Poul Sander 2026-05-24 21:47 502
	const std::vector<std::string>& border_files = sago::GetFileList("borders");
727f4a09 Poul Sander 2026-05-24 21:47 503
	for (const std::string& filename : border_files) {
727f4a09 Poul Sander 2026-05-24 21:47 504
		if (boost::algorithm::ends_with(filename, ".json")) {
727f4a09 Poul Sander 2026-05-24 21:47 505
			std::string filepath = fmt::format("borders/{}", filename);
727f4a09 Poul Sander 2026-05-24 21:47 506
			std::string s = sago::GetFileContent(filepath);
727f4a09 Poul Sander 2026-05-24 21:47 507
			if (s.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 508
				continue;
727f4a09 Poul Sander 2026-05-24 21:47 509
			}
727f4a09 Poul Sander 2026-05-24 21:47 510
			try {
727f4a09 Poul Sander 2026-05-24 21:47 511
				json j = json::parse(s);
727f4a09 Poul Sander 2026-05-24 21:47 512
				ThemeBorderData border = j;
727f4a09 Poul Sander 2026-05-24 21:47 513
				border_data[border.name] = border;
727f4a09 Poul Sander 2026-05-24 21:47 514
				if (globalData.verboseLevel) {
727f4a09 Poul Sander 2026-05-24 21:47 515
					std::cout << "Loaded custom border: " << border.name << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 516
				}
727f4a09 Poul Sander 2026-05-24 21:47 517
			}
727f4a09 Poul Sander 2026-05-24 21:47 518
			catch (const std::exception& e) {
727f4a09 Poul Sander 2026-05-24 21:47 519
				std::cerr << "Error loading border file " << filepath << ": " << e.what() << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 520
			}
727f4a09 Poul Sander 2026-05-24 21:47 521
		}
727f4a09 Poul Sander 2026-05-24 21:47 522
	}
727f4a09 Poul Sander 2026-05-24 21:47 523
}
727f4a09 Poul Sander 2026-05-24 21:47 524
727f4a09 Poul Sander 2026-05-24 21:47 525
void ThemesLoadCustomBackgrounds() {
727f4a09 Poul Sander 2026-05-24 21:47 526
	const std::vector<std::string>& background_files = sago::GetFileList("backgrounds");
727f4a09 Poul Sander 2026-05-24 21:47 527
	for (const std::string& filename : background_files) {
727f4a09 Poul Sander 2026-05-24 21:47 528
		if (boost::algorithm::ends_with(filename, ".json")) {
727f4a09 Poul Sander 2026-05-24 21:47 529
			std::string filepath = fmt::format("backgrounds/{}", filename);
727f4a09 Poul Sander 2026-05-24 21:47 530
			std::string s = sago::GetFileContent(filepath);
727f4a09 Poul Sander 2026-05-24 21:47 531
			if (s.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 532
				continue;
727f4a09 Poul Sander 2026-05-24 21:47 533
			}
727f4a09 Poul Sander 2026-05-24 21:47 534
			try {
727f4a09 Poul Sander 2026-05-24 21:47 535
				json j = json::parse(s);
727f4a09 Poul Sander 2026-05-24 21:47 536
				BackGroundData background = j;
727f4a09 Poul Sander 2026-05-24 21:47 537
				background_data[background.name] = background;
727f4a09 Poul Sander 2026-05-24 21:47 538
				if (globalData.verboseLevel) {
727f4a09 Poul Sander 2026-05-24 21:47 539
					std::cout << "Loaded custom background: " << background.name << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 540
				}
727f4a09 Poul Sander 2026-05-24 21:47 541
			}
727f4a09 Poul Sander 2026-05-24 21:47 542
			catch (const std::exception& e) {
727f4a09 Poul Sander 2026-05-24 21:47 543
				std::cerr << "Error loading background file " << filepath << ": " << e.what() << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 544
			}
727f4a09 Poul Sander 2026-05-24 21:47 545
		}
727f4a09 Poul Sander 2026-05-24 21:47 546
	}
727f4a09 Poul Sander 2026-05-24 21:47 547
}
727f4a09 Poul Sander 2026-05-24 21:47 548
727f4a09 Poul Sander 2026-05-24 21:47 549
bool ThemesValidateSpriteName(const std::string& sprite_name) {
727f4a09 Poul Sander 2026-05-24 21:47 550
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 551
	if (sprite_name.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 552
		return false;
727f4a09 Poul Sander 2026-05-24 21:47 553
	}
727f4a09 Poul Sander 2026-05-24 21:47 554
	// Note: GetSprite returns a default sprite if not found, so we can't easily validate
727f4a09 Poul Sander 2026-05-24 21:47 555
	// The sprite will be validated when actually used in the game
727f4a09 Poul Sander 2026-05-24 21:47 556
	// For now, just check that it's not empty
727f4a09 Poul Sander 2026-05-24 21:47 557
	return true;
727f4a09 Poul Sander 2026-05-24 21:47 558
}
727f4a09 Poul Sander 2026-05-24 21:47 559
727f4a09 Poul Sander 2026-05-24 21:47 560
std::vector<std::string> ThemesGetBorderNames() {
727f4a09 Poul Sander 2026-05-24 21:47 561
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 562
	std::vector<std::string> names;
727f4a09 Poul Sander 2026-05-24 21:47 563
	for (const auto& pair : border_data) {
727f4a09 Poul Sander 2026-05-24 21:47 564
		names.push_back(pair.first);
727f4a09 Poul Sander 2026-05-24 21:47 565
	}
727f4a09 Poul Sander 2026-05-24 21:47 566
	return names;
727f4a09 Poul Sander 2026-05-24 21:47 567
}
727f4a09 Poul Sander 2026-05-24 21:47 568
727f4a09 Poul Sander 2026-05-24 21:47 569
std::vector<std::string> ThemesGetBackgroundNames() {
727f4a09 Poul Sander 2026-05-24 21:47 570
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 571
	std::vector<std::string> names;
727f4a09 Poul Sander 2026-05-24 21:47 572
	for (const auto& pair : background_data) {
727f4a09 Poul Sander 2026-05-24 21:47 573
		names.push_back(pair.first);
727f4a09 Poul Sander 2026-05-24 21:47 574
	}
727f4a09 Poul Sander 2026-05-24 21:47 575
	return names;
727f4a09 Poul Sander 2026-05-24 21:47 576
}
727f4a09 Poul Sander 2026-05-24 21:47 577
727f4a09 Poul Sander 2026-05-24 21:47 578
std::vector<std::string> ThemesGetDecorationNames() {
727f4a09 Poul Sander 2026-05-24 21:47 579
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 580
	std::vector<std::string> names;
727f4a09 Poul Sander 2026-05-24 21:47 581
	for (const auto& pair : decoration_data) {
727f4a09 Poul Sander 2026-05-24 21:47 582
		names.push_back(pair.first);
727f4a09 Poul Sander 2026-05-24 21:47 583
	}
727f4a09 Poul Sander 2026-05-24 21:47 584
	return names;
727f4a09 Poul Sander 2026-05-24 21:47 585
}
727f4a09 Poul Sander 2026-05-24 21:47 586
727f4a09 Poul Sander 2026-05-24 21:47 587
BackGroundData ThemesGetBackground(const std::string& name) {
727f4a09 Poul Sander 2026-05-24 21:47 588
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 589
	auto it = background_data.find(name);
727f4a09 Poul Sander 2026-05-24 21:47 590
	if (it == background_data.end()) {
727f4a09 Poul Sander 2026-05-24 21:47 591
		return background_data["standard"];
727f4a09 Poul Sander 2026-05-24 21:47 592
	}
727f4a09 Poul Sander 2026-05-24 21:47 593
	return it->second;
5b5139a9 Poul Sander 2024-02-21 20:32 594
}