aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/dataloader
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2023-11-13 13:42:37 +0100
committer GitHub <noreply@github.com>2023-11-13 13:42:37 +0100
commitf572664cbe1aa5ec2cb6907de3083f058c20af7e (patch)
treec9a61c5dd15fb1eae1555f47119423dbba315e76 /src/openvic-simulation/dataloader
parentba7bfc52803781c970d6e8afc84c7d3d3e843726 (diff)
parentce84886cb931975f622134d6c8d32a69c675d975 (diff)
Merge pull request #71 from OpenVicProject/gui-loading
GUI and GFX file loading
Diffstat (limited to 'src/openvic-simulation/dataloader')
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp141
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp19
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp22
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp13
4 files changed, 136 insertions, 59 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index aefb6fc..011b524 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -36,8 +36,13 @@ using namespace ovdl;
using StringUtils::append_string_views;
-#define FILESYSTEM_CASE_INSENSITIVE (defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)))
-#define FILESYSTEM_NEEDS_FORWARD_SLASHES (!defined(_WIN32))
+#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
+#define FILESYSTEM_CASE_INSENSITIVE
+#endif
+
+#if !defined(_WIN32)
+#define FILESYSTEM_NEEDS_FORWARD_SLASHES
+#endif
static constexpr bool path_equals_case_insensitive(std::string_view lhs, std::string_view rhs) {
constexpr auto ichar_equals = [](unsigned char l, unsigned char r) {
@@ -48,7 +53,7 @@ static constexpr bool path_equals_case_insensitive(std::string_view lhs, std::st
// Windows and Mac by default act like case insensitive filesystems
static constexpr bool path_equals(std::string_view lhs, std::string_view rhs) {
-#if FILESYSTEM_CASE_INSENSITIVE
+#if defined(FILESYSTEM_CASE_INSENSITIVE)
return path_equals_case_insensitive(lhs, rhs);
#else
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
@@ -369,7 +374,7 @@ bool Dataloader::set_roots(path_vector_t const& new_roots) {
}
fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const {
-#if FILESYSTEM_NEEDS_FORWARD_SLASHES
+#if defined(FILESYSTEM_NEEDS_FORWARD_SLASHES)
/* Back-slashes need to be converted into forward-slashes */
const std::string forward_slash_path { StringUtils::make_forward_slash_path(StringUtils::remove_leading_slashes(path)) };
path = forward_slash_path;
@@ -377,7 +382,7 @@ fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const
const fs::path filepath { path };
-#if FILESYSTEM_CASE_INSENSITIVE
+#if defined(FILESYSTEM_CASE_INSENSITIVE)
/* Case-insensitive filesystem */
for (fs::path const& root : roots) {
const fs::path composed = root / filepath;
@@ -411,34 +416,62 @@ fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const
return {};
}
-template<typename _DirIterator, std::predicate<fs::path const&, fs::path const&> _Equiv>
-Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(std::string_view path, fs::path const& extension) const {
-#if FILESYSTEM_NEEDS_FORWARD_SLASHES
+fs::path Dataloader::lookup_image_file_or_dds(std::string_view path) const {
+ fs::path ret = lookup_file(path, false);
+ if (ret.empty()) {
+ // TODO - change search order so root order takes priority over extension replacement order
+ ret = lookup_file(append_string_views(StringUtils::remove_extension(path), ".dds"), false);
+ if (!ret.empty()) {
+ return ret;
+ }
+ Logger::error("Image lookup for ", path, " failed!");
+ }
+ return ret;
+}
+
+template<typename _DirIterator, typename _UniqueKey>
+requires requires (_UniqueKey const& unique_key, std::string_view path) {
+ { unique_key(path) } -> std::convertible_to<std::string_view>;
+}
+Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
+ std::string_view path, fs::path const& extension, _UniqueKey const& unique_key
+) const {
+#if defined(FILESYSTEM_NEEDS_FORWARD_SLASHES)
/* Back-slashes need to be converted into forward-slashes */
const std::string forward_slash_path { StringUtils::make_forward_slash_path(StringUtils::remove_leading_slashes(path)) };
path = forward_slash_path;
#endif
- const fs::path filepath { path };
- static constexpr _Equiv Equiv {};
+ const fs::path dirpath { path };
path_vector_t ret;
- size_t start_of_current_root_entries;
+ struct file_entry_t {
+ fs::path file;
+ fs::path const* root;
+ };
+ string_map_t<file_entry_t> found_files;
for (fs::path const& root : roots) {
- start_of_current_root_entries = ret.size();
- const fs::path composed = root / filepath;
+ const size_t root_len = root.string().size();
+ const fs::path composed = root / dirpath;
std::error_code ec;
for (fs::directory_entry const& entry : _DirIterator { composed, ec }) {
if (entry.is_regular_file()) {
- const fs::path file = entry;
- if ((extension.empty() || file.extension() == extension) && !Equiv(file, {})) {
- size_t index = 0;
- for (; index < ret.size() && !Equiv(file, ret[index]); ++index) {}
- if (index >= ret.size()) {
- ret.push_back(file);
- } else if (start_of_current_root_entries <= index) {
- Logger::warning(
- "Files in the same directory with conflicting names: ", ret[index], " (accepted) and ", file,
- " (rejected)"
- );
+ fs::path file = entry;
+ if ((extension.empty() || file.extension() == extension)) {
+ const std::string full_path = file.string();
+ std::string_view relative_path = full_path;
+ relative_path.remove_prefix(root_len);
+ relative_path = StringUtils::remove_leading_slashes(relative_path);
+ const std::string_view key = unique_key(relative_path);
+ if (!key.empty()) {
+ const typename decltype(found_files)::const_iterator it = found_files.find(key);
+ if (it == found_files.end()) {
+ found_files.emplace(key, file_entry_t { file, &root });
+ ret.emplace_back(std::move(file));
+ } else if (it->second.root == &root) {
+ Logger::warning(
+ "Files in the same directory with conflicting keys: ", it->first, " - ", it->second.file,
+ " (accepted) and ", key, " - ", file, " (rejected)"
+ );
+ }
}
}
}
@@ -447,38 +480,28 @@ Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(std::string_view path
return ret;
}
-struct EquivFilename {
- bool operator()(fs::path const& lhs, fs::path const& rhs) const {
- return lhs.filename() == rhs.filename();
- }
-};
-
Dataloader::path_vector_t Dataloader::lookup_files_in_dir(std::string_view path, fs::path const& extension) const {
- return _lookup_files_in_dir<fs::directory_iterator, EquivFilename>(path, extension);
+ return _lookup_files_in_dir<fs::directory_iterator>(path, extension, std::identity {});
}
Dataloader::path_vector_t Dataloader::lookup_files_in_dir_recursive(std::string_view path, fs::path const& extension) const {
- return _lookup_files_in_dir<fs::recursive_directory_iterator, EquivFilename>(path, extension);
+ return _lookup_files_in_dir<fs::recursive_directory_iterator>(path, extension, std::identity {});
}
-struct EquivBasicIdentifierPrefix {
- bool operator()(fs::path const& lhs, fs::path const& rhs) const {
- const std::string lhs_str = lhs.stem().string();
- const std::string rhs_str = rhs.stem().string();
- return extract_basic_identifier_prefix(lhs_str) == extract_basic_identifier_prefix(rhs_str);
- }
+static std::string_view _extract_basic_identifier_prefix_from_path(std::string_view path) {
+ return extract_basic_identifier_prefix(StringUtils::get_filename(path));
};
Dataloader::path_vector_t Dataloader::lookup_basic_indentifier_prefixed_files_in_dir(
std::string_view path, fs::path const& extension
) const {
- return _lookup_files_in_dir<fs::directory_iterator, EquivBasicIdentifierPrefix>(path, extension);
+ return _lookup_files_in_dir<fs::directory_iterator>(path, extension, _extract_basic_identifier_prefix_from_path);
}
Dataloader::path_vector_t Dataloader::lookup_basic_indentifier_prefixed_files_in_dir_recursive(
std::string_view path, fs::path const& extension
) const {
- return _lookup_files_in_dir<fs::recursive_directory_iterator, EquivBasicIdentifierPrefix>(path, extension);
+ return _lookup_files_in_dir<fs::recursive_directory_iterator>(path, extension, _extract_basic_identifier_prefix_from_path);
}
bool Dataloader::apply_to_files(path_vector_t const& files, callback_t<fs::path const&> callback) const {
@@ -555,6 +578,36 @@ csv::Windows1252Parser Dataloader::parse_csv(fs::path const& path) {
return _run_ovdl_parser<csv::Windows1252Parser, &_csv_parse>(path);
}
+bool Dataloader::_load_interface_files(UIManager& ui_manager) const {
+ static constexpr std::string_view interface_directory = "interface/";
+
+ bool ret = apply_to_files(
+ lookup_files_in_dir(interface_directory, ".gfx"),
+ [&ui_manager](fs::path const& file) -> bool {
+ return ui_manager.load_gfx_file(parse_defines(file).get_file_node());
+ }
+ );
+ ui_manager.lock_sprites();
+ ui_manager.lock_fonts();
+
+ // Hard-coded example until the mechanism for requesting them from GDScript is fleshed out
+ static const std::vector<std::string_view> gui_files {
+ "province_interface.gui", "topbar.gui"
+ };
+ for (std::string_view const& gui_file : gui_files) {
+ if (!ui_manager.load_gui_file(
+ gui_file,
+ parse_defines(lookup_file(append_string_views(interface_directory, gui_file))).get_file_node()
+ )) {
+ Logger::error("Failed to load interface gui file: ", gui_file);
+ ret = false;
+ }
+ }
+ ui_manager.lock_scenes();
+
+ return ret;
+}
+
bool Dataloader::_load_pop_types(
PopManager& pop_manager, UnitManager const& unit_manager, GoodManager const& good_manager
) const {
@@ -798,6 +851,10 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
bool ret = true;
+ if (!_load_interface_files(game_manager.get_ui_manager())) {
+ Logger::error("Failed to load interface files!");
+ ret = false;
+ }
if (!game_manager.get_modifier_manager().setup_modifier_effects()) {
Logger::error("Failed to set up modifier effects!");
ret = false;
@@ -889,7 +946,9 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
Logger::error("Failed to load leader traits!");
ret = false;
}
- if (!game_manager.get_military_manager().get_wargoal_manager().load_wargoal_file(parse_defines(lookup_file(cb_types_file)).get_file_node())) {
+ if (!game_manager.get_military_manager().get_wargoal_manager().load_wargoal_file(
+ parse_defines(lookup_file(cb_types_file)).get_file_node()
+ )) {
Logger::error("Failed to load wargoals!");
ret = false;
}
diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp
index 2123469..5039582 100644
--- a/src/openvic-simulation/dataloader/Dataloader.hpp
+++ b/src/openvic-simulation/dataloader/Dataloader.hpp
@@ -12,6 +12,7 @@ namespace OpenVic {
namespace fs = std::filesystem;
struct GameManager;
+ class UIManager;
struct PopManager;
struct UnitManager;
struct GoodManager;
@@ -23,16 +24,22 @@ namespace OpenVic {
private:
path_vector_t roots;
+ bool _load_interface_files(UIManager& ui_manager) const;
bool _load_pop_types(PopManager& pop_manager, UnitManager const& unit_manager, GoodManager const& good_manager) const;
bool _load_units(UnitManager& unit_manager, GoodManager const& good_manager) const;
bool _load_map_dir(GameManager& game_manager) const;
bool _load_history(GameManager& game_manager, bool unused_history_file_warnings) const;
- /* _DirIterator is fs::directory_iterator or fs::recursive_directory_iterator.
- * _Equiv is an equivalence relation with respect to which every found file shall be unique.
- * If a file is equivalent to the empty path then it is not included. */
- template<typename _DirIterator, std::predicate<fs::path const&, fs::path const&> _Equiv>
- path_vector_t _lookup_files_in_dir(std::string_view path, fs::path const& extension) const;
+ /* _DirIterator is fs::directory_iterator or fs::recursive_directory_iterator. _UniqueKey is the type of a callable
+ * which converts a string_view filepath with root removed into a string_view unique key. Any path whose key is empty
+ * or matches an earlier found path's key is discarded, ensuring each looked up path's key is non-empty and unique. */
+ template<typename _DirIterator, typename _UniqueKey>
+ requires requires (_UniqueKey const& unique_key, std::string_view path) {
+ { unique_key(path) } -> std::convertible_to<std::string_view>;
+ }
+ path_vector_t _lookup_files_in_dir(
+ std::string_view path, fs::path const& extension, _UniqueKey const& unique_key
+ ) const;
public:
static ovdl::v2script::Parser parse_defines(fs::path const& path);
@@ -70,6 +77,8 @@ namespace OpenVic {
* DAT-24
*/
fs::path lookup_file(std::string_view path, bool print_error = true) const;
+ /* Checks alternate file endings, e.g. if "*.tga" doesn't exist then try "*.dds" */
+ fs::path lookup_image_file_or_dds(std::string_view path) const;
path_vector_t lookup_files_in_dir(std::string_view path, fs::path const& extension) const;
path_vector_t lookup_files_in_dir_recursive(std::string_view path, fs::path const& extension) const;
path_vector_t lookup_basic_indentifier_prefixed_files_in_dir(std::string_view path, fs::path const& extension) const;
diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp
index 27d0f95..c412f33 100644
--- a/src/openvic-simulation/dataloader/NodeTools.cpp
+++ b/src/openvic-simulation/dataloader/NodeTools.cpp
@@ -76,10 +76,10 @@ node_callback_t NodeTools::expect_int_bool(callback_t<bool> callback) {
return expect_identifier(expect_mapped_string(bool_map, callback));
}
-node_callback_t NodeTools::expect_int64(callback_t<int64_t> callback) {
- return expect_identifier([callback](std::string_view identifier) -> bool {
+node_callback_t NodeTools::expect_int64(callback_t<int64_t> callback, int base) {
+ return expect_identifier([callback, base](std::string_view identifier) -> bool {
bool successful = false;
- const int64_t val = StringUtils::string_to_int64(identifier, &successful, 10);
+ const int64_t val = StringUtils::string_to_int64(identifier, &successful, base);
if (successful) {
return callback(val);
}
@@ -88,10 +88,10 @@ node_callback_t NodeTools::expect_int64(callback_t<int64_t> callback) {
});
}
-node_callback_t NodeTools::expect_uint64(callback_t<uint64_t> callback) {
- return expect_identifier([callback](std::string_view identifier) -> bool {
+node_callback_t NodeTools::expect_uint64(callback_t<uint64_t> callback, int base) {
+ return expect_identifier([callback, base](std::string_view identifier) -> bool {
bool successful = false;
- const uint64_t val = StringUtils::string_to_uint64(identifier, &successful, 10);
+ const uint64_t val = StringUtils::string_to_uint64(identifier, &successful, base);
if (successful) {
return callback(val);
}
@@ -141,6 +141,10 @@ node_callback_t NodeTools::expect_colour(callback_t<colour_t> callback) {
};
}
+node_callback_t NodeTools::expect_colour_hex(callback_t<colour_t> callback) {
+ return expect_uint(callback, 16);
+}
+
callback_t<std::string_view> NodeTools::expect_date_str(callback_t<Date> callback) {
return [callback](std::string_view identifier) -> bool {
bool successful = false;
@@ -188,8 +192,12 @@ NodeCallback auto _expect_vec2(Callback<vec2_t<T>> auto callback) {
};
}
+static node_callback_t _expect_int(callback_t<ivec2_t::type> callback) {
+ return expect_int(callback);
+}
+
node_callback_t NodeTools::expect_ivec2(callback_t<ivec2_t> callback) {
- return _expect_vec2<int32_t, expect_int>(callback);
+ return _expect_vec2<ivec2_t::type, _expect_int>(callback);
}
node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) {
diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp
index a23fb4f..1ca6cf0 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -73,11 +73,11 @@ namespace OpenVic {
node_callback_t expect_bool(callback_t<bool> callback);
node_callback_t expect_int_bool(callback_t<bool> callback);
- node_callback_t expect_int64(callback_t<int64_t> callback);
- node_callback_t expect_uint64(callback_t<uint64_t> callback);
+ node_callback_t expect_int64(callback_t<int64_t> callback, int base = 10);
+ node_callback_t expect_uint64(callback_t<uint64_t> callback, int base = 10);
template<std::signed_integral T>
- NodeCallback auto expect_int(callback_t<T> callback) {
+ NodeCallback auto expect_int(callback_t<T> callback, int base = 10) {
return expect_int64([callback](int64_t val) -> bool {
if (static_cast<int64_t>(std::numeric_limits<T>::lowest()) <= val &&
val <= static_cast<int64_t>(std::numeric_limits<T>::max())) {
@@ -88,11 +88,11 @@ namespace OpenVic {
static_cast<int64_t>(std::numeric_limits<T>::max()), "])"
);
return false;
- });
+ }, base);
}
template<std::integral T>
- NodeCallback auto expect_uint(callback_t<T> callback) {
+ NodeCallback auto expect_uint(callback_t<T> callback, int base = 10) {
return expect_uint64([callback](uint64_t val) -> bool {
if (val <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
return callback(val);
@@ -101,12 +101,13 @@ namespace OpenVic {
"Invalid uint: ", val, " (valid range: [0, ", static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"
);
return false;
- });
+ }, base);
}
callback_t<std::string_view> expect_fixed_point_str(callback_t<fixed_point_t> callback);
node_callback_t expect_fixed_point(callback_t<fixed_point_t> callback);
node_callback_t expect_colour(callback_t<colour_t> callback);
+ node_callback_t expect_colour_hex(callback_t<colour_t> callback);
callback_t<std::string_view> expect_date_str(callback_t<Date> callback);
node_callback_t expect_date(callback_t<Date> callback);