summaryrefslogtreecommitdiffhomepage
path: root/loader
diff options
context:
space:
mode:
Diffstat (limited to 'loader')
-rw-r--r--loader/anim-cell.hpp (renamed from loader/anim-info.hpp)2
-rw-r--r--loader/anim.cpp11
-rw-r--r--loader/atlas-loader-fwd.hpp9
-rw-r--r--loader/atlas-loader-storage.hpp23
-rw-r--r--loader/atlas-loader.hpp32
-rw-r--r--loader/atlas-loader.inl120
-rw-r--r--loader/atlas.cpp5
-rw-r--r--loader/error-tex.cpp2
-rw-r--r--loader/ground-atlas.cpp146
-rw-r--r--loader/ground-atlas.hpp7
-rw-r--r--loader/ground-cell.hpp (renamed from loader/ground-info.hpp)8
-rw-r--r--loader/ground-traits.cpp87
-rw-r--r--loader/ground-traits.hpp25
-rw-r--r--loader/impl.cpp38
-rw-r--r--loader/impl.hpp34
-rw-r--r--loader/json.cpp4
-rw-r--r--loader/loader.cpp32
-rw-r--r--loader/loader.hpp34
-rw-r--r--loader/texture.cpp6
-rw-r--r--loader/wall-atlas.cpp21
-rw-r--r--loader/wall-cell.hpp (renamed from loader/wall-info.hpp)2
21 files changed, 426 insertions, 222 deletions
diff --git a/loader/anim-info.hpp b/loader/anim-cell.hpp
index 97ba5954..a9c92a23 100644
--- a/loader/anim-info.hpp
+++ b/loader/anim-cell.hpp
@@ -6,7 +6,7 @@ namespace floormat {
class anim_atlas;
-struct anim_info
+struct anim_cell
{
String name;
std::shared_ptr<anim_atlas> atlas;
diff --git a/loader/anim.cpp b/loader/anim.cpp
index 25b5e292..6fca5a49 100644
--- a/loader/anim.cpp
+++ b/loader/anim.cpp
@@ -1,5 +1,5 @@
#include "impl.hpp"
-#include "loader/anim-info.hpp"
+#include "loader/anim-cell.hpp"
#include "compat/exception.hpp"
#include "src/anim-atlas.hpp"
#include <Corrade/Containers/Array.h>
@@ -58,9 +58,10 @@ ArrayView<const String> loader_impl::anim_atlas_list()
std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false)
{
if (name == INVALID) return make_invalid_anim_atlas().atlas; // todo! hack
+
fm_soft_assert(check_atlas_name(name));
fm_soft_assert(!dir || dir[dir.size()-1] == '/');
- char buf[FILENAME_MAX];
+ char buf[fm_FILENAME_MAX];
auto path = make_atlas_path(buf, dir, name);
if (auto it = anim_atlas_map.find(path); it != anim_atlas_map.end())
@@ -89,7 +90,7 @@ void loader_impl::get_anim_atlas_list()
fm_assert(!anim_atlases.empty());
}
-const anim_info& loader_impl::make_invalid_anim_atlas()
+const anim_cell& loader_impl::make_invalid_anim_atlas()
{
if (invalid_anim_atlas) [[likely]]
return *invalid_anim_atlas;
@@ -115,11 +116,11 @@ const anim_info& loader_impl::make_invalid_anim_atlas()
.nframes = 1,
};
auto atlas = std::make_shared<class anim_atlas>(INVALID, make_error_texture(size), std::move(def));
- auto info = anim_info {
+ auto info = anim_cell{
.name = INVALID,
.atlas = atlas,
};
- invalid_anim_atlas = Pointer<anim_info>{ InPlace, std::move(info) };
+ invalid_anim_atlas = Pointer<anim_cell>{ InPlace, std::move(info) };
return *invalid_anim_atlas;
}
diff --git a/loader/atlas-loader-fwd.hpp b/loader/atlas-loader-fwd.hpp
new file mode 100644
index 00000000..2fe1cd84
--- /dev/null
+++ b/loader/atlas-loader-fwd.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace floormat::loader_detail {
+
+template<typename ATLAS> struct atlas_loader_traits;
+template<typename ATLAS, typename TRAITS = atlas_loader_traits<ATLAS>> class atlas_loader;
+template<typename ATLAS, typename TRAITS = atlas_loader_traits<ATLAS>> struct atlas_storage;
+
+} // namespace floormat::loader_detail
diff --git a/loader/atlas-loader-storage.hpp b/loader/atlas-loader-storage.hpp
new file mode 100644
index 00000000..f428be0a
--- /dev/null
+++ b/loader/atlas-loader-storage.hpp
@@ -0,0 +1,23 @@
+#pragma once
+#include "compat/int-hash.hpp"
+#include "atlas-loader-fwd.hpp"
+#include <vector>
+#include <tsl/robin_map.h>
+
+namespace floormat::loader_detail {
+
+template<typename ATLAS, typename TRAITS>
+struct atlas_storage
+{
+ using Traits = TRAITS;
+ using Cell = typename TRAITS::Cell;
+
+ tsl::robin_map<StringView, Cell*, hash_string_view> name_map;
+ std::vector<Cell> cell_array;
+ std::vector<String> missing_atlas_names;
+ Pointer<Cell> invalid_atlas;
+
+ bool is_empty() const { return cell_array.empty(); }
+};
+
+} // namespace floormat::loader_detail
diff --git a/loader/atlas-loader.hpp b/loader/atlas-loader.hpp
new file mode 100644
index 00000000..9fa82e49
--- /dev/null
+++ b/loader/atlas-loader.hpp
@@ -0,0 +1,32 @@
+#pragma once
+#include "compat/defs.hpp"
+#include "atlas-loader-fwd.hpp"
+#include "policy.hpp"
+#include <memory>
+
+namespace floormat::loader_detail {
+
+template<typename ATLAS, typename TRAITS>
+class atlas_loader final
+{
+ [[fm_no_unique_address]] TRAITS t;
+ atlas_storage<ATLAS, TRAITS> s;
+
+public:
+ using Traits = TRAITS;
+ using Atlas = ATLAS;
+ using Cell = typename TRAITS::Cell;
+
+ ~atlas_loader() noexcept = default;
+ fm_DECLARE_DELETED_COPY_ASSIGNMENT(atlas_loader);
+ fm_DECLARE_DELETED_MOVE_ASSIGNMENT(atlas_loader);
+
+ atlas_loader(TRAITS&& traits);
+ atlas_loader() requires std::is_default_constructible_v<TRAITS>;
+
+ ArrayView<const Cell> ensure_atlas_list();
+ const std::shared_ptr<Atlas>& get_atlas(StringView name, loader_policy p);
+ const Cell& get_invalid_atlas();
+};
+
+} // namespace floormat::loader_detail
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
diff --git a/loader/atlas.cpp b/loader/atlas.cpp
index a4c38264..e856f639 100644
--- a/loader/atlas.cpp
+++ b/loader/atlas.cpp
@@ -1,6 +1,7 @@
#include "impl.hpp"
//#include "compat/assert.hpp"
#include "compat/exception.hpp"
+#include "loader/loader.hpp"
//#include "src/emplacer.hpp"
//#include "src/anim-atlas.hpp"
#include <cstring>
@@ -13,11 +14,11 @@
namespace floormat {
-StringView loader_::make_atlas_path(char(&buf)[FILENAME_MAX], StringView dir, StringView name)
+StringView loader_::make_atlas_path(char(&buf)[fm_FILENAME_MAX], StringView dir, StringView name)
{
fm_soft_assert(!dir || dir[dir.size()-1] == '/');
const auto dirsiz = dir.size(), namesiz = name.size();
- fm_soft_assert(dirsiz + namesiz + 1 < FILENAME_MAX);
+ fm_soft_assert(dirsiz + namesiz + 1 < fm_FILENAME_MAX);
std::memcpy(buf, dir.data(), dirsiz);
std::memcpy(&buf[dirsiz], name.data(), namesiz);
auto len = dirsiz + namesiz;
diff --git a/loader/error-tex.cpp b/loader/error-tex.cpp
index c3a0a58b..16df2b43 100644
--- a/loader/error-tex.cpp
+++ b/loader/error-tex.cpp
@@ -11,7 +11,7 @@ Trade::ImageData2D loader_impl::make_error_texture(Vector2ui size)
{
fm_assert(size.product() != 0);
constexpr auto magenta = Vector4ub{255, 0, 255, 255};
- auto array = Array<char>{NoInit, 4 * size.product()};
+ auto array = Array<char>{NoInit, 4uz * size.product()};
auto data = array.data(), end = data + array.size();
while (data != end)
{
diff --git a/loader/ground-atlas.cpp b/loader/ground-atlas.cpp
index ba4eaeb0..02186cec 100644
--- a/loader/ground-atlas.cpp
+++ b/loader/ground-atlas.cpp
@@ -1,30 +1,36 @@
#include "impl.hpp"
+#include "atlas-loader-storage.hpp"
+#include "atlas-loader.inl"
+#include "ground-traits.hpp"
+#include "ground-cell.hpp"
#include "src/tile-constants.hpp"
#include "src/ground-atlas.hpp"
#include "compat/exception.hpp"
#include "serialize/json-helper.hpp"
-#include "serialize/corrade-string.hpp"
#include "serialize/ground-atlas.hpp"
-#include "src/tile-defs.hpp"
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Utility/Path.h>
#include <Magnum/Trade/ImageData.h>
#include <Magnum/ImageView.h>
+namespace floormat::loader_detail {
+
+template class atlas_loader<ground_atlas>;
+
+} // namespace floormat::loader_detail
+
namespace floormat {
-using loader_detail::loader_impl;
+
+using loader_detail::atlas_loader_traits;
+using ALT = atlas_loader_traits<ground_atlas>;
std::shared_ptr<ground_atlas>
loader_::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false)
{
fm_assert(name != loader.INVALID);
-
- char buf[FILENAME_MAX];
- auto filename = make_atlas_path(buf, loader.GROUND_TILESET_PATH, name);
- auto tex = texture(""_s, filename);
-
+ auto tex = texture(loader.GROUND_TILESET_PATH, name);
auto info = ground_def{name, size, pass};
- auto atlas = std::make_shared<class ground_atlas>(info, filename, tex);
+ auto atlas = std::make_shared<class ground_atlas>(info, tex);
return atlas;
}
@@ -32,128 +38,22 @@ loader_::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexc
namespace floormat::loader_detail {
-// todo copypasta from wall-atlas.cpp
-std::shared_ptr<class ground_atlas> loader_impl::ground_atlas(StringView name, loader_policy policy) noexcept(false)
+atlas_loader<class ground_atlas>* loader_impl::make_ground_atlas_loader()
{
- (void)ground_atlas_list();
-
- switch (policy)
- {
- case loader_policy::error:
- fm_assert(name != INVALID);
- break;
- case loader_policy::ignore:
- case loader_policy::warn:
- break;
- default:
- fm_abort("invalid loader_policy");
- }
-
- fm_soft_assert(check_atlas_name(name));
- auto it = ground_atlas_map.find(name);
-
- if (it != ground_atlas_map.end()) [[likely]]
- {
- if (it->second == (ground_info*)-1) [[unlikely]]
- {
- switch (policy)
- {
- case loader_policy::error:
- goto error;
- case loader_policy::warn:
- case loader_policy::ignore:
- goto missing_ok;
- }
- fm_assert(false);
- std::unreachable();
- }
- else if (!it->second->atlas)
- return it->second->atlas = get_ground_atlas(name, it->second->size, it->second->pass);
- else
- return it->second->atlas;
- }
- else
- {
- switch (policy)
- {
- case loader_policy::error:
- goto error;
- case loader_policy::warn:
- goto missing_warn;
- case loader_policy::ignore:
- goto missing_ok;
- }
- fm_assert(false);
- std::unreachable();
- }
-
-missing_warn:
- {
- missing_ground_atlases.push_back(String { AllocatedInit, name });
- auto string_view = StringView{missing_ground_atlases.back()};
- ground_atlas_map[string_view] = (ground_info*)-1;
- }
-
- if (name != loader.INVALID)
- DBG_nospace << "ground_atlas '" << name << "' doesn't exist";
-
-missing_ok:
- return make_invalid_ground_atlas().atlas;
-
-error:
- fm_throw("no such ground atlas '{}'"_cf, name);
+ return new atlas_loader<class ground_atlas>;
}
-ArrayView<const ground_info> loader_impl::ground_atlas_list() noexcept(false)
-{
- if (ground_atlas_map.empty()) [[unlikely]]
- {
- get_ground_atlas_list();
- fm_assert(!ground_atlas_map.empty());
- }
- return ground_atlas_array;
-}
+auto loader_impl::ground_atlas_list() noexcept(false) -> ArrayView<const ground_cell> { return _ground_loader->ensure_atlas_list(); }
-void loader_impl::get_ground_atlas_list()
+const ground_cell& loader_impl::make_invalid_ground_atlas()
{
- fm_assert(ground_atlas_map.empty());
-
- auto defs = json_helper::from_json<std::vector<ground_def>>(Path::join(loader_::GROUND_TILESET_PATH, "ground.json"_s));
- std::vector<ground_info> infos;
- infos.reserve(defs.size());
-
- for (auto& x : defs)
- infos.push_back(ground_info{std::move(x.name), {}, x.size, x.pass});
-
- ground_atlas_array = infos;
- ground_atlas_array.shrink_to_fit();
- ground_atlas_map.clear();
- ground_atlas_map.reserve(ground_atlas_array.size()*2);
-
- for (auto& x : ground_atlas_array)
- {
- fm_soft_assert(x.name != loader.INVALID);
- fm_soft_assert(check_atlas_name(x.name));
- StringView name = x.name;
- ground_atlas_map[name] = &x;
- fm_debug_assert(name.data() == ground_atlas_map[name]->name.data());
- }
-
- fm_assert(!ground_atlas_map.empty());
+ return _ground_loader->get_invalid_atlas();
}
-const ground_info& loader_impl::make_invalid_ground_atlas()
+const std::shared_ptr<class ground_atlas>&
+loader_impl::ground_atlas(StringView filename, loader_policy policy) noexcept(false)
{
- if (invalid_ground_atlas) [[likely]]
- return *invalid_ground_atlas;
-
- auto atlas = std::make_shared<class ground_atlas>(
- ground_def{loader.INVALID, Vector2ub{1,1}, pass_mode::pass},
- ""_s, make_error_texture(Vector2ui(iTILE_SIZE2)));
- invalid_ground_atlas = Pointer<ground_info>{
- InPlaceInit, atlas->name(),
- atlas, atlas->num_tiles2(), atlas->pass_mode()};
- return *invalid_ground_atlas;
+ return _ground_loader->get_atlas(filename, policy);
}
} // namespace floormat::loader_detail
diff --git a/loader/ground-atlas.hpp b/loader/ground-atlas.hpp
new file mode 100644
index 00000000..b388f543
--- /dev/null
+++ b/loader/ground-atlas.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace floormat::loader_detail {
+
+
+
+} // namespace floormat::loader_detail
diff --git a/loader/ground-info.hpp b/loader/ground-cell.hpp
index 1a21e960..260301c2 100644
--- a/loader/ground-info.hpp
+++ b/loader/ground-cell.hpp
@@ -1,17 +1,15 @@
#pragma once
-#include "src/pass-mode.hpp"
+#include "src/ground-def.hpp"
#include <memory>
-#include <Corrade/Containers/String.h>
-#include <Magnum/Math/Vector2.h>
namespace floormat {
class ground_atlas;
-struct ground_info
+struct ground_cell
{
- String name;
std::shared_ptr<ground_atlas> atlas;
+ String name;
Vector2ub size;
pass_mode pass = pass_mode::pass;
};
diff --git a/loader/ground-traits.cpp b/loader/ground-traits.cpp
new file mode 100644
index 00000000..cf0dee4e
--- /dev/null
+++ b/loader/ground-traits.cpp
@@ -0,0 +1,87 @@
+#include "ground-traits.hpp"
+#include "compat/assert.hpp"
+#include "compat/exception.hpp"
+#include "atlas-loader.hpp"
+#include "atlas-loader-storage.hpp"
+#include "ground-cell.hpp"
+#include "loader.hpp"
+#include "src/tile-defs.hpp"
+#include "serialize/json-helper.hpp"
+#include "serialize/ground-atlas.hpp"
+#include <Corrade/Containers/StringView.h>
+#include <Corrade/Containers/Pointer.h>
+#include <Corrade/Utility/Path.h>
+#include <Magnum/ImageView.h>
+#include <Magnum/Trade/ImageData.h>
+
+namespace floormat::loader_detail {
+
+StringView atlas_loader_traits<ground_atlas>::loader_name() { return "ground_atlas"_s; }
+StringView atlas_loader_traits<ground_atlas>::name_of(const Cell& x) { return x.name; }
+auto atlas_loader_traits<ground_atlas>::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; }
+StringView atlas_loader_traits<ground_atlas>::name_of(const Atlas& x) { return x.name(); }
+
+void atlas_loader_traits<ground_atlas>::ensure_atlases_loaded(Storage& st)
+{
+ if (!st.is_empty()) [[likely]]
+ return;
+
+ fm_assert(st.cell_array.empty());
+ fm_assert(st.name_map.empty());
+
+ auto defs = json_helper::from_json<std::vector<ground_def>>(Path::join(loader_::GROUND_TILESET_PATH, "ground.json"_s));
+ std::vector<ground_cell> infos;
+ infos.reserve(defs.size());
+
+ for (auto& x : defs)
+ infos.push_back(ground_cell{{}, std::move(x.name), x.size, x.pass});
+
+ st.cell_array = Utility::move(infos);
+ fm_assert(!st.cell_array.empty());
+ fm_assert(st.name_map.empty());
+
+ constexpr bool add_invalid = true;
+
+ if constexpr(add_invalid)
+ for (auto& x : st.cell_array)
+ fm_soft_assert(x.name != loader.INVALID);
+
+ if constexpr(true) // NOLINT(*-simplify-boolean-expr)
+ st.cell_array.push_back(make_invalid_atlas(st)); // add invalid atlas
+
+ st.name_map.reserve(st.cell_array.size());
+
+ for (auto& x : st.cell_array)
+ {
+ if constexpr(!add_invalid)
+ fm_soft_assert(x.name != loader.INVALID);
+ fm_soft_assert(loader.check_atlas_name(x.name));
+ st.name_map[x.name] = &x;
+ }
+
+ fm_assert(!st.cell_array.empty());
+ fm_assert(!st.name_map.empty());
+ fm_debug_assert(!st.is_empty());
+}
+
+auto atlas_loader_traits<ground_atlas>::make_invalid_atlas(Storage& s) -> const Cell&
+{
+ if (!s.invalid_atlas) [[unlikely]]
+ {
+ auto atlas = std::make_shared<Atlas>(
+ ground_def{loader.INVALID, Vector2ub{1,1}, pass_mode::pass},
+ loader.make_error_texture(Vector2ui(tile_size_xy)));
+ s.invalid_atlas = Pointer<ground_cell>{ InPlaceInit, atlas, atlas->name(), atlas->num_tiles2(), atlas->pass_mode() };
+ }
+ return *s.invalid_atlas;
+}
+
+auto atlas_loader_traits<ground_atlas>::make_atlas(StringView name, const Cell& cell) -> std::shared_ptr<Atlas>
+{
+ auto def = ground_def{name, cell.size, cell.pass};
+ auto tex = loader.texture(loader.GROUND_TILESET_PATH, name);
+ auto atlas = std::make_shared<Atlas>(def, tex);
+ return atlas;
+}
+
+} // namespace floormat::loader_detail
diff --git a/loader/ground-traits.hpp b/loader/ground-traits.hpp
new file mode 100644
index 00000000..56923cd0
--- /dev/null
+++ b/loader/ground-traits.hpp
@@ -0,0 +1,25 @@
+#pragma once
+#include "atlas-loader-fwd.hpp"
+#include <memory>
+
+namespace floormat { struct ground_cell; class ground_atlas; }
+
+namespace floormat::loader_detail {
+
+template<> struct atlas_loader_traits<ground_atlas>
+{
+ using Atlas = ground_atlas;
+ using Cell = ground_cell; // convertible to atlas and holding the atlas
+ using Self = atlas_loader_traits<ground_atlas>;
+ using Storage = atlas_storage<ground_atlas, Self>;
+
+ static StringView loader_name();
+ static const std::shared_ptr<Atlas>& atlas_of(const Cell& x);
+ static StringView name_of(const Cell& x);
+ static StringView name_of(const Atlas& x);
+ static void ensure_atlases_loaded(Storage& st);
+ static const Cell& make_invalid_atlas(Storage& st);
+ static std::shared_ptr<Atlas> make_atlas(StringView name, const Cell& c);
+};
+
+} // namespace floormat::loader_detail
diff --git a/loader/impl.cpp b/loader/impl.cpp
index 7da85f3f..543f0794 100644
--- a/loader/impl.cpp
+++ b/loader/impl.cpp
@@ -1,9 +1,13 @@
#include "impl.hpp"
#include "compat/assert.hpp"
-#include "loader/scenery.hpp"
-#include "loader/wall-info.hpp"
-#include "loader/anim-info.hpp"
-#include "src/ground-atlas.hpp"
+#include "scenery.hpp"
+#include "wall-cell.hpp"
+#include "anim-cell.hpp"
+#include "ground-cell.hpp"
+#include "ground-traits.hpp"
+#include "atlas-loader.hpp"
+#include "atlas-loader-storage.hpp"
+
#include <Corrade/Containers/Pair.h>
#include <Magnum/Trade/ImageData.h>
@@ -11,6 +15,10 @@
#pragma GCC diagnostic ignored "-Walloca"
#endif
+namespace floormat {
+
+} // namespace floormat
+
namespace floormat::loader_detail {
StringView loader_impl::shader(StringView filename) noexcept
@@ -23,9 +31,9 @@ StringView loader_impl::shader(StringView filename) noexcept
return ret;
}
-loader_impl::loader_impl()
+loader_impl::loader_impl() :
+ _ground_loader{ make_ground_atlas_loader() }
{
- missing_ground_atlases.reserve(32);
missing_wall_atlases.reserve(32);
system_init();
set_application_working_directory();
@@ -46,4 +54,22 @@ void loader_impl::ensure_plugins()
fm_assert(tga_importer);
}
+void loader_impl::destroy()
+{
+ wall_atlas_map.clear();
+ wall_atlas_array.clear();
+ invalid_wall_atlas = nullptr;
+ missing_wall_atlases.clear();
+ _ground_loader = {InPlace};
+ anim_atlas_map.clear();
+ anim_atlases.clear();
+ invalid_anim_atlas = nullptr;
+ sceneries_map.clear();
+ sceneries_array.clear();
+
+ vobj_atlas_map.clear();
+ vobjs.clear();
+}
+
+
} // namespace floormat::loader_detail
diff --git a/loader/impl.hpp b/loader/impl.hpp
index 5c8a542a..7bddda29 100644
--- a/loader/impl.hpp
+++ b/loader/impl.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "compat/safe-ptr.hpp"
#include "loader/loader.hpp"
+#include "atlas-loader-fwd.hpp"
#include <tsl/robin_map.h>
#include <memory>
#include <vector>
@@ -12,6 +14,9 @@
namespace floormat::loader_detail {
+
+
+
struct loader_impl final : loader_
{
explicit loader_impl();
@@ -36,37 +41,34 @@ struct loader_impl final : loader_
Optional<Utility::Resource> shader_res;
StringView shader(StringView filename) noexcept override;
- Trade::ImageData2D make_error_texture(Vector2ui size);
+ Trade::ImageData2D make_error_texture(Vector2ui size) override;
Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) override;
// >-----> walls >----->
- tsl::robin_map<StringView, wall_info*> wall_atlas_map;
- std::vector<wall_info> wall_atlas_array;
+ tsl::robin_map<StringView, wall_cell*> wall_atlas_map;
+ std::vector<wall_cell> wall_atlas_array;
std::vector<String> missing_wall_atlases;
- Pointer<wall_info> invalid_wall_atlas;
+ Pointer<wall_cell> invalid_wall_atlas;
std::shared_ptr<class wall_atlas> wall_atlas(StringView name, loader_policy policy) override;
- ArrayView<const wall_info> wall_atlas_list() override;
+ ArrayView<const wall_cell> wall_atlas_list() override;
void get_wall_atlas_list();
- const wall_info& make_invalid_wall_atlas() override;
+ const wall_cell& make_invalid_wall_atlas() override;
// >-----> ground >----->
- tsl::robin_map<StringView, ground_info*> ground_atlas_map;
- std::vector<ground_info> ground_atlas_array;
- std::vector<String> missing_ground_atlases;
- Pointer<ground_info> invalid_ground_atlas;
- std::shared_ptr<class ground_atlas> ground_atlas(StringView filename, loader_policy policy) noexcept(false) override;
- ArrayView<const ground_info> ground_atlas_list() noexcept(false) override;
- void get_ground_atlas_list();
- const ground_info& make_invalid_ground_atlas() override;
+ static atlas_loader<class ground_atlas>* make_ground_atlas_loader();
+ safe_ptr<atlas_loader<class ground_atlas>> _ground_loader{make_ground_atlas_loader()};
+ const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy) noexcept(false) override;
+ ArrayView<const ground_cell> ground_atlas_list() noexcept(false) override;
+ const ground_cell& make_invalid_ground_atlas() override;
// >-----> anim >----->
tsl::robin_map<StringView, std::shared_ptr<class anim_atlas>> anim_atlas_map;
std::vector<String> anim_atlases;
- Pointer<anim_info> invalid_anim_atlas;
+ Pointer<anim_cell> invalid_anim_atlas;
ArrayView<const String> anim_atlas_list() override;
std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false) override;
void get_anim_atlas_list();
- const anim_info& make_invalid_anim_atlas() override;
+ const anim_cell& make_invalid_anim_atlas() override;
// >-----> scenery >----->
std::vector<serialized_scenery> sceneries_array;
diff --git a/loader/json.cpp b/loader/json.cpp
index 5c7eecb5..d374571c 100644
--- a/loader/json.cpp
+++ b/loader/json.cpp
@@ -6,7 +6,7 @@
#include "serialize/anim.hpp"
#include "serialize/scenery.hpp"
#include "loader/scenery.hpp"
-#include "loader/anim-info.hpp"
+#include "loader/anim-cell.hpp"
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Utility/Path.h>
@@ -26,7 +26,7 @@ void loader_impl::get_scenery_list()
sceneries_array.clear();
sceneries_array = json_helper::from_json<std::vector<serialized_scenery>>(Path::join(SCENERY_PATH, "scenery.json"));
- if constexpr(false)
+ if constexpr(true) // todo!
{
auto proto = scenery_proto{};
proto.atlas = make_invalid_anim_atlas().atlas;
diff --git a/loader/loader.cpp b/loader/loader.cpp
index 531d731a..8b711206 100644
--- a/loader/loader.cpp
+++ b/loader/loader.cpp
@@ -1,35 +1,9 @@
#include "impl.hpp"
-#include "ground-info.hpp"
-#include "wall-info.hpp"
-#include "anim-info.hpp"
+#include "ground-cell.hpp"
+#include "loader/wall-cell.hpp"
+#include "anim-cell.hpp"
#include "scenery.hpp"
-namespace floormat::loader_detail {
-
-void loader_impl::destroy()
-{
- wall_atlas_map.clear();
- wall_atlas_array.clear();
- invalid_wall_atlas = nullptr;
- missing_wall_atlases.clear();
-
- ground_atlas_map.clear();
- ground_atlas_array.clear();
- invalid_ground_atlas = nullptr;
- missing_ground_atlases.clear();
-
- anim_atlas_map.clear();
- anim_atlases.clear();
- invalid_anim_atlas = nullptr;
- sceneries_map.clear();
- sceneries_array.clear();
-
- vobj_atlas_map.clear();
- vobjs.clear();
-}
-
-} // namespace floormat::loader_detail
-
namespace floormat {
using loader_detail::loader_impl;
diff --git a/loader/loader.hpp b/loader/loader.hpp
index 96ab57ed..faa0269a 100644
--- a/loader/loader.hpp
+++ b/loader/loader.hpp
@@ -2,27 +2,26 @@
#include "compat/defs.hpp"
#include "src/pass-mode.hpp"
#include "loader/policy.hpp"
-#include <stdio.h> // NOLINT(*-deprecated-headers)
#include <memory>
#include <Corrade/Containers/String.h>
-namespace Magnum { using Vector2ub = Math::Vector2<unsigned char>; }
-namespace floormat { struct serialized_scenery; }
-namespace Magnum::Trade {
-template<uint32_t> class ImageData;
-using ImageData2D = ImageData<2>;
-} // namespace Magnum::Trade
+//namespace Magnum { using Vector2ub = Math::Vector2<unsigned char>; }
+namespace Magnum::Trade { template<uint32_t> class ImageData; using ImageData2D = ImageData<2>; }
namespace floormat {
+struct serialized_scenery;
+namespace loader_detail {}
+namespace Serialize {}
+
struct anim_def;
class anim_atlas;
-struct anim_info;
+struct anim_cell;
struct scenery_proto;
struct vobj_info;
class ground_atlas;
-struct ground_info;
-struct wall_info;
+struct ground_cell;
+struct wall_cell;
class wall_atlas;
struct scenery_proto;
@@ -35,27 +34,28 @@ struct vobj_info final
struct loader_
{
virtual StringView shader(StringView filename) noexcept = 0;
+ virtual Trade::ImageData2D make_error_texture(Vector2ui size) = 0;
virtual Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) = 0;
- virtual std::shared_ptr<class ground_atlas> ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0;
+ virtual const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0;
virtual ArrayView<const String> anim_atlas_list() = 0;
virtual std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir = ANIM_PATH, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0;
virtual std::shared_ptr<class wall_atlas> wall_atlas(StringView name, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0;
- virtual ArrayView<const wall_info> wall_atlas_list() = 0;
+ virtual ArrayView<const wall_cell> wall_atlas_list() = 0;
virtual void destroy() = 0;
static loader_& default_loader() noexcept;
- virtual ArrayView<const ground_info> ground_atlas_list() noexcept(false) = 0; // todo maybe try returning
+ virtual ArrayView<const ground_cell> ground_atlas_list() noexcept(false) = 0; // todo maybe try returning
virtual ArrayView<const serialized_scenery> sceneries() = 0;
virtual const scenery_proto& scenery(StringView name) noexcept(false) = 0;
virtual StringView startup_directory() noexcept = 0;
static StringView strip_prefix(StringView name);
virtual const vobj_info& vobj(StringView name) = 0;
virtual ArrayView<const struct vobj_info> vobj_list() = 0;
- static StringView make_atlas_path(char(&buf)[FILENAME_MAX], StringView dir, StringView name);
+ static StringView make_atlas_path(char(&buf)[fm_FILENAME_MAX], StringView dir, StringView name);
[[nodiscard]] static bool check_atlas_name(StringView name) noexcept;
- virtual const wall_info& make_invalid_wall_atlas() = 0;
- virtual const ground_info& make_invalid_ground_atlas() = 0;
- virtual const anim_info& make_invalid_anim_atlas() = 0;
+ virtual const wall_cell& make_invalid_wall_atlas() = 0;
+ virtual const ground_cell& make_invalid_ground_atlas() = 0;
+ virtual const anim_cell& make_invalid_anim_atlas() = 0;
/** \deprecated{internal use only}*/ [[nodiscard]]
std::shared_ptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false);
diff --git a/loader/texture.cpp b/loader/texture.cpp
index 8ac9e793..e93b21af 100644
--- a/loader/texture.cpp
+++ b/loader/texture.cpp
@@ -4,7 +4,7 @@
#include "compat/defs.hpp"
#include "compat/strerror.hpp"
#include <cstring>
-#include <cstdio>
+//#include <cstdio>
#include <Corrade/Utility/Path.h>
#include <Magnum/Trade/ImageData.h>
@@ -19,11 +19,11 @@ Trade::ImageData2D loader_impl::texture(StringView prefix, StringView filename_)
const auto N = prefix.size();
if (N > 0) [[likely]]
fm_assert(prefix[N-1] == '/');
- fm_soft_assert(filename_.size() + prefix.size() + max_extension_length + 1 < FILENAME_MAX);
+ fm_soft_assert(filename_.size() + prefix.size() + max_extension_length + 1 < fm_FILENAME_MAX);
fm_soft_assert(check_atlas_name(filename_));
fm_soft_assert(tga_importer);
- char buf[FILENAME_MAX];
+ char buf[fm_FILENAME_MAX];
const auto path_no_ext = make_atlas_path(buf, prefix, filename_);
const auto len = path_no_ext.size();
diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp
index ee33e052..80eb6e0f 100644
--- a/loader/wall-atlas.cpp
+++ b/loader/wall-atlas.cpp
@@ -1,12 +1,11 @@
#include "loader/impl.hpp"
#include "src/tile-constants.hpp"
-#include "wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include "compat/assert.hpp"
#include "compat/exception.hpp"
#include "src/wall-atlas.hpp"
#include "serialize/json-helper.hpp"
#include "serialize/corrade-string.hpp"
-#include "src/tile-defs.hpp"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/StringIterable.h>
@@ -19,14 +18,14 @@ namespace floormat {
using nlohmann::json;
using loader_detail::loader_impl;
-[[maybe_unused]] static void from_json(const json& j, wall_info& val)
+[[maybe_unused]] static void from_json(const json& j, wall_cell& val)
{
val = {};
val.name = j["name"];
fm_soft_assert(loader.check_atlas_name(val.name));
}
-[[maybe_unused]] static void to_json(json& j, const wall_info& val)
+[[maybe_unused]] static void to_json(json& j, const wall_cell& val)
{
j["name"] = val.name;
}
@@ -34,7 +33,7 @@ using loader_detail::loader_impl;
std::shared_ptr<wall_atlas> loader_::get_wall_atlas(StringView name) noexcept(false)
{
fm_assert(name != "<invalid>"_s);
- char buf[FILENAME_MAX];
+ char buf[fm_FILENAME_MAX];
auto filename = make_atlas_path(buf, loader.WALL_TILESET_PATH, name);
auto def = wall_atlas_def::deserialize(""_s.join({filename, ".json"_s}));
auto tex = texture(""_s, filename);
@@ -49,7 +48,7 @@ std::shared_ptr<wall_atlas> loader_::get_wall_atlas(StringView name) noexcept(fa
namespace floormat::loader_detail {
-const wall_info& loader_impl::make_invalid_wall_atlas()
+const wall_cell& loader_impl::make_invalid_wall_atlas()
{
if (invalid_wall_atlas) [[likely]]
return *invalid_wall_atlas;
@@ -65,7 +64,7 @@ const wall_info& loader_impl::make_invalid_wall_atlas()
{{ {.val = 0}, {}, }},
{1u},
}, name, make_error_texture(frame_size));
- invalid_wall_atlas = Pointer<wall_info>{InPlaceInit, wall_info{ .name = name, .atlas = std::move(a) } };
+ invalid_wall_atlas = Pointer<wall_cell>{InPlaceInit, wall_cell{ .name = name, .atlas = std::move(a) } };
return *invalid_wall_atlas;
}
@@ -90,7 +89,7 @@ std::shared_ptr<class wall_atlas> loader_impl::wall_atlas(StringView name, loade
if (it != wall_atlas_map.end()) [[likely]]
{
- if (it->second == (wall_info*)-1) [[unlikely]]
+ if (it->second == (wall_cell*)-1) [[unlikely]]
{
switch (policy)
{
@@ -125,7 +124,7 @@ missing_warn:
{
missing_wall_atlases.push_back(String { AllocatedInit, name });
auto string_view = StringView{missing_wall_atlases.back()};
- wall_atlas_map[string_view] = (wall_info*)-1;
+ wall_atlas_map[string_view] = (wall_cell*)-1;
}
if (name != "<invalid>")
@@ -142,7 +141,7 @@ void loader_impl::get_wall_atlas_list()
{
fm_assert(wall_atlas_map.empty());
- wall_atlas_array = json_helper::from_json<std::vector<wall_info>>(Path::join(WALL_TILESET_PATH, "walls.json"_s));
+ wall_atlas_array = json_helper::from_json<std::vector<wall_cell>>(Path::join(WALL_TILESET_PATH, "walls.json"_s));
wall_atlas_array.shrink_to_fit();
wall_atlas_map.clear();
wall_atlas_map.reserve(wall_atlas_array.size()*2);
@@ -159,7 +158,7 @@ void loader_impl::get_wall_atlas_list()
fm_assert(!wall_atlas_map.empty());
}
-ArrayView<const wall_info> loader_impl::wall_atlas_list()
+ArrayView<const wall_cell> loader_impl::wall_atlas_list()
{
if (wall_atlas_map.empty()) [[unlikely]]
{
diff --git a/loader/wall-info.hpp b/loader/wall-cell.hpp
index 9b586a10..3dfa698b 100644
--- a/loader/wall-info.hpp
+++ b/loader/wall-cell.hpp
@@ -6,7 +6,7 @@ namespace floormat {
class wall_atlas;
-struct wall_info
+struct wall_cell
{
String name;
std::shared_ptr<wall_atlas> atlas;