1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include "UI.hpp"
#include "openvic-simulation/types/Colour.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
using namespace OpenVic::GFX;
using namespace OpenVic::GUI;
bool UIManager::add_font(
std::string_view identifier, colour_argb_t colour, std::string_view fontname, std::string_view charset, uint32_t height
) {
if (identifier.empty()) {
Logger::error("Invalid font identifier - empty!");
return false;
}
if (colour.alpha == colour_argb_t::colour_traits::null) {
Logger::error("Invalid colour for font ", identifier, " - completely transparent! (", colour, ")");
return false;
}
if (fontname.empty()) {
Logger::error("Invalid fontname for font ", identifier, " - empty!");
return false;
}
return fonts.add_item({ identifier, colour, fontname, charset, height }, duplicate_warning_callback);
}
bool UIManager::_load_font(ast::NodeCPtr node) {
std::string_view identifier, fontname, charset;
colour_argb_t colour = colour_argb_t::null();
uint32_t height = 0;
bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(identifier)),
"fontname", ONE_EXACTLY, expect_string(assign_variable_callback(fontname)),
"color", ONE_EXACTLY, expect_colour_hex(assign_variable_callback(colour)),
"charset", ZERO_OR_ONE, expect_string(assign_variable_callback(charset)),
"height", ZERO_OR_ONE, expect_uint(assign_variable_callback(height)),
"colorcodes", ZERO_OR_ONE, success_callback,
"effect", ZERO_OR_ONE, success_callback
)(node);
ret &= add_font(identifier, colour, fontname, charset, height);
return ret;
}
NodeCallback auto UIManager::_load_fonts(std::string_view font_key) {
return expect_dictionary_reserve_length(
fonts,
[this, font_key](std::string_view key, ast::NodeCPtr node) -> bool {
if (key != font_key) {
Logger::error("Invalid key: \"", key, "\" (expected ", font_key, ")");
return false;
}
return _load_font(node);
}
);
}
void UIManager::lock_gfx_registries() {
lock_sprites();
lock_fonts();
lock_objects();
}
bool UIManager::load_gfx_file(ast::NodeCPtr root) {
return expect_dictionary_keys(
"spriteTypes", ZERO_OR_ONE, Sprite::expect_sprites(
NodeTools::reserve_length_callback(sprites),
[this](std::unique_ptr<Sprite>&& sprite) -> bool {
/* TODO - more checks on duplicates (the false here reduces them from
* errors to warnings). The repeats in vanilla are identical (simple
* texture sprites with the same name referring to the same asset),
* maybe check if duplicates are equal? (this would require some kind
* of duplicate handling callback for `add_item`)
*
* It's also possible that some of the vanilla duplicates are intentional,
* after all I'm assuming all GFX files are loaded into a global registry
* rather than each GUI file using only the contnts of a few specific,
* maybe even hardcoded GFX files. This can't, however, explain all of the
* vanilla duplicates, as GFX_frontend_tab_button is repeated in the same
* file, albeit in a section marked "OLD STUFF BELOW..".
*
* Vanilla Duplicates:
* - GFX_bp_open_manager and GFX_bp_toggle_visible
* - simple texture sprites appearing identically in menubar.gfx and battleplansinterface.gfx
* - GFX_frontend_tab_button
* - texture sprite appearing twice identically in the same file (temp_frontend.gfx),
* both below a comment saying "OLD STUFF BELOW.."
*/
return sprites.add_item(std::move(sprite), duplicate_warning_callback);
}
),
"bitmapfonts", ZERO_OR_ONE, _load_fonts("bitmapfont"),
"fonts", ZERO_OR_ONE, _load_fonts("font"),
"objectTypes", ZERO_OR_ONE, Object::expect_objects(
NodeTools::reserve_length_callback(objects),
[this](std::unique_ptr<Object>&& object) -> bool {
/* There are various models with the same name but slight differences, e.g. Prussian and German variants
* of PrussianGCCavalry (the latter added in a spritepack). Currently we default to using the first loaded
* model of each name, but we may want to switch to using the last loaded or allow multiple models per name
* (e.g. by grouping them per gfx file). */
return objects.add_item(std::move(object), duplicate_warning_callback);
}
),
"lightTypes", ZERO_OR_ONE, success_callback
)(root);
}
bool UIManager::load_gui_file(std::string_view scene_name, ast::NodeCPtr root) {
if (!sprites_are_locked()) {
Logger::error("Cannot load GUI files until GFX files (i.e. Sprites) are locked!");
return false;
}
return expect_dictionary_keys(
"guiTypes", ZERO_OR_ONE, Scene::expect_scene(
scene_name,
[this](std::unique_ptr<Scene>&& scene) -> bool {
return scenes.add_item(std::move(scene));
},
*this
)
)(root);
}
|