summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/loader.cpp4
-rw-r--r--compat/defs.hpp2
-rw-r--r--compat/int-hash.cpp13
-rw-r--r--compat/int-hash.hpp4
-rw-r--r--compat/is-complete.hpp21
-rw-r--r--compat/map.hpp2
-rw-r--r--compat/safe-ptr.hpp35
-rw-r--r--editor/ground-editor.cpp5
-rw-r--r--editor/ground-editor.hpp4
-rw-r--r--editor/imgui-editors.cpp12
-rw-r--r--editor/wall-editor.cpp2
-rw-r--r--editor/wall-editor.hpp4
-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
-rw-r--r--serialize/ground-atlas.cpp6
-rw-r--r--serialize/ground-atlas.hpp2
-rw-r--r--src/ground-atlas.cpp27
-rw-r--r--src/ground-atlas.hpp33
-rw-r--r--src/ground-def.hpp15
-rw-r--r--src/world.cpp2
-rw-r--r--test/dijkstra.cpp2
-rw-r--r--test/json.cpp2
-rw-r--r--test/loader.cpp3
-rw-r--r--test/path-search.cpp2
-rw-r--r--test/raycast.cpp2
-rw-r--r--test/wall-atlas2.cpp2
45 files changed, 542 insertions, 312 deletions
diff --git a/bench/loader.cpp b/bench/loader.cpp
index c96ef31c..bb878758 100644
--- a/bench/loader.cpp
+++ b/bench/loader.cpp
@@ -1,6 +1,6 @@
#include "loader/loader.hpp"
-#include "loader/ground-info.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/ground-cell.hpp"
+#include "loader/wall-cell.hpp"
#include "serialize/json-helper.hpp"
#include "serialize/anim.hpp"
#include <Corrade/Containers/ArrayView.h>
diff --git a/compat/defs.hpp b/compat/defs.hpp
index edefbb5e..6f3c9ab2 100644
--- a/compat/defs.hpp
+++ b/compat/defs.hpp
@@ -89,3 +89,5 @@
#ifndef fm_ASAN
#define fm_ASAN 0
#endif
+
+#define fm_FILENAME_MAX 260
diff --git a/compat/int-hash.cpp b/compat/int-hash.cpp
index 3c85a436..35422486 100644
--- a/compat/int-hash.cpp
+++ b/compat/int-hash.cpp
@@ -1,5 +1,6 @@
#include "compat/defs.hpp"
#include "int-hash.hpp"
+#include <Corrade/Containers/StringView.h>
#include <bit>
namespace floormat {
@@ -78,15 +79,9 @@ fm_UNROLL_8
return hash;
}
-size_t hash_int(uint32_t x) noexcept
-{
- return fnvhash_uint_32(x);
-}
-
-size_t hash_int(uint64_t x) noexcept
-{
- return fnvhash_uint_64(x);
-}
+size_t hash_int(uint32_t x) noexcept { return fnvhash_uint_32(x); }
+size_t hash_int(uint64_t x) noexcept { return fnvhash_uint_64(x); }
+size_t hash_string_view::operator()(StringView s) const noexcept { return Hash::fnvhash_buf(s.data(), s.size()); }
} // namespace floormat
diff --git a/compat/int-hash.hpp b/compat/int-hash.hpp
index a5d6b147..27f2651f 100644
--- a/compat/int-hash.hpp
+++ b/compat/int-hash.hpp
@@ -1,5 +1,7 @@
#pragma once
+// todo rename to hash-fnv.hpp
+
namespace floormat::Hash {
template<size_t N = sizeof nullptr * 8> struct fnvhash_params;
@@ -20,4 +22,6 @@ uint32_t hash_32(const void* buf, size_t size) noexcept;
size_t hash_int(uint32_t x) noexcept;
size_t hash_int(uint64_t x) noexcept;
+struct hash_string_view { size_t operator()(StringView str) const noexcept; };
+
} // namespace floormat
diff --git a/compat/is-complete.hpp b/compat/is-complete.hpp
new file mode 100644
index 00000000..d6bba88b
--- /dev/null
+++ b/compat/is-complete.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+namespace floormat::detail_type_traits {
+
+namespace { template<class T> class IsComplete_ {
+ // from <Corrade/Containers/Pointer.h>
+ template<class U> static char get(U*, decltype(sizeof(U))* = nullptr);
+ static short get(...);
+ public:
+ enum: bool { value = sizeof(get(static_cast<T*>(nullptr))) == sizeof(char) };
+}; } // namespace
+
+} // namespace floormat::detail_type_traits
+
+namespace floormat {
+
+template<typename T>
+constexpr inline bool is_complete =
+ bool(::floormat::detail_type_traits::IsComplete_<T>::value);
+
+} // namespace floormat
diff --git a/compat/map.hpp b/compat/map.hpp
index 3c1610d4..860b4d77 100644
--- a/compat/map.hpp
+++ b/compat/map.hpp
@@ -32,7 +32,7 @@ constexpr auto map(const F& fun, const std::array<T, N>& array)
using return_type = std::decay_t<decltype( fun(array[0]) )>;
static_assert(!std::is_same_v<return_type, void>);
static_assert(std::is_same_v<T, std::decay_t<T>>);
- static_assert(sizeof(return_type) > 0);
+ static_assert(sizeof(return_type));
using ::floormat::detail::map::map0;
return map0(fun, array, std::make_index_sequence<N>{});
}
diff --git a/compat/safe-ptr.hpp b/compat/safe-ptr.hpp
index 0882f3be..95cd3bae 100644
--- a/compat/safe-ptr.hpp
+++ b/compat/safe-ptr.hpp
@@ -13,41 +13,26 @@ class safe_ptr final
T* ptr;
public:
- template<typename... Ts>
- requires requires (Ts&&... xs) {
- new T{Utility::forward<Ts>(xs)...};
- }
- safe_ptr(InPlaceInitT, Ts&&... args) noexcept:
- ptr{new T{Utility::forward<Ts>(args)...}}
- {}
-
- explicit safe_ptr(T*&& ptr) noexcept: ptr{ptr}
- {
- fm_assert(ptr != nullptr);
- ptr = nullptr;
- }
-
~safe_ptr() noexcept
{
- if (ptr) [[likely]]
- delete ptr;
+ delete ptr;
ptr = (T*)0xbadcafedeadbabe;
}
- explicit safe_ptr(safe_ptr&& other) noexcept: ptr{other.ptr}
- {
- other.ptr = nullptr;
- }
+ safe_ptr(std::nullptr_t) = delete;
+ safe_ptr(T* ptr) noexcept: ptr{ptr} { fm_assert(ptr != nullptr); }
+ safe_ptr(safe_ptr&& other) noexcept: ptr{other.ptr} { other.ptr = nullptr; }
+
+ safe_ptr() noexcept: safe_ptr{InPlaceInit} {}
- explicit safe_ptr() noexcept:
- ptr{new T{}}
+ template<typename... Ts> safe_ptr(InPlaceInitT, Ts&&... args) noexcept:
+ ptr(new T{ Utility::forward<Ts>(args)... })
{}
safe_ptr& operator=(safe_ptr&& other) noexcept
{
fm_assert(this != &other);
- if (ptr) [[likely]]
- delete ptr;
+ delete ptr;
ptr = other.ptr;
other.ptr = nullptr;
return *this;
@@ -57,6 +42,8 @@ public:
//explicit operator bool() const noexcept { return ptr != nullptr; }
+ T* get() noexcept { return ptr; }
+ const T* get() const noexcept { return ptr; }
const T& operator*() const noexcept { return *ptr; }
T& operator*() noexcept { return *ptr; }
const T* operator->() const noexcept { return ptr; }
diff --git a/editor/ground-editor.cpp b/editor/ground-editor.cpp
index 82a76405..653ad122 100644
--- a/editor/ground-editor.cpp
+++ b/editor/ground-editor.cpp
@@ -30,7 +30,10 @@ void ground_editor::load_atlases()
fm_assert(_atlases.empty());
for (const auto& g : loader.ground_atlas_list())
{
- (void)loader.ground_atlas(g.name);
+ if (g.name != loader.INVALID) [[likely]]
+ (void)loader.ground_atlas(g.name);
+ else
+ loader.make_invalid_ground_atlas();
fm_assert(g.atlas);
_atlases[g.name] = &g;
}
diff --git a/editor/ground-editor.hpp b/editor/ground-editor.hpp
index a0d99813..a7de3333 100644
--- a/editor/ground-editor.hpp
+++ b/editor/ground-editor.hpp
@@ -10,14 +10,14 @@
namespace floormat {
class world;
-struct ground_info;
+struct ground_cell;
class ground_editor final
{
enum selection_mode : unsigned char { sel_none, sel_tile, sel_perm, };
struct tuple;
- std::map<StringView, const ground_info*> _atlases;
+ std::map<StringView, const ground_cell*> _atlases;
tile_image_proto _selected_tile;
safe_ptr<tuple> _permutation;
selection_mode _selection_mode = sel_none;
diff --git a/editor/imgui-editors.cpp b/editor/imgui-editors.cpp
index 570094bc..efb37426 100644
--- a/editor/imgui-editors.cpp
+++ b/editor/imgui-editors.cpp
@@ -39,23 +39,23 @@ StringView scenery_type_to_string(const scenery_& sc)
}
}
-StringView scenery_path(const wall_info* wa) { return wa->atlas->name(); }
+StringView scenery_path(const wall_cell* wa) { return wa->atlas->name(); }
StringView scenery_name(StringView, const scenery_& sc) { return sc.name; }
StringView scenery_name(StringView, const vobj_& vobj) { return vobj.descr; }
-StringView scenery_name(StringView, const wall_info* w) { return w->name; }
+StringView scenery_name(StringView, const wall_cell* w) { return w->name; }
std::shared_ptr<anim_atlas> get_atlas(const scenery_& sc) { return sc.proto.atlas; }
std::shared_ptr<anim_atlas> get_atlas(const vobj_& vobj) { return vobj.factory->atlas(); }
-std::shared_ptr<wall_atlas> get_atlas(const wall_info* w) { return loader.wall_atlas(w->name); }
+std::shared_ptr<wall_atlas> get_atlas(const wall_cell* w) { return loader.wall_atlas(w->name); }
Vector2ui get_size(const auto&, anim_atlas& atlas) { return atlas.frame(atlas.first_rotation(), 0).size; }
Vector2ui get_size(const auto&, wall_atlas& atlas) { auto sz = atlas.image_size(); return { std::max(1u, std::min(sz.y()*3/2, sz.x())), sz.y() }; }
bool is_selected(const scenery_editor& ed, const scenery_& sc) { return ed.is_item_selected(sc); }
bool is_selected(const vobj_editor& vo, const vobj_& sc) { return vo.is_item_selected(sc); }
-bool is_selected(const wall_editor& wa, const wall_info* sc) { return wa.is_atlas_selected(sc->atlas); }
+bool is_selected(const wall_editor& wa, const wall_cell* sc) { return wa.is_atlas_selected(sc->atlas); }
void select_tile(scenery_editor& ed, const scenery_& sc) { ed.select_tile(sc); }
void select_tile(vobj_editor& vo, const vobj_& sc) { vo.select_tile(sc); }
-void select_tile(wall_editor& wa, const wall_info* sc) { wa.select_atlas(sc->atlas); }
+void select_tile(wall_editor& wa, const wall_cell* sc) { wa.select_atlas(sc->atlas); }
auto get_texcoords(const auto&, anim_atlas& atlas) { return atlas.texcoords_for_frame(atlas.first_rotation(), 0, !atlas.group(atlas.first_rotation()).mirror_from.isEmpty()); }
-auto get_texcoords(const wall_info* w, wall_atlas& atlas) { auto sz = get_size(w, atlas); return Quads::texcoords_at({}, sz, atlas.image_size()); }
+auto get_texcoords(const wall_cell* w, wall_atlas& atlas) { auto sz = get_size(w, atlas); return Quads::texcoords_at({}, sz, atlas.image_size()); }
void draw_editor_tile_pane_atlas(ground_editor& ed, StringView name, const std::shared_ptr<ground_atlas>& atlas, Vector2 dpi)
{
diff --git a/editor/wall-editor.cpp b/editor/wall-editor.cpp
index f3e0b13f..681397a5 100644
--- a/editor/wall-editor.cpp
+++ b/editor/wall-editor.cpp
@@ -3,7 +3,7 @@
#include "src/wall-atlas.hpp"
#include "src/world.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include <Corrade/Containers/ArrayView.h>
namespace floormat {
diff --git a/editor/wall-editor.hpp b/editor/wall-editor.hpp
index 159135a0..b58dd72a 100644
--- a/editor/wall-editor.hpp
+++ b/editor/wall-editor.hpp
@@ -2,7 +2,7 @@
#include "editor-enums.hpp"
#include "src/rotation.hpp"
#include "src/global-coords.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include <memory>
#include <map>
@@ -13,7 +13,7 @@ class wall_atlas;
class wall_editor
{
- std::map<StringView, const wall_info*> _atlases;
+ std::map<StringView, const wall_cell*> _atlases;
std::shared_ptr<wall_atlas> _selected_atlas;
enum rotation _r = rotation::N;
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;
diff --git a/serialize/ground-atlas.cpp b/serialize/ground-atlas.cpp
index 71c53510..d5c04332 100644
--- a/serialize/ground-atlas.cpp
+++ b/serialize/ground-atlas.cpp
@@ -38,10 +38,8 @@ void adl_serializer<std::shared_ptr<ground_atlas>>::to_json(json& j, const std::
void adl_serializer<std::shared_ptr<ground_atlas>>::from_json(const json& j, std::shared_ptr<ground_atlas>& val)
{
- char buf[FILENAME_MAX];
- ground_def info = j;
- auto path = loader.make_atlas_path(buf, loader.GROUND_TILESET_PATH, info.name);
- val = std::make_shared<ground_atlas>(std::move(info), path, loader.texture(""_s, path));
+ ground_def def = j;
+ val = std::make_shared<ground_atlas>(std::move(def), loader.texture(loader.GROUND_TILESET_PATH, def.name));
}
} // namespace nlohmann
diff --git a/serialize/ground-atlas.hpp b/serialize/ground-atlas.hpp
index fc8acec5..a423ebbe 100644
--- a/serialize/ground-atlas.hpp
+++ b/serialize/ground-atlas.hpp
@@ -4,7 +4,7 @@
namespace floormat {
-struct ground_info;
+struct ground_cell;
} // namespace floormat
diff --git a/src/ground-atlas.cpp b/src/ground-atlas.cpp
index f918f940..ea513d44 100644
--- a/src/ground-atlas.cpp
+++ b/src/ground-atlas.cpp
@@ -3,6 +3,7 @@
#include "compat/assert.hpp"
#include "tile-image.hpp"
#include "compat/exception.hpp"
+#include "loader/loader.hpp"
#include <limits>
#include <Magnum/Math/Color.h>
#include <Magnum/ImageView.h>
@@ -12,15 +13,16 @@ namespace floormat {
using namespace floormat::Quads;
-ground_atlas::ground_atlas(ground_def info, String path, const ImageView2D& image) :
- texcoords_{make_texcoords_array(Vector2ui(image.size()), info.size)},
- path_{std::move(path)}, name_{std::move(info.name)}, size_{image.size()}, dims_{info.size}, passability{info.pass}
+ground_atlas::ground_atlas(ground_def info, const ImageView2D& image) :
+ _def{std::move(info)}, _path{make_path(_def.name)},
+ _texcoords{make_texcoords_array(Vector2ui(image.size()), _def.size)},
+ _pixel_size{image.size()}
{
constexpr auto variant_max = std::numeric_limits<variant_t>::max();
fm_soft_assert(num_tiles() <= variant_max);
- fm_soft_assert(dims_[0] > 0 && dims_[1] > 0);
- fm_soft_assert(size_ % Vector2ui{info.size} == Vector2ui());
- tex_.setLabel(path_)
+ fm_soft_assert(_def.size.x() > 0 && _def.size.y() > 0);
+ fm_soft_assert(_pixel_size % Vector2ui{_def.size} == Vector2ui());
+ _tex.setLabel(_path)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setMinificationFilter(GL::SamplerFilter::Linear)
@@ -33,7 +35,7 @@ ground_atlas::ground_atlas(ground_def info, String path, const ImageView2D& imag
std::array<Vector2, 4> ground_atlas::texcoords_for_id(size_t i) const
{
fm_assert(i < num_tiles());
- return texcoords_[i];
+ return _texcoords[i];
}
auto ground_atlas::make_texcoords(Vector2ui pixel_size, Vector2ub tile_count, size_t i) -> texcoords
@@ -53,7 +55,14 @@ auto ground_atlas::make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_cou
return ptr;
}
-size_t ground_atlas::num_tiles() const { return Vector2ui{dims_}.product(); }
-enum pass_mode ground_atlas::pass_mode() const { return passability; }
+size_t ground_atlas::num_tiles() const { return Vector2ui{_def.size}.product(); }
+enum pass_mode ground_atlas::pass_mode() const { return _def.pass; }
+
+String ground_atlas::make_path(StringView name)
+{
+ char buf[fm_FILENAME_MAX];
+ auto sv = loader.make_atlas_path(buf, loader.GROUND_TILESET_PATH, name);
+ return String{sv};
+}
} // namespace floormat
diff --git a/src/ground-atlas.hpp b/src/ground-atlas.hpp
index 38832f9b..e13c0012 100644
--- a/src/ground-atlas.hpp
+++ b/src/ground-atlas.hpp
@@ -1,7 +1,7 @@
#pragma once
#include "src/pass-mode.hpp"
#include "src/quads.hpp"
-#include "loader/ground-info.hpp"
+#include "loader/ground-cell.hpp"
#include <array>
#include <memory>
#include <Corrade/Containers/Optional.h>
@@ -12,13 +12,6 @@
namespace floormat {
-struct ground_def
-{
- String name;
- Vector2ub size;
- pass_mode pass = pass_mode::pass;
-};
-
class ground_atlas;
class ground_atlas final
@@ -28,25 +21,23 @@ class ground_atlas final
static std::unique_ptr<const texcoords[]> make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count);
static texcoords make_texcoords(Vector2ui pixel_size, Vector2ub tile_count, size_t i);
+ static String make_path(StringView name);
- std::unique_ptr<const texcoords[]> texcoords_;
- GL::Texture2D tex_;
- String path_, name_;
- Vector2ui size_;
- Vector2ub dims_;
- enum pass_mode passability;
+ ground_def _def;
+ String _path;
+ std::unique_ptr<const texcoords[]> _texcoords;
+ GL::Texture2D _tex;
+ Vector2ui _pixel_size;
public:
- ground_atlas(ground_def info, String path, const ImageView2D& img);
+ ground_atlas(ground_def info, const ImageView2D& img);
texcoords texcoords_for_id(size_t id) const;
- [[maybe_unused]] Vector2ui pixel_size() const { return size_; }
+ [[maybe_unused]] Vector2ui pixel_size() const { return _pixel_size; }
size_t num_tiles() const;
- Vector2ub num_tiles2() const { return dims_; }
- GL::Texture2D& texture() { return tex_; }
- StringView name() const { return name_; }
+ Vector2ub num_tiles2() const { return _def.size; }
+ GL::Texture2D& texture() { return _tex; }
+ StringView name() const { return _def.name; }
enum pass_mode pass_mode() const;
-
- static constexpr enum pass_mode default_pass_mode = pass_mode::pass;
};
} // namespace floormat
diff --git a/src/ground-def.hpp b/src/ground-def.hpp
new file mode 100644
index 00000000..9b3825ff
--- /dev/null
+++ b/src/ground-def.hpp
@@ -0,0 +1,15 @@
+#pragma once
+#include "pass-mode.hpp"
+#include <Corrade/Containers/String.h>
+#include <Magnum/Math/Vector2.h>
+
+namespace floormat {
+
+struct ground_def
+{
+ String name;
+ Vector2ub size;
+ pass_mode pass = pass_mode::pass;
+};
+
+} // namespace floormat
diff --git a/src/world.cpp b/src/world.cpp
index 59ea8d3d..759b9060 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -44,7 +44,7 @@ world& world::operator=(world&& w) noexcept
_last_chunk = {};
_chunks = std::move(w._chunks);
_objects = std::move(w._objects);
- w._objects = safe_ptr<robin_map_wrapper>{};
+ w._objects = {};
_unique_id = std::move(w._unique_id);
fm_debug_assert(_unique_id);
fm_debug_assert(w._unique_id == nullptr);
diff --git a/test/dijkstra.cpp b/test/dijkstra.cpp
index 8a702a52..6b2eafd4 100644
--- a/test/dijkstra.cpp
+++ b/test/dijkstra.cpp
@@ -1,7 +1,7 @@
#include "app.hpp"
#include "src/path-search.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include <Magnum/Math/Functions.h>
namespace floormat {
diff --git a/test/json.cpp b/test/json.cpp
index d94489ee..aac6fdee 100644
--- a/test/json.cpp
+++ b/test/json.cpp
@@ -11,7 +11,7 @@
#include "src/chunk.hpp"
#include "src/world.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include <memory>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Path.h>
diff --git a/test/loader.cpp b/test/loader.cpp
index 3b04459a..c517d00a 100644
--- a/test/loader.cpp
+++ b/test/loader.cpp
@@ -1,7 +1,7 @@
#include "app.hpp"
#include "compat/assert.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include "src/ground-atlas.hpp"
namespace floormat {
@@ -53,6 +53,7 @@ void test_app::test_loader()
(void)loader.get_wall_atlas(name);
for (const auto& x : loader.ground_atlas_list())
+ if (x.name != loader.INVALID) // todo!
(void)loader.ground_atlas(x.name);
fm_assert(loader.ground_atlas("texel")->pass_mode() == pass_mode::blocked);
fm_assert(loader.ground_atlas("metal1")->pass_mode() == pass_mode::pass);
diff --git a/test/path-search.cpp b/test/path-search.cpp
index 5a1dc825..f602a8b9 100644
--- a/test/path-search.cpp
+++ b/test/path-search.cpp
@@ -2,7 +2,7 @@
#include "compat/assert.hpp"
#include "compat/function2.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include "src/world.hpp"
#include "src/scenery.hpp"
#include "src/path-search.hpp"
diff --git a/test/raycast.cpp b/test/raycast.cpp
index cb76333f..6e3880cd 100644
--- a/test/raycast.cpp
+++ b/test/raycast.cpp
@@ -3,7 +3,7 @@
#include "src/raycast-diag.hpp"
#include "src/world.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
#include <Magnum/Math/Functions.h>
namespace floormat {
diff --git a/test/wall-atlas2.cpp b/test/wall-atlas2.cpp
index 4e86885b..8387d656 100644
--- a/test/wall-atlas2.cpp
+++ b/test/wall-atlas2.cpp
@@ -3,7 +3,7 @@
#include "src/tile-constants.hpp"
#include "src/wall-atlas.hpp"
#include "loader/loader.hpp"
-#include "loader/wall-info.hpp"
+#include "loader/wall-cell.hpp"
namespace floormat {