aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/openvic-simulation/country/Country.cpp15
-rw-r--r--src/openvic-simulation/country/Country.hpp3
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp3
-rw-r--r--src/openvic-simulation/interface/GFXObject.cpp104
-rw-r--r--src/openvic-simulation/interface/GFXObject.hpp42
-rw-r--r--src/openvic-simulation/interface/UI.cpp6
-rw-r--r--src/openvic-simulation/interface/UI.hpp5
-rw-r--r--src/openvic-simulation/pop/Culture.cpp30
-rw-r--r--src/openvic-simulation/pop/Culture.hpp7
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp21
10 files changed, 157 insertions, 79 deletions
diff --git a/src/openvic-simulation/country/Country.cpp b/src/openvic-simulation/country/Country.cpp
index 5ec4aee..0fdeb60 100644
--- a/src/openvic-simulation/country/Country.cpp
+++ b/src/openvic-simulation/country/Country.cpp
@@ -43,14 +43,12 @@ Country::Country(
alternative_colours { std::move(new_alternative_colours) },
primary_unit_colour { new_primary_unit_colour },
secondary_unit_colour { new_secondary_unit_colour },
- tertiary_unit_colour { new_tertiary_unit_colour }
- {}
+ tertiary_unit_colour { new_tertiary_unit_colour } {}
bool CountryManager::add_country(
std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture,
IdentifierRegistry<CountryParty>&& parties, Country::unit_names_map_t&& unit_names, bool dynamic_tag,
- Country::government_colour_map_t&& alternative_colours,
- colour_t primary_unit_colour, colour_t secondary_unit_colour, colour_t tertiary_unit_colour
+ Country::government_colour_map_t&& alternative_colours
) {
if (identifier.empty()) {
Logger::error("Invalid country identifier - empty!");
@@ -67,9 +65,13 @@ bool CountryManager::add_country(
return false;
}
+ static constexpr colour_t default_colour = colour_t::fill_as(colour_t::max_value);
+
return countries.add_item({
identifier, colour, *graphical_culture, std::move(parties), std::move(unit_names), dynamic_tag,
- std::move(alternative_colours), primary_unit_colour, secondary_unit_colour, tertiary_unit_colour
+ std::move(alternative_colours),
+ /* Default to country colour for the chest and grey for the others. Update later if necessary. */
+ colour, default_colour, default_colour
});
}
@@ -205,8 +207,7 @@ bool CountryManager::load_country_data_file(
)(root);
ret &= add_country(
- name, colour, graphical_culture, std::move(parties), std::move(unit_names), is_dynamic,
- std::move(alternative_colours), colour_t::null(), colour_t::null(), colour_t::null()
+ name, colour, graphical_culture, std::move(parties), std::move(unit_names), is_dynamic, std::move(alternative_colours)
);
return ret;
}
diff --git a/src/openvic-simulation/country/Country.hpp b/src/openvic-simulation/country/Country.hpp
index ea8f732..1d960c2 100644
--- a/src/openvic-simulation/country/Country.hpp
+++ b/src/openvic-simulation/country/Country.hpp
@@ -85,8 +85,7 @@ namespace OpenVic {
bool add_country(
std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture,
IdentifierRegistry<CountryParty>&& parties, Country::unit_names_map_t&& unit_names, bool dynamic_tag,
- Country::government_colour_map_t&& alternative_colours,
- colour_t primary_unit_colour, colour_t secondary_unit_colour, colour_t tertiary_unit_colour
+ Country::government_colour_map_t&& alternative_colours
);
bool load_country_colours(ast::NodeCPtr root);
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index e13bc23..f99417f 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -280,8 +280,7 @@ bool Dataloader::_load_interface_files(UIManager& ui_manager) const {
return ui_manager.load_gfx_file(parse_defines(file).get_file_node());
}
);
- ui_manager.lock_sprites();
- ui_manager.lock_fonts();
+ ui_manager.lock_gfx_registries();
/* Hard-coded GUI file names, might be replaced with a dynamic system but everything should still be loaded on startup. */
static const std::vector<std::string_view> gui_files {
diff --git a/src/openvic-simulation/interface/GFXObject.cpp b/src/openvic-simulation/interface/GFXObject.cpp
index d873db1..67abc4d 100644
--- a/src/openvic-simulation/interface/GFXObject.cpp
+++ b/src/openvic-simulation/interface/GFXObject.cpp
@@ -101,44 +101,92 @@ node_callback_t Object::expect_objects(length_callback_t length_callback, callba
);
}
-Actor::Attachment::Attachment() : node {}, attach_id { 0 } {}
+Actor::Attachment::Attachment(std::string_view new_actor_name, std::string_view new_attach_node, attach_id_t new_attach_id)
+ : actor_name { new_actor_name }, attach_node { new_attach_node }, attach_id { new_attach_id } {}
-bool Actor::Attachment::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) {
- bool ret = Named::_fill_key_map(key_map);
- ret &= add_key_map_entries(key_map,
- "node", ONE_EXACTLY, expect_string(assign_variable_callback_string(node)),
- "attachId", ONE_EXACTLY, expect_uint(assign_variable_callback(attach_id))
- );
- return ret;
-}
+Actor::Animation::Animation(std::string_view new_file, fixed_point_t new_scroll_time)
+ : file { new_file }, scroll_time { new_scroll_time } {}
-Actor::Animation::Animation() : file {}, default_time { 0 } {}
+Actor::Actor() : model_file {}, scale { 1 }, idle_animation {}, move_animation {}, attack_animation {} {}
-bool Actor::Animation::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) {
- bool ret = Named::_fill_key_map(key_map);
- ret &= add_key_map_entries(key_map,
- "file", ONE_EXACTLY, expect_string(assign_variable_callback_string(file)),
- "defaultAnimationTime", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(default_time))
- );
- return ret;
-}
+bool Actor::_set_animation(std::string_view name, std::string_view file, fixed_point_t scroll_time) {
+ std::optional<Animation>* animation = nullptr;
+
+ if (name == "idle") {
+ animation = &idle_animation;
+ } else if (name == "move") {
+ animation = &move_animation;
+ } else if (name == "attack") {
+ animation = &attack_animation;
+ } else {
+ Logger::error(
+ "Unknown animation type \"", name, "\" for actor ", get_name(), " (with file ", file, " and scroll time ",
+ scroll_time, ")"
+ );
+ return false;
+ }
+
+ if (animation->has_value()) {
+ Logger::error(
+ "Duplicate ", name, " animation for actor ", get_name(), ": ", file, " with scroll time ",
+ scroll_time, " (already set to ", (*animation)->file, " with scroll time ", (*animation)->scroll_time, ")"
+ );
+ return false;
+ }
-Actor::Actor() : model_file {}, idle_animation_file {}, move_animation_file {}, attack_animation_file {}, scale { 1 } {}
+ /* Don't set static/non-moving animation, to avoid needing an AnimationPlayer for the generated Godot Skeleton3D. */
+ static constexpr std::string_view null_animation = "static.xsm";
+ if (file.ends_with(null_animation)) {
+ return true;
+ }
+
+ animation->emplace(Animation { file, scroll_time });
+ return true;
+}
bool Actor::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) {
bool ret = Object::_fill_key_map(key_map);
+
ret &= add_key_map_entries(key_map,
"actorfile", ONE_EXACTLY, expect_string(assign_variable_callback_string(model_file)),
- "idle", ZERO_OR_ONE, expect_string(assign_variable_callback_string(idle_animation_file)),
- "move", ZERO_OR_ONE, expect_string(assign_variable_callback_string(move_animation_file)),
- "attack", ZERO_OR_ONE, expect_string(assign_variable_callback_string(attack_animation_file)),
"scale", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(scale)),
- "attach", ZERO_OR_MORE, Attachment::_expect_value<Attachment>([this](Attachment&& attachment) -> bool {
- return attachments.add_item(std::move(attachment));
- }),
- "animation", ZERO_OR_MORE, Animation::_expect_value<Animation>([this](Animation&& animation) -> bool {
- return animations.add_item(std::move(animation));
- })
+
+ "attach", ZERO_OR_MORE, [this](ast::NodeCPtr node) -> bool {
+ std::string_view actor_name {}, attach_node {};
+ Attachment::attach_id_t attach_id = 0;
+
+ if (!expect_dictionary_keys<StringMapCaseInsensitive>(
+ "name", ONE_EXACTLY, expect_string(assign_variable_callback(actor_name)),
+ "node", ONE_EXACTLY, expect_string(assign_variable_callback(attach_node)),
+ "attachId", ONE_EXACTLY, expect_uint(assign_variable_callback(attach_id))
+ )(node)) {
+ Logger::error("Failed to load attachment for actor ", get_name());
+ return false;
+ }
+
+ attachments.push_back({ actor_name, attach_node, attach_id });
+ return true;
+ },
+
+ "idle", ZERO_OR_ONE, expect_string(std::bind(&Actor::_set_animation, this, "idle", std::placeholders::_1, 0)),
+ "move", ZERO_OR_ONE, expect_string(std::bind(&Actor::_set_animation, this, "move", std::placeholders::_1, 0)),
+ "attack", ZERO_OR_ONE, expect_string(std::bind(&Actor::_set_animation, this, "attack", std::placeholders::_1, 0)),
+ "animation", ZERO_OR_MORE, [this](ast::NodeCPtr node) -> bool {
+ std::string_view name {}, file {};
+ fixed_point_t scroll_time = 0;
+
+ if (!expect_dictionary_keys<StringMapCaseInsensitive>(
+ "name", ONE_EXACTLY, expect_string(assign_variable_callback(name)),
+ "file", ONE_EXACTLY, expect_string(assign_variable_callback(file)),
+ "defaultAnimationTime", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(scroll_time))
+ )(node)) {
+ Logger::error("Failed to load animation for actor ", get_name());
+ return false;
+ }
+
+ return _set_animation(name, file, scroll_time);
+ }
);
+
return ret;
}
diff --git a/src/openvic-simulation/interface/GFXObject.hpp b/src/openvic-simulation/interface/GFXObject.hpp
index 840e4a9..db15096 100644
--- a/src/openvic-simulation/interface/GFXObject.hpp
+++ b/src/openvic-simulation/interface/GFXObject.hpp
@@ -24,48 +24,44 @@ namespace OpenVic::GFX {
friend std::unique_ptr<Actor> std::make_unique<Actor>();
public:
- class Attachment : public Named<> {
- friend class LoadBase;
+ class Attachment {
+ friend class Actor;
- private:
- std::string PROPERTY(node);
- int32_t PROPERTY(attach_id);
+ public:
+ using attach_id_t = uint32_t;
- protected:
- Attachment();
+ private:
+ std::string PROPERTY(actor_name);
+ std::string PROPERTY(attach_node);
+ attach_id_t PROPERTY(attach_id);
- bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
+ Attachment(std::string_view new_actor_name, std::string_view new_attach_node, attach_id_t new_attach_id);
public:
Attachment(Attachment&&) = default;
- virtual ~Attachment() = default;
};
- class Animation : public Named<> {
- friend class LoadBase;
+ class Animation {
+ friend class Actor;
std::string PROPERTY(file);
- fixed_point_t PROPERTY(default_time);
+ fixed_point_t PROPERTY(scroll_time);
- protected:
- Animation();
-
- bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
+ Animation(std::string_view new_file, fixed_point_t new_scroll_time);
public:
Animation(Animation&&) = default;
- virtual ~Animation() = default;
};
private:
- std::string PROPERTY(model_file);
- std::string PROPERTY(idle_animation_file);
- std::string PROPERTY(move_animation_file);
- std::string PROPERTY(attack_animation_file);
fixed_point_t PROPERTY(scale);
+ std::string PROPERTY(model_file);
+ std::optional<Animation> PROPERTY(idle_animation);
+ std::optional<Animation> PROPERTY(move_animation);
+ std::optional<Animation> PROPERTY(attack_animation);
+ std::vector<Attachment> PROPERTY(attachments);
- NamedRegistry<Attachment> IDENTIFIER_REGISTRY(attachment);
- NamedRegistry<Animation> IDENTIFIER_REGISTRY(animation);
+ bool _set_animation(std::string_view name, std::string_view file, fixed_point_t scroll_time);
protected:
Actor();
diff --git a/src/openvic-simulation/interface/UI.cpp b/src/openvic-simulation/interface/UI.cpp
index 479948d..ea871de 100644
--- a/src/openvic-simulation/interface/UI.cpp
+++ b/src/openvic-simulation/interface/UI.cpp
@@ -55,6 +55,12 @@ NodeCallback auto UIManager::_load_fonts(std::string_view font_key) {
);
}
+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(
diff --git a/src/openvic-simulation/interface/UI.hpp b/src/openvic-simulation/interface/UI.hpp
index ada540a..9aec96c 100644
--- a/src/openvic-simulation/interface/UI.hpp
+++ b/src/openvic-simulation/interface/UI.hpp
@@ -7,10 +7,11 @@ namespace OpenVic {
class UIManager {
NamedInstanceRegistry<GFX::Sprite> IDENTIFIER_REGISTRY(sprite);
- NamedInstanceRegistry<GUI::Scene, UIManager const&> IDENTIFIER_REGISTRY(scene);
IdentifierRegistry<GFX::Font> IDENTIFIER_REGISTRY(font);
NamedInstanceRegistry<GFX::Object> IDENTIFIER_REGISTRY(object);
+ NamedInstanceRegistry<GUI::Scene, UIManager const&> IDENTIFIER_REGISTRY(scene);
+
bool _load_font(ast::NodeCPtr node);
NodeTools::NodeCallback auto _load_fonts(std::string_view font_key);
@@ -20,6 +21,8 @@ namespace OpenVic {
uint32_t height
);
+ void lock_gfx_registries();
+
bool load_gfx_file(ast::NodeCPtr root);
bool load_gui_file(std::string_view scene_name, ast::NodeCPtr root);
};
diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 9466e9f..18ed3d8 100644
--- a/src/openvic-simulation/pop/Culture.cpp
+++ b/src/openvic-simulation/pop/Culture.cpp
@@ -22,6 +22,8 @@ Culture::Culture(
first_names { std::move(new_first_names) }, last_names { std::move(new_last_names) }, radicalism { new_radicalism },
primary_country { new_primary_country } {}
+CultureManager::CultureManager() : default_graphical_culture_type { nullptr } {}
+
bool CultureManager::add_graphical_culture_type(std::string_view identifier) {
if (identifier.empty()) {
Logger::error("Invalid culture group identifier - empty!");
@@ -78,17 +80,26 @@ bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) {
graphical_culture_types,
expect_identifier(std::bind_front(&CultureManager::add_graphical_culture_type, this))
)(root);
+
lock_graphical_culture_types();
+
+ if (graphical_culture_types_empty()) {
+ Logger::error("Cannot set default graphical culture type - none loaded!");
+ return false;
+ }
+
+ /* Last defined graphical culture type is used as default. */
+ default_graphical_culture_type = &get_graphical_culture_types().back();
+
return ret;
}
bool CultureManager::_load_culture_group(
- CountryManager const& country_manager, size_t& total_expected_cultures,
- GraphicalCultureType const* default_unit_graphical_culture_type, std::string_view culture_group_key,
+ CountryManager const& country_manager, size_t& total_expected_cultures, std::string_view culture_group_key,
ast::NodeCPtr culture_group_node
) {
std::string_view leader {};
- GraphicalCultureType const* unit_graphical_culture_type = default_unit_graphical_culture_type;
+ GraphicalCultureType const* unit_graphical_culture_type = default_graphical_culture_type;
bool is_overseas = true;
Country const* union_country = nullptr;
@@ -152,21 +163,12 @@ bool CultureManager::load_culture_file(CountryManager const& country_manager, as
return false;
}
- static constexpr std::string_view default_unit_graphical_culture_type_identifier = "Generic";
- GraphicalCultureType const* const default_unit_graphical_culture_type =
- get_graphical_culture_type_by_identifier(default_unit_graphical_culture_type_identifier);
- if (default_unit_graphical_culture_type == nullptr) {
- Logger::error("Failed to find default unit graphical culture type: ", default_unit_graphical_culture_type_identifier);
- }
-
size_t total_expected_cultures = 0;
bool ret = expect_dictionary_reserve_length(culture_groups,
- [this, &country_manager, default_unit_graphical_culture_type, &total_expected_cultures](
+ [this, &country_manager, &total_expected_cultures](
std::string_view key, ast::NodeCPtr value
) -> bool {
- return _load_culture_group(
- country_manager, total_expected_cultures, default_unit_graphical_culture_type, key, value
- );
+ return _load_culture_group(country_manager, total_expected_cultures, key, value);
}
)(root);
lock_culture_groups();
diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp
index 8807123..72ea3ee 100644
--- a/src/openvic-simulation/pop/Culture.hpp
+++ b/src/openvic-simulation/pop/Culture.hpp
@@ -61,10 +61,11 @@ namespace OpenVic {
IdentifierRegistry<CultureGroup> IDENTIFIER_REGISTRY(culture_group);
IdentifierRegistry<Culture> IDENTIFIER_REGISTRY(culture);
+ GraphicalCultureType const* PROPERTY(default_graphical_culture_type);
+
bool _load_culture_group(
CountryManager const& country_manager, size_t& total_expected_cultures,
- GraphicalCultureType const* default_unit_graphical_culture_type, std::string_view culture_group_key,
- ast::NodeCPtr culture_group_node
+ std::string_view culture_group_key, ast::NodeCPtr culture_group_node
);
bool _load_culture(
CountryManager const& country_manager, CultureGroup const& culture_group, std::string_view culture_key,
@@ -72,6 +73,8 @@ namespace OpenVic {
);
public:
+ CultureManager();
+
bool add_graphical_culture_type(std::string_view identifier);
bool add_culture_group(
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index c1fef9d..533273a 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -269,6 +269,23 @@ namespace OpenVic {
} \
return nullptr; \
} \
+ template<std::derived_from<external_value_type> T> \
+ requires requires(external_value_type const& value) { \
+ { value.get_type() } -> std::same_as<std::string_view>; \
+ { T::get_type_static() } -> std::same_as<std::string_view>; \
+ } \
+ constexpr T CONST* get_cast_item_by_identifier(std::string_view identifier) CONST { \
+ external_value_type CONST* item = get_item_by_identifier(identifier); \
+ if (item != nullptr) { \
+ if (item->get_type() == T::get_type_static()) { \
+ return reinterpret_cast<T CONST*>(item); \
+ } \
+ Logger::error( \
+ "Invalid type for item \"", identifier, "\": ", item->get_type(), " (expected ", T::get_type_static(), ")" \
+ ); \
+ } \
+ return nullptr; \
+ } \
constexpr external_value_type CONST* get_item_by_index(std::size_t index) CONST { \
if (index < items.size()) { \
return std::addressof(ValueInfo::get_external_value(ItemInfo::get_value(items[index]))); \
@@ -565,6 +582,10 @@ private:
constexpr decltype(registry)::external_value_type const_kw* get_##singular##_by_identifier(std::string_view identifier) const_kw { \
return registry.get_item_by_identifier(identifier); \
} \
+ template<std::derived_from<decltype(registry)::external_value_type> T> \
+ constexpr T const_kw* get_cast_##singular##_by_identifier(std::string_view identifier) const_kw { \
+ return registry.get_cast_item_by_identifier<T>(identifier); \
+ } \
constexpr decltype(registry)::external_value_type const_kw* get_##singular##_by_index(std::size_t index) const_kw { \
return index >= index_offset ? registry.get_item_by_index(index - index_offset) : nullptr; \
} \