summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--loader/atlas.cpp4
-rw-r--r--loader/error-tex.cpp13
-rw-r--r--loader/impl.hpp2
-rw-r--r--loader/texture.cpp2
-rw-r--r--loader/wall-atlas.cpp4
-rw-r--r--serialize/world-reader.cpp38
-rw-r--r--serialize/world-writer.cpp50
7 files changed, 58 insertions, 55 deletions
diff --git a/loader/atlas.cpp b/loader/atlas.cpp
index c32ae345..39442b6a 100644
--- a/loader/atlas.cpp
+++ b/loader/atlas.cpp
@@ -30,9 +30,11 @@ bool loader_::check_atlas_name(StringView str) noexcept
{
constexpr auto first_char =
"_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"_s;
+ if (str == "<invalid>"_s)
+ return true;
if (!str || !first_char.find(str[0]))
return false;
- if (str.findAny("\\\"'\n\r\t\a\033\0|$!%{}#^*?<>&;:^"_s) || str.find("/."_s))
+ if (str.findAny("\\\"'\n\r\t\a\033\0|$!%{}^*?<>&;:^"_s) || str.find("/."_s))
return false;
return true;
diff --git a/loader/error-tex.cpp b/loader/error-tex.cpp
index 4cc64f91..7f91f032 100644
--- a/loader/error-tex.cpp
+++ b/loader/error-tex.cpp
@@ -1,15 +1,20 @@
#include "impl.hpp"
+#include "compat/assert.hpp"
+#include <Corrade/Containers/Array.h>
#include <Magnum/Math/Vector4.h>
#include <Magnum/PixelFormat.h>
#include <Magnum/Trade/ImageData.h>
namespace floormat::loader_detail {
-Trade::ImageData2D loader_impl::make_error_texture()
+Trade::ImageData2D loader_impl::make_error_texture(Vector2ui size)
{
- static const Vector4ub data[] = { {255, 0, 255, 255} }; // magenta
- return Trade::ImageData2D{PixelFormat::RGBA8Unorm, {1, 1}, {},
- Containers::arrayView(data, 1), {}, {}};
+ fm_assert(size.product() != 0);
+ constexpr auto magenta = Vector4ub{255, 0, 255, 255};
+ auto array = Array<Vector4ub>{DirectInit, size.product(), magenta};
+ auto img = Trade::ImageData2D{PixelFormat::RGBA8Unorm, Vector2i(size), {},
+ std::move(array), {}, {}};
+ return img;
}
} // namespace floormat::loader_detail
diff --git a/loader/impl.hpp b/loader/impl.hpp
index 84022f8d..4cb9236b 100644
--- a/loader/impl.hpp
+++ b/loader/impl.hpp
@@ -41,7 +41,7 @@ struct loader_impl final : loader_
Optional<Utility::Resource> shader_res;
StringView shader(StringView filename) noexcept override;
- Trade::ImageData2D make_error_texture();
+ Trade::ImageData2D make_error_texture(Vector2ui size);
Trade::ImageData2D texture(StringView prefix, StringView filename, bool fail_ok = true) noexcept(false) override;
// >-----> walls >----->
diff --git a/loader/texture.cpp b/loader/texture.cpp
index 1e4ac709..a12986b4 100644
--- a/loader/texture.cpp
+++ b/loader/texture.cpp
@@ -51,7 +51,7 @@ Trade::ImageData2D loader_impl::texture(StringView prefix, StringView filename_,
if (!fail_ok)
fm_throw("can't open image '{}' (cwd '{}'): {}"_cf, buf, path ? StringView{*path} : "(null)"_s, get_error_string(errbuf));
else
- return make_error_texture();
+ return make_error_texture({1,1});
}
} // namespace floormat::loader_detail
diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp
index 4f13e91a..502cfd0c 100644
--- a/loader/wall-atlas.cpp
+++ b/loader/wall-atlas.cpp
@@ -65,10 +65,10 @@ const wall_info& loader_impl::make_invalid_wall_atlas()
wall_atlas_def {
Wall::Info{.name = name, .depth = 8},
{{ {}, frame_size}, },
- {{ {.index = 0, .count = 1, .pixel_size = frame_size, } } },
+ {{ {.index = 0, .count = 1, .pixel_size = frame_size, .is_defined = true, } } },
{{ {.val = 0}, {}, }},
{1u},
- }, name, make_error_texture());
+ }, name, make_error_texture(frame_size));
invalid_wall_atlas = Pointer<wall_info>{InPlaceInit, wall_info{ .name = name, .atlas = std::move(a) } };
return *invalid_wall_atlas;
}
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index d3954b09..f90acbd6 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -27,7 +27,7 @@ struct reader_state final {
private:
using reader_t = binary_reader<decltype(ArrayView<const char>{}.cbegin())>;
- const std::shared_ptr<tile_atlas>& lookup_atlas(atlasid id);
+ StringView lookup_atlas(atlasid id);
const scenery_proto& lookup_scenery(atlasid id);
StringView lookup_string(uint32_t idx);
void read_atlases(reader_t& reader);
@@ -38,7 +38,7 @@ private:
std::vector<String> strings;
std::vector<scenery_proto> sceneries;
- std::vector<std::shared_ptr<tile_atlas>> atlases;
+ std::vector<String> atlases;
world* _world;
uint16_t PROTO = proto_version;
@@ -59,9 +59,7 @@ void reader_state::read_atlases(reader_t& s)
size[0] << s;
size[1] << s;
const auto& [buf, len] = s.read_asciiz_string<atlas_name_max>();
- auto atlas = loader.tile_atlas({buf, len});
- fm_soft_assert(size <= atlas->num_tiles2());
- atlases.push_back(std::move(atlas));
+ atlases.push_back({buf, len});
}
}
@@ -136,7 +134,7 @@ void reader_state::read_strings(reader_t& s)
}
}
-const std::shared_ptr<tile_atlas>& reader_state::lookup_atlas(atlasid id)
+StringView reader_state::lookup_atlas(atlasid id)
{
if (id < atlases.size())
return atlases[id];
@@ -202,7 +200,7 @@ void reader_state::read_chunks(reader_t& s)
tile_ref t = c[i];
using uchar = uint8_t;
- const auto make_atlas = [&]() -> tile_image_proto {
+ const auto make_atlas = [&]<typename T>() -> image_proto_<T> {
atlasid id;
if (PROTO < 8) [[unlikely]]
id = flags & meta_short_atlasid_ ? atlasid{s.read<uchar>()} : s.read<atlasid>();
@@ -215,21 +213,29 @@ void reader_state::read_chunks(reader_t& s)
v = flags & meta_short_variant_
? s.read<uint8_t>()
: uint8_t(s.read<uint16_t>());
- auto atlas = lookup_atlas(id);
- fm_soft_assert(v < atlas->num_tiles());
- return { atlas, v };
+ auto name = lookup_atlas(id);
+ if constexpr(std::is_same_v<tile_atlas, T>)
+ {
+ auto atlas = loader.tile_atlas(name);
+ fm_soft_assert(v < atlas->num_tiles());
+ return { atlas, v };
+ }
+ else if (std::is_same_v<wall_atlas, T>)
+ {
+ auto atlas = loader.wall_atlas(name, true);
+ return { atlas, v };
+ }
+ else
+ std::unreachable();
};
SET_CHUNK_SIZE();
//t.passability() = pass_mode(flags & pass_mask);
if (flags & meta_ground)
- t.ground() = make_atlas();
- // todo!
-#if 0
+ t.ground() = make_atlas.operator()<tile_atlas>();
if (flags & meta_wall_n)
- t.wall_north() = make_atlas();
+ t.wall_north() = make_atlas.operator()<wall_atlas>();
if (flags & meta_wall_w)
- t.wall_west() = make_atlas();
-#endif
+ t.wall_west() = make_atlas.operator()<wall_atlas>();
if (PROTO >= 3 && PROTO < 8) [[unlikely]]
if (flags & meta_scenery_)
read_old_scenery(s, ch, i);
diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp
index 90fcf3b4..a89f039a 100644
--- a/serialize/world-writer.cpp
+++ b/serialize/world-writer.cpp
@@ -1,7 +1,7 @@
#define FM_SERIALIZE_WORLD_IMPL
#include "world-impl.hpp"
-
#include "src/tile-atlas.hpp"
+#include "src/wall-atlas.hpp"
#include "binary-writer.inl"
#include "src/global-coords.hpp"
#include "src/chunk.hpp"
@@ -30,8 +30,9 @@ using namespace floormat::Serialize;
namespace {
struct interned_atlas final {
- const tile_atlas* img;
+ StringView name;
atlasid index;
+ Vector2ub num_tiles;
};
struct interned_scenery {
@@ -55,8 +56,7 @@ struct writer_state final {
private:
using writer_t = binary_writer<decltype(std::vector<char>{}.begin())>;
- atlasid intern_atlas(const tile_image_proto& img);
- atlasid maybe_intern_atlas(const tile_image_proto& img);
+ atlasid intern_atlas(const void* ptr, StringView name, Vector2ub num_tiles);
scenery_pair intern_scenery(const scenery& sc, bool create);
uint32_t intern_string(StringView name);
@@ -97,17 +97,17 @@ uint32_t writer_state::intern_string(StringView name)
return kv->second;
}
-atlasid writer_state::intern_atlas(const tile_image_proto& img)
+atlasid writer_state::intern_atlas(const void* ptr, StringView name, Vector2ub num_tiles)
{
- const void* const ptr = img.atlas.get();
fm_debug_assert(ptr != nullptr);
- emplacer e{[&]() -> interned_atlas { return { &*img.atlas, (atlasid)tile_images.size() }; }};
- return tile_images.try_emplace(ptr, e).first->second.index;
-}
-
-atlasid writer_state::maybe_intern_atlas(const tile_image_proto& img)
-{
- return img ? intern_atlas(img) : null_atlas;
+ if (auto it = tile_images.find(ptr); it != tile_images.end())
+ return it->second.index;
+ else
+ {
+ auto aid = (atlasid)tile_images.size();
+ tile_images[ptr] = { name, aid, num_tiles };
+ return aid;
+ }
}
void writer_state::load_scenery_1(const serialized_scenery& s)
@@ -227,14 +227,12 @@ void writer_state::serialize_atlases()
return a.index < b.index;
});
- for (const auto& [atlas, _] : atlases)
+ for (const auto& [name, aid, num_tiles] : atlases)
{
- const auto name = atlas->name();
const auto namesiz = name.size();
fm_debug_assert(s.bytes_written() + namesiz < atlasbuf_size);
fm_assert(namesiz < atlas_name_max);
- const auto sz2 = atlas->num_tiles2();
- s << sz2[0]; s << sz2[1];
+ s << num_tiles[0]; s << num_tiles[1];
s.write_asciiz_string(name);
}
atlas_buf.resize(s.bytes_written());
@@ -464,11 +462,11 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords_ coord)
fm_debug_assert(s.bytes_written() + tile_size <= chunkbuf_size);
- auto img_g = maybe_intern_atlas(ground);
- //auto img_n = maybe_intern_atlas(wall_north);
- //auto img_w = maybe_intern_atlas(wall_west);
- // todo!
- auto img_n = null_atlas, img_w = null_atlas;
+ auto img_g = ground.atlas ? intern_atlas(&*ground.atlas, ground.atlas->name(), ground.atlas->num_tiles2()) : null_atlas;
+ auto img_n = wall_north ? intern_atlas(&*wall_north.atlas, wall_north.atlas->name(), {0xff, 0xff}) : null_atlas;
+ auto img_w = wall_west ? intern_atlas(&*wall_west.atlas, wall_west.atlas->name(), {0xff, 0xff}) : null_atlas;
+
+ fm_assert(!ground.atlas || ground.variant < ground.atlas->num_tiles());
if (img_g == null_atlas && img_n == null_atlas && img_w == null_atlas)
{
@@ -494,14 +492,6 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords_ coord)
flags |= meta_wall_w * (img_w != null_atlas);
s << flags;
- constexpr auto check_atlas = [](const tile_image_proto& x) {
- fm_assert(!x.atlas || x.variant < x.atlas->num_tiles());
- };
- check_atlas(ground);
- // todo!
- //check_atlas(wall_north);
- //check_atlas(wall_west);
-
if (img_g != null_atlas)
{
s << img_g;