summaryrefslogtreecommitdiffhomepage
path: root/loader/atlas-loader.inl
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-02-07 23:38:31 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-02-08 08:43:49 +0100
commita6514d1a95d0f84f0935866215463ef6aed23e19 (patch)
tree639075646b1ea42a3cd4a76ae59af7dda0c4b14a /loader/atlas-loader.inl
parent4575194adb4615deeca174044a872093c3664ad4 (diff)
loader: work toward removing duplicate atlas code
Diffstat (limited to 'loader/atlas-loader.inl')
-rw-r--r--loader/atlas-loader.inl120
1 files changed, 120 insertions, 0 deletions
diff --git a/loader/atlas-loader.inl b/loader/atlas-loader.inl
new file mode 100644
index 00000000..a2e3e2a7
--- /dev/null
+++ b/loader/atlas-loader.inl
@@ -0,0 +1,120 @@
+#pragma once
+#include "compat/assert.hpp"
+#include "compat/exception.hpp"
+#include "atlas-loader.hpp"
+#include "atlas-loader-storage.hpp"
+#include "loader/loader.hpp"
+
+namespace floormat::loader_detail {
+
+template<typename ATLAS, typename TRAITS>
+atlas_loader<ATLAS, TRAITS>::atlas_loader(TRAITS&& traits): // NOLINT(*-rvalue-reference-param-not-moved)
+ t{Utility::move(traits)}
+{}
+
+template<typename ATLAS, typename TRAITS>
+atlas_loader<ATLAS, TRAITS>::atlas_loader() requires std::is_default_constructible_v<TRAITS>: atlas_loader{TRAITS{}} {}
+
+template<typename TRAITS>
+atlas_loader(TRAITS&& traits) noexcept -> atlas_loader<TRAITS, typename TRAITS::Atlas>;
+
+template<typename ATLAS, typename TRAITS>
+auto atlas_loader<ATLAS, TRAITS>::ensure_atlas_list() -> ArrayView<const Cell>
+{
+ if (!s.cell_array.empty()) [[likely]]
+ return { s.cell_array.data(), s.cell_array.size() };
+ t.ensure_atlases_loaded(s);
+ fm_assert(!s.cell_array.empty());
+ return { s.cell_array.data(), s.cell_array.size() };
+}
+
+template<typename ATLAS, typename TRAITS>
+const std::shared_ptr<ATLAS>& atlas_loader<ATLAS, TRAITS>::get_atlas(StringView name, loader_policy p)
+{
+ ensure_atlas_list();
+ auto* const invalid_atlas = const_cast<Cell*>(&t.make_invalid_atlas(s));
+ fm_debug_assert(invalid_atlas);
+ fm_debug_assert(t.atlas_of(*invalid_atlas));
+
+ switch (p)
+ {
+ using enum loader_policy;
+ case error:
+ case ignore:
+ case warn:
+ break;
+ default:
+ fm_abort("invalid loader_policy (%d)", (int)p);
+ }
+
+ if (name == loader.INVALID) [[unlikely]]
+ switch (p)
+ {
+ using enum loader_policy;
+ case error:
+ goto error;
+ case ignore:
+ case warn:
+ return invalid_atlas->atlas;
+ }
+
+ fm_soft_assert(loader.check_atlas_name(name));
+
+ if (auto it = s.name_map.find(name); it != s.name_map.end()) [[likely]]
+ {
+ if (it->second == invalid_atlas)
+ {
+ switch (p)
+ {
+ using enum loader_policy;
+ case error:
+ goto error;
+ case warn:
+ case ignore:
+ return invalid_atlas->atlas;
+ }
+ }
+ else if (!it->second->atlas)
+ return it->second->atlas = t.make_atlas(name, *it->second);
+ else
+ return it->second->atlas;
+ }
+ else
+ switch (p)
+ {
+ using enum loader_policy;
+ case error:
+ goto error;
+ case warn:
+ goto missing_warn;
+ case ignore:
+ return invalid_atlas->atlas;
+ }
+
+ std::unreachable();
+ fm_assert(false);
+
+error:
+ fm_throw("no such atlas '{}'"_cf, name);
+
+missing_warn:
+ s.missing_atlas_names.push_back(String { AllocatedInit, name });
+ s.name_map[ s.missing_atlas_names.back() ] = invalid_atlas;
+
+ if (name != loader.INVALID)
+ {
+ DBG_nospace << t.loader_name() << " '" << name << "' doesn't exist";
+ }
+
+ return invalid_atlas->atlas;
+}
+
+template<typename ATLAS, typename TRAITS>
+auto atlas_loader<ATLAS, TRAITS>::get_invalid_atlas() -> const Cell&
+{
+ const auto& cell = t.make_invalid_atlas(s);
+ fm_assert(t.atlas_of(cell));
+ return cell;
+}
+
+} // namespace floormat::loader_detail