aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/interface/UI.cpp
blob: ea871dea05cc0b666ced797c7372e567248256ad (plain) (blame)
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);
}