summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-01 16:35:03 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-01 16:35:03 +0100
commit704e9bd3ac58484a5209e186798076f1cbd432ef (patch)
tree511479ebd088d5c9524803c6f3fe4641009b58bc
parent7ff1f0911e0b0c314d6e639887b705d6fc0d78aa (diff)
wip
-rw-r--r--draw/floor.cpp12
-rw-r--r--draw/floor.hpp6
-rw-r--r--draw/wall.cpp11
-rw-r--r--draw/wall.hpp8
-rw-r--r--editor/editor.cpp28
-rw-r--r--editor/editor.hpp12
-rw-r--r--editor/update.cpp10
-rw-r--r--floormat/events.hpp1
-rw-r--r--serialize/tile.cpp10
-rw-r--r--serialize/tile.hpp8
-rw-r--r--serialize/world-impl.hpp8
-rw-r--r--serialize/world-reader.cpp20
-rw-r--r--serialize/world-writer.cpp39
-rw-r--r--src/chunk.cpp6
-rw-r--r--src/chunk.hpp26
-rw-r--r--src/local-coords.hpp2
-rw-r--r--src/tile-atlas.cpp3
-rw-r--r--src/tile-image.cpp17
-rw-r--r--src/tile-image.hpp8
-rw-r--r--src/tile-iterator.cpp8
-rw-r--r--src/tile-iterator.hpp10
-rw-r--r--src/tile.cpp32
-rw-r--r--src/tile.hpp15
-rw-r--r--src/world.hpp2
-rw-r--r--test/json.cpp12
-rw-r--r--test/serializer.cpp12
-rw-r--r--test/tile-iter.cpp10
27 files changed, 180 insertions, 156 deletions
diff --git a/draw/floor.cpp b/draw/floor.cpp
index 444ee127..861336c7 100644
--- a/draw/floor.cpp
+++ b/draw/floor.cpp
@@ -17,11 +17,11 @@ floor_mesh::floor_mesh()
.setIndexBuffer(_index_buffer, 0, GL::MeshIndexType::UnsignedShort);
}
-void floor_mesh::set_tile(quad_data& data, tile& x)
+void floor_mesh::set_tile(quad_data& data, tile_ref& x)
{
- if (x.ground)
+ if (auto ground = x.ground(); ground)
{
- auto texcoords = x.ground.atlas->texcoords_for_id(x.ground.variant);
+ auto texcoords = ground.atlas->texcoords_for_id(ground.variant);
for (size_t i = 0; i < 4; i++)
data[i] = { texcoords[i] };
}
@@ -34,7 +34,7 @@ void floor_mesh::draw(tile_shader& shader, chunk& c)
{
//_vertex_buffer.setData({nullptr, sizeof(quad_data) * TILE_COUNT}, Magnum::GL::BufferUsage::DynamicDraw); // orphan the buffer
std::array<quad_data, TILE_COUNT> data;
- for (auto& [x, idx, pt] : c) {
+ for (auto [x, idx, pt] : c) {
set_tile(data[idx], x);
}
_vertex_buffer.setSubData(0, data);
@@ -57,8 +57,8 @@ void floor_mesh::draw(tile_shader& shader, chunk& c)
last_pos = i;
};
- for (auto& [x, i, pt] : c)
- do_draw(i, x.ground.atlas.get());
+ for (auto [x, i, pt] : c)
+ do_draw(i, x.ground_atlas().get());
do_draw(TILE_COUNT, nullptr);
}
diff --git a/draw/floor.hpp b/draw/floor.hpp
index 4a273dfc..4ece92eb 100644
--- a/draw/floor.hpp
+++ b/draw/floor.hpp
@@ -10,10 +10,10 @@
namespace floormat {
-struct tile_shader;
-struct chunk;
struct tile_ref;
struct tile_proto;
+struct tile_shader;
+struct chunk;
struct floor_mesh final
{
@@ -34,7 +34,7 @@ private:
GL::Buffer _vertex_buffer{std::array<quad_data, TILE_COUNT>{}, Magnum::GL::BufferUsage::DynamicDraw},
_index_buffer{make_index_array()}, _positions_buffer{make_position_array()};
- static void set_tile(quad_data& data, tile& x);
+ static void set_tile(quad_data& data, tile_ref& x);
};
} // namespace floormat
diff --git a/draw/wall.cpp b/draw/wall.cpp
index 4602453d..18462e2c 100644
--- a/draw/wall.cpp
+++ b/draw/wall.cpp
@@ -2,6 +2,7 @@
#include "tile-atlas.hpp"
#include "shaders/tile.hpp"
#include "chunk.hpp"
+#include "tile-image.hpp"
#include <Magnum/GL/Texture.h>
#include <Magnum/GL/MeshView.h>
@@ -18,7 +19,7 @@ wall_mesh::wall_mesh()
CORRADE_INTERNAL_ASSERT(_mesh.isIndexed());
}
-void wall_mesh::add_wall(vertex_array& data, texture_array& textures, tile_image& img, std::size_t pos)
+void wall_mesh::add_wall(vertex_array& data, texture_array& textures, const tile_image_ref& img, std::size_t pos)
{
CORRADE_INTERNAL_ASSERT(pos < data.size());
auto texcoords = img.atlas->texcoords_for_id(img.variant);
@@ -29,11 +30,11 @@ void wall_mesh::add_wall(vertex_array& data, texture_array& textures, tile_image
}
}
-void wall_mesh::maybe_add_tile(vertex_array& data, texture_array& textures, tile& x, std::size_t pos)
+void wall_mesh::maybe_add_tile(vertex_array& data, texture_array& textures, tile_ref x, std::size_t pos)
{
- if (auto& wall = x.wall_north; wall.atlas)
+ if (auto wall = x.wall_north(); wall.atlas)
add_wall(data, textures, wall, pos * 2 + 0);
- if (auto& wall = x.wall_west; wall.atlas)
+ if (auto wall = x.wall_west(); wall.atlas)
add_wall(data, textures, wall, pos * 2 + 1);
}
@@ -43,7 +44,7 @@ void wall_mesh::draw(tile_shader& shader, chunk& c)
texture_array textures = {};
{
vertex_array data;
- for (auto& [x, idx, pt] : c) {
+ for (auto [x, idx, pt] : c) {
maybe_add_tile(data, textures, x, idx);
}
_vertex_buffer.setSubData(0, data);
diff --git a/draw/wall.hpp b/draw/wall.hpp
index 06d99842..ad1eafad 100644
--- a/draw/wall.hpp
+++ b/draw/wall.hpp
@@ -10,10 +10,10 @@
namespace floormat {
-struct tile;
-struct tile_image;
struct tile_shader;
struct chunk;
+struct tile_ref;
+struct tile_image_ref;
struct wall_mesh final
{
@@ -31,8 +31,8 @@ private:
using vertex_array = std::array<quad, COUNT>;
using texture_array = std::array<GL::Texture2D*, COUNT>;
- static void maybe_add_tile(vertex_array& data, texture_array& textures, tile& x, std::size_t pos);
- static void add_wall(vertex_array& data, texture_array& textures, tile_image& img, std::size_t pos);
+ static void maybe_add_tile(vertex_array& data, texture_array& textures, tile_ref x, std::size_t pos);
+ static void add_wall(vertex_array& data, texture_array& textures, const tile_image_ref& img, std::size_t pos);
GL::Mesh _mesh;
GL::Buffer _vertex_buffer{vertex_array{}, Magnum::GL::BufferUsage::DynamicDraw},
diff --git a/editor/editor.cpp b/editor/editor.cpp
index fc2d1a1f..3d2ee3a6 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -68,7 +68,7 @@ void tile_editor::select_tile(const std::shared_ptr<tile_atlas>& atlas, std::siz
fm_assert(atlas);
clear_selection();
_selection_mode = sel_tile;
- _selected_tile = { atlas, decltype(tile_image::variant)(variant % atlas->num_tiles()) };
+ _selected_tile = { atlas, variant_t(variant % atlas->num_tiles()) };
}
void tile_editor::select_tile_permutation(const std::shared_ptr<tile_atlas>& atlas)
@@ -117,10 +117,9 @@ void fisher_yates(T begin, T end)
}
}
-tile_image tile_editor::get_selected_perm()
+tile_image_proto tile_editor::get_selected_perm()
{
auto& [atlas, vec] = _permutation;
- using variant_t = decltype(tile_image::variant);
const auto N = (variant_t)atlas->num_tiles();
if (N == 0)
return {};
@@ -135,7 +134,7 @@ tile_image tile_editor::get_selected_perm()
return {atlas, idx};
}
-tile_image tile_editor::get_selected()
+tile_image_proto tile_editor::get_selected()
{
switch (_selection_mode)
{
@@ -151,25 +150,26 @@ tile_image tile_editor::get_selected()
}
}
-void tile_editor::place_tile(world& world, global_coords pos, tile_image& img)
+void tile_editor::place_tile(world& world, global_coords pos, const tile_image_proto& img)
{
- const auto& [c, t] = world[pos];
+ auto [c, t] = world[pos];
const auto& [atlas, variant] = img;
switch (_mode)
{
- default:
- fm_warn_once("invalid editor mode '%u'", (unsigned)_mode);
- break;
case editor_mode::none:
break;
case editor_mode::floor:
- t.ground = { atlas, variant };
+ t.ground() = img;
break;
case editor_mode::walls:
- switch (tile_image x = { atlas, variant }; _rotation)
+ switch (_rotation)
{
- case editor_wall_rotation::N: t.wall_north = x; break;
- case editor_wall_rotation::W: t.wall_west = x; break;
+ case editor_wall_rotation::N:
+ t.wall_north() = img;
+ break;
+ case editor_wall_rotation::W:
+ t.wall_west() = img;
+ break;
}
break;
}
@@ -307,7 +307,7 @@ void editor::on_click(world& world, global_coords pos, int mods, button b)
if (auto opt = mode->get_selected(); opt)
{
_last_pos = { pos, mode->check_snap(mods), _last_pos ? _last_pos->btn : b };
- switch (tile_image empty; b)
+ switch (tile_image_proto empty; b)
{
case button::place: return mode->place_tile(world, pos, opt);
case button::remove: return mode->place_tile(world, pos, empty);
diff --git a/editor/editor.hpp b/editor/editor.hpp
index 460bb8c8..dda13567 100644
--- a/editor/editor.hpp
+++ b/editor/editor.hpp
@@ -2,7 +2,7 @@
#include "compat/defs.hpp"
#include "tile-atlas.hpp"
#include "global-coords.hpp"
-#include "tile-image.hpp"
+#include "tile.hpp"
#include <cstdint>
#include <tuple>
@@ -34,14 +34,14 @@ private:
std::string _name;
std::map<std::string, std::shared_ptr<tile_atlas>> _atlases;
- tile_image _selected_tile;
- std::tuple<std::shared_ptr<tile_atlas>, std::vector<decltype(tile_image::variant)>> _permutation;
+ tile_image_proto _selected_tile;
+ std::tuple<std::shared_ptr<tile_atlas>, std::vector<decltype(tile_image_proto::variant)>> _permutation;
selection_mode _selection_mode = sel_none;
editor_mode _mode;
editor_wall_rotation _rotation = editor_wall_rotation::W;
void load_atlases();
- tile_image get_selected_perm();
+ tile_image_proto get_selected_perm();
public:
enum class snap_mode : std::uint8_t {
@@ -68,8 +68,8 @@ public:
bool is_tile_selected(const std::shared_ptr<const tile_atlas>& atlas, std::size_t variant) const;
bool is_permutation_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
bool is_atlas_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
- tile_image get_selected();
- void place_tile(world& world, global_coords pos, tile_image& img);
+ tile_image_proto get_selected();
+ void place_tile(world& world, global_coords pos, const tile_image_proto& img);
void toggle_rotation();
void set_rotation(editor_wall_rotation r);
snap_mode check_snap(int mods) const;
diff --git a/editor/update.cpp b/editor/update.cpp
index b96d80fe..adca9492 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -18,16 +18,16 @@ void app::maybe_initialize_chunk_(const chunk_coords& pos, chunk& c)
#else
const auto& atlas = pt.x == N/2 || pt.y == N/2 ? _floor2 : _floor1;
#endif
- x.ground = { atlas, decltype(tile_image::variant)(k % atlas->num_tiles()) };
+ x.ground() = { atlas, variant_t(k % atlas->num_tiles()) };
}
#ifdef FM_NO_BINDINGS
const auto& wall1 = floor1, wall2 = floor1;
#endif
constexpr auto K = N/2;
- c[{K, K }].wall_north = { _wall1, 0 };
- c[{K, K }].wall_west = { _wall2, 0 };
- c[{K, K+1}].wall_north = { _wall1, 0 };
- c[{K+1, K }].wall_west = { _wall2, 0 };
+ c[{K, K }].wall_north() = { _wall1, 0 };
+ c[{K, K }].wall_west() = { _wall2, 0 };
+ c[{K, K+1}].wall_north() = { _wall1, 0 };
+ c[{K+1, K }].wall_west() = { _wall2, 0 };
}
void app::maybe_initialize_chunk([[maybe_unused]] const chunk_coords& pos, [[maybe_unused]] chunk& c)
diff --git a/floormat/events.hpp b/floormat/events.hpp
index 6ab1b3ae..597c89b2 100644
--- a/floormat/events.hpp
+++ b/floormat/events.hpp
@@ -47,7 +47,6 @@ struct key_event final {
};
union alignas(alignof(void*)) any_event {
- std::size_t size[0] = {};
char buf[64];
};
diff --git a/serialize/tile.cpp b/serialize/tile.cpp
index 68def2d8..abce91e1 100644
--- a/serialize/tile.cpp
+++ b/serialize/tile.cpp
@@ -6,7 +6,11 @@
namespace floormat {
-NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(tile_image, atlas, variant)
+NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(tile_image_proto, atlas, variant)
+
+inline void to_json(nlohmann::json& j, const tile_image_ref& val) { j = tile_image_proto(val); }
+inline void from_json(const nlohmann::json& j, tile_image_ref& val) { val = tile_image_proto(j); }
+
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(local_coords, x, y)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(chunk_coords, x, y)
@@ -23,8 +27,8 @@ using namespace floormat;
namespace nlohmann {
-void adl_serializer<tile_image>::to_json(json& j, const tile_image& val) { using nlohmann::to_json; if (val.atlas) to_json(j, val); else j = nullptr; }
-void adl_serializer<tile_image>::from_json(const json& j, tile_image& val) { using nlohmann::from_json; if (j.is_null()) val = {}; else from_json(j, val); }
+void adl_serializer<tile_image_ref>::to_json(json& j, const tile_image_ref& val) { using nlohmann::to_json; if (val.atlas) to_json(j, val); else j = nullptr; }
+void adl_serializer<tile_image_ref>::from_json(const json& j, tile_image_ref& val) { using nlohmann::from_json; if (j.is_null()) val = {}; else from_json(j, val); }
void adl_serializer<local_coords>::to_json(json& j, const local_coords& val) { using nlohmann::to_json; to_json(j, val); }
void adl_serializer<local_coords>::from_json(const json& j, local_coords& val) { using nlohmann::from_json; from_json(j, val); }
diff --git a/serialize/tile.hpp b/serialize/tile.hpp
index 1d629fe6..66982682 100644
--- a/serialize/tile.hpp
+++ b/serialize/tile.hpp
@@ -3,7 +3,7 @@
namespace floormat {
-struct tile_image;
+struct tile_image_ref;
struct local_coords;
struct chunk_coords;
struct global_coords;
@@ -13,9 +13,9 @@ struct global_coords;
namespace nlohmann {
template<>
-struct adl_serializer<floormat::tile_image> {
- static void to_json(json& j, const floormat::tile_image& val);
- static void from_json(const json& j, floormat::tile_image& val);
+struct adl_serializer<floormat::tile_image_ref> {
+ static void to_json(json& j, const floormat::tile_image_ref& val);
+ static void from_json(const json& j, floormat::tile_image_ref& val);
};
template<>
diff --git a/serialize/world-impl.hpp b/serialize/world-impl.hpp
index a0414606..caf5e8a7 100644
--- a/serialize/world-impl.hpp
+++ b/serialize/world-impl.hpp
@@ -12,10 +12,10 @@ namespace floormat::Serialize {
namespace {
using tilemeta = std::uint8_t;
-using varid = decltype(tile_image::variant);
+using varid = decltype(tile_image_proto::variant);
using atlasid = std::uint16_t;
using chunksiz = std::uint16_t;
-using enum tile::pass_mode;
+using proto_t = std::uint16_t;
template<typename T> constexpr inline T int_max = std::numeric_limits<T>::max();
@@ -24,10 +24,10 @@ template<typename T> constexpr inline T int_max = std::numeric_limits<T>::max();
constexpr inline std::size_t atlas_name_max = 128;
constexpr inline auto null_atlas = (atlasid)-1LL;
-constexpr inline std::uint16_t proto_version = 1;
+constexpr inline proto_t proto_version = 1;
constexpr inline auto chunk_magic = (std::uint16_t)~0xc0d3;
-constexpr inline std::underlying_type_t<tile::pass_mode> pass_mask = pass_blocked | pass_shoot_through | pass_ok;
+constexpr inline std::underlying_type_t<pass_mode> pass_mask = pass_blocked | pass_shoot_through | pass_ok;
constexpr inline auto pass_bits = std::bit_width(pass_mask);
enum : tilemeta {
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index 385d6e39..aa156609 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -65,9 +65,9 @@ void reader_state::read_chunks(reader_t& s)
for (std::size_t i = 0; i < TILE_COUNT; i++)
{
const tilemeta flags = s.read<tilemeta>();
- tile& t = chunk[i];
+ tile_ref t = chunk[i];
using uchar = std::uint8_t;
- const auto make_atlas = [&]() -> tile_image {
+ const auto make_atlas = [&]() -> tile_image_proto {
auto id = flags & meta_short_atlasid ? (atlasid)(s.read<uchar>()) : s.read<atlasid>();
auto v = flags & meta_short_variant ? (varid) (s.read<uchar>()) : s.read<varid>();
auto atlas = lookup_atlas(id);
@@ -76,18 +76,18 @@ void reader_state::read_chunks(reader_t& s)
};
if (flags & meta_ground)
- t.ground = make_atlas();
+ t.ground() = make_atlas();
if (flags & meta_wall_n)
- t.wall_north = make_atlas();
+ t.wall_north() = make_atlas();
if (flags & meta_wall_w)
- t.wall_west = make_atlas();
+ t.wall_west() = make_atlas();
- switch (auto x = flags & pass_mask)
+ switch (auto x = pass_mode(flags & pass_mask))
{
- case tile::pass_shoot_through:
- case tile::pass_blocked:
- case tile::pass_ok:
- t.passability = (tile::pass_mode)x;
+ case pass_shoot_through:
+ case pass_blocked:
+ case pass_ok:
+ t.pass_mode() = x;
break;
default:
fm_abort("bad pass mode '%zu' for tile %zu", i, (std::size_t)x);
diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp
index a55e6eb1..c16dc32a 100644
--- a/serialize/world-writer.cpp
+++ b/serialize/world-writer.cpp
@@ -29,8 +29,8 @@ struct writer_state final {
fm_DECLARE_DEPRECATED_COPY_ASSIGNMENT(writer_state);
private:
- atlasid intern_atlas(const tile_image& img);
- atlasid maybe_intern_atlas(const tile_image& img);
+ atlasid intern_atlas(const tile_image_proto& img);
+ atlasid maybe_intern_atlas(const tile_image_proto& img);
void serialize_chunk(const chunk& c, chunk_coords coord);
void serialize_atlases();
@@ -66,7 +66,7 @@ writer_state::writer_state(const struct world& world) : world{&world}
#pragma warning(pop)
#endif
-atlasid writer_state::intern_atlas(const tile_image& img)
+atlasid writer_state::intern_atlas(const tile_image_proto& img)
{
const void* const ptr = img.atlas.get();
fm_debug_assert(ptr != nullptr);
@@ -76,7 +76,7 @@ atlasid writer_state::intern_atlas(const tile_image& img)
return (tile_images[ptr] = { &*img.atlas, (atlasid)tile_images.size() }).index;
}
-atlasid writer_state::maybe_intern_atlas(const tile_image& img)
+atlasid writer_state::maybe_intern_atlas(const tile_image_proto& img)
{
return img ? intern_atlas(img) : null_atlas;
}
@@ -92,13 +92,14 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
for (std::size_t i = 0; i < TILE_COUNT; i++)
{
- const tile& x = c[i];
+ const tile_proto x = c[i];
+ const auto ground = x.ground_image(), wall_north = x.wall_north_image(), wall_west = x.wall_west_image();
fm_debug_assert(s.bytes_written() + tile_size <= chunkbuf_size);
- auto img_g = maybe_intern_atlas(x.ground);
- auto img_n = maybe_intern_atlas(x.wall_north);
- auto img_w = maybe_intern_atlas(x.wall_west);
+ auto img_g = maybe_intern_atlas(ground);
+ auto img_n = maybe_intern_atlas(wall_north);
+ auto img_w = maybe_intern_atlas(wall_west);
tilemeta flags = {};
flags |= meta_ground * (img_g != null_atlas);
@@ -110,28 +111,28 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
constexpr auto ashortp = [](atlasid id) {
return id == null_atlas || id == (uchar)id;
};
- constexpr auto vshortp = [](const tile_image& img) {
+ constexpr auto vshortp = [](const tile_image_proto& img) {
return !img.atlas || img.variant == (uchar)img.variant;
};
if (flags != 0 && ashortp(img_g) && ashortp(img_n) && ashortp(img_w))
flags |= meta_short_atlasid;
- if (flags != 0 && vshortp(x.ground) && vshortp(x.wall_north) && vshortp(x.wall_west))
+ if (flags != 0 && vshortp(ground) && vshortp(wall_north) && vshortp(wall_west))
flags |= meta_short_variant;
- fm_debug_assert((x.passability & pass_mask) == x.passability);
- flags |= x.passability;
+ fm_debug_assert((x.pass_mode & pass_mask) == x.pass_mode);
+ flags |= x.pass_mode;
s << flags;
#ifndef FM_NO_DEBUG
- constexpr auto check_atlas = [](const tile_image& x) {
+ constexpr auto check_atlas = [](const tile_image_proto& x) {
if (x.atlas)
fm_assert(x.variant < x.atlas->num_tiles());
};
- check_atlas(x.ground);
- check_atlas(x.wall_north);
- check_atlas(x.wall_west);
+ check_atlas(ground);
+ check_atlas(wall_north);
+ check_atlas(wall_west);
#endif
const auto write = [&](atlasid x, varid v) {
@@ -140,11 +141,11 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
};
if (img_g != null_atlas)
- write(img_g, x.ground.variant);
+ write(img_g, ground.variant);
if (img_n != null_atlas)
- write(img_n, x.wall_north.variant);
+ write(img_n, wall_north.variant);
if (img_w != null_atlas)
- write(img_w, x.wall_west.variant);
+ write(img_w, wall_west.variant);
}
const auto nbytes = s.bytes_written();
diff --git a/src/chunk.cpp b/src/chunk.cpp
index 9eca0138..59e05d73 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -7,12 +7,14 @@ bool chunk::empty(bool force) const noexcept
if (!force && !_maybe_empty)
return false;
- for (const tile& x : _tiles)
- if (x.ground || x.wall_north || x.wall_west)
+ for (std::size_t i = 0; i < TILE_COUNT; i++)
+ {
+ if (_ground_atlases[i] || _wall_north_atlases[i] || _wall_west_atlases[i])
{
_maybe_empty = false;
return false;
}
+ }
return true;
}
diff --git a/src/chunk.hpp b/src/chunk.hpp
index 6031b913..564f049e 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -12,25 +12,15 @@ struct chunk final
friend struct tile_ref;
friend struct pass_mode_ref;
-#if 0
- tile& operator[](local_coords xy) noexcept { return _tiles[xy.to_index()]; }
- const tile& operator[](local_coords xy) const noexcept { return _tiles[xy.to_index()]; }
- tile& operator[](std::size_t i) noexcept { return _tiles[i]; }
- const tile& operator[](std::size_t i) const noexcept { return _tiles[i]; }
- const auto& tiles() const noexcept { return _tiles; }
- auto& tiles() noexcept { return _tiles; }
-#endif
+ tile_ref operator[](std::size_t idx) noexcept { return { *this, std::uint8_t(idx) }; }
+ tile_proto operator[](std::size_t idx) const noexcept { return tile_proto(tile_ref { *const_cast<chunk*>(this), std::uint8_t(idx) }); }
+ tile_ref operator[](local_coords xy) noexcept { return operator[](xy.to_index()); }
+ tile_proto operator[](local_coords xy) const noexcept { return operator[](xy.to_index()); }
using iterator = tile_iterator;
-#if 0
- iterator begin() noexcept { return iterator{_tiles.data(), 0}; }
- iterator end() noexcept { return iterator{_tiles.data(), _tiles.size()}; }
- const_iterator cbegin() const noexcept { return const_iterator{_tiles.data(), 0}; }
- const_iterator cend() const noexcept { return const_iterator{_tiles.data(), _tiles.size()}; }
- const_iterator begin() const noexcept { return cbegin(); }
- const_iterator end() const noexcept { return cend(); }
-#endif
+ iterator begin() noexcept { return iterator { *this, 0 }; }
+ iterator end() noexcept { return iterator { *this, TILE_COUNT }; }
bool empty(bool force = false) const noexcept;
@@ -43,8 +33,8 @@ private:
static constexpr std::size_t PASS_BITS = 2;
std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases, _wall_north_atlases, _wall_west_atlases;
- std::array<std::uint16_t, TILE_COUNT> _ground_variants, _wall_north_variants, _wall_west_variants;
- std::bitset<TILE_COUNT*2> _passability;
+ std::array<std::uint16_t, TILE_COUNT> _ground_variants = {}, _wall_north_variants = {}, _wall_west_variants = {};
+ std::bitset<TILE_COUNT*2> _passability = {};
mutable bool _maybe_empty = true;
};
diff --git a/src/local-coords.hpp b/src/local-coords.hpp
index e0aea1d6..949a90e0 100644
--- a/src/local-coords.hpp
+++ b/src/local-coords.hpp
@@ -12,7 +12,7 @@ struct local_coords final {
template<std::integral T> requires (sizeof(T) <= sizeof(std::size_t))
constexpr local_coords(T x, T y) noexcept;
constexpr local_coords(std::uint8_t x, std::uint8_t y) noexcept : x{x}, y{y} {}
- constexpr std::size_t to_index() const noexcept { return y*TILE_MAX_DIM + x; }
+ constexpr std::uint8_t to_index() const noexcept { return y*TILE_MAX_DIM + x; }
};
constexpr local_coords::local_coords(std::size_t index) noexcept :
diff --git a/src/tile-atlas.cpp b/src/tile-atlas.cpp
index e6df942f..624b4694 100644
--- a/src/tile-atlas.cpp
+++ b/src/tile-atlas.cpp
@@ -13,7 +13,8 @@ tile_atlas::tile_atlas(StringView name, const ImageView2D& image, Vector2ub tile
texcoords_{make_texcoords_array(Vector2ui(image.size()), tile_count)},
name_{name}, size_{image.size()}, dims_{tile_count}
{
- fm_assert(num_tiles() <= std::numeric_limits<decltype(tile_image::variant)>::max());
+ constexpr auto variant_max = std::numeric_limits<variant_t>::max();
+ fm_assert(num_tiles() <= variant_max);
fm_assert(dims_[0] > 0 && dims_[1] > 0);
fm_assert(size_ % Vector2ui{tile_count} == Vector2ui());
tex_.setWrapping(GL::SamplerWrapping::ClampToEdge)
diff --git a/src/tile-image.cpp b/src/tile-image.cpp
index c9dc24f4..5d9d9f11 100644
--- a/src/tile-image.cpp
+++ b/src/tile-image.cpp
@@ -2,18 +2,16 @@
namespace floormat {
-bool operator==(const tile_image_proto& a, const tile_image_proto& b) noexcept = default;
-
-tile_image_ref::tile_image_ref(std::shared_ptr<tile_atlas>& atlas, std::uint16_t& variant) noexcept :
- atlas{atlas}, variant{variant}
+bool operator==(const tile_image_proto& a, const tile_image_proto& b) noexcept
{
+ return a.atlas == b.atlas && a.variant == b.variant;
}
-tile_image_ref& tile_image_ref::operator=(tile_image_ref&& ref) noexcept
+tile_image_proto::operator bool() const noexcept { return atlas != nullptr; }
+
+tile_image_ref::tile_image_ref(std::shared_ptr<tile_atlas>& atlas, std::uint16_t& variant) noexcept :
+ atlas{atlas}, variant{variant}
{
- atlas = ref.atlas;
- variant = ref.variant;
- return *this;
}
tile_image_ref& tile_image_ref::operator=(const tile_image_proto& proto) noexcept
@@ -24,11 +22,12 @@ tile_image_ref& tile_image_ref::operator=(const tile_image_proto& proto) noexcep
}
tile_image_ref::tile_image_ref(const tile_image_ref&) noexcept = default;
-tile_image_ref::tile_image_ref(tile_image_ref&&) noexcept = default;
tile_image_ref::operator tile_image_proto() const noexcept
{
return { atlas, variant };
}
+tile_image_ref::operator bool() const noexcept { return atlas != nullptr; }
+
} // namespace floormat
diff --git a/src/tile-image.hpp b/src/tile-image.hpp
index 033d3916..5a13e13f 100644
--- a/src/tile-image.hpp
+++ b/src/tile-image.hpp
@@ -1,16 +1,20 @@
#pragma once
#include "compat/integer-types.hpp"
+#include <memory>
namespace floormat {
struct tile_atlas;
+using variant_t = std::uint16_t;
+
struct tile_image_proto final
{
std::shared_ptr<tile_atlas> atlas;
- std::uint16_t variant = (std::uint16_t)-1;
+ variant_t variant = (std::uint16_t)-1;
friend bool operator==(const tile_image_proto& a, const tile_image_proto& b) noexcept;
+ operator bool() const noexcept;
};
struct tile_image_ref final
@@ -21,9 +25,9 @@ struct tile_image_ref final
tile_image_ref(std::shared_ptr<tile_atlas>& atlas, std::uint16_t& variant) noexcept;
tile_image_ref(const tile_image_ref&) noexcept;
tile_image_ref(tile_image_ref&&) noexcept;
- tile_image_ref& operator=(tile_image_ref&& tile_rvalue_ref) noexcept;
tile_image_ref& operator=(const tile_image_proto& tile_proto) noexcept;
operator tile_image_proto() const noexcept;
+ operator bool() const noexcept;
};
} // namespace floormat
diff --git a/src/tile-iterator.cpp b/src/tile-iterator.cpp
index 943bbaf8..6dfc5f6d 100644
--- a/src/tile-iterator.cpp
+++ b/src/tile-iterator.cpp
@@ -8,12 +8,12 @@ tile_iterator::tile_iterator(const tile_iterator&) noexcept = default;
tile_iterator& tile_iterator::operator=(const tile_iterator&) noexcept = default;
tile_iterator& tile_iterator::operator++() noexcept { pos++; return *this; }
-tile_iterator tile_iterator::operator++() noexcept { auto it = *this; pos++; return it; }
+tile_iterator tile_iterator::operator++(int) noexcept { auto it = *this; pos++; return it; }
void tile_iterator::swap(tile_iterator& other) noexcept { std::swap(c, other.c); std::swap(pos, other.pos); }
-std::strong_ordering tile_iterator::operator<=>(const tile_iterator&) const noexcept = default;
+bool operator==(const tile_iterator& a, const tile_iterator& b) noexcept { return a.c == b.c && a.pos == b.pos; }
-tile_iterator_tuple tile_iterator::operator->() { return { tile_ref{*c, i}, i, local_coords{i} }; }
-tile_iterator_tuple tile_iterator::operator*() { return { tile_ref{*c, i}, i, local_coords{i} }; }
+tile_iterator_tuple tile_iterator::operator->() noexcept { return { tile_ref{*c, std::uint8_t(pos)}, pos, local_coords{pos} }; }
+tile_iterator_tuple tile_iterator::operator*() noexcept { return { tile_ref{*c, std::uint8_t(pos)}, pos, local_coords{pos} }; }
} // namespace floormat
diff --git a/src/tile-iterator.hpp b/src/tile-iterator.hpp
index 2f860380..5d999716 100644
--- a/src/tile-iterator.hpp
+++ b/src/tile-iterator.hpp
@@ -3,7 +3,6 @@
#include "compat/integer-types.hpp"
#include "local-coords.hpp"
#include "tile.hpp"
-#include <compare>
namespace floormat {
@@ -11,21 +10,22 @@ struct tile_iterator_tuple final { // NOLINT(cppcoreguidelines-pro-type-member-i
const tile_iterator_tuple* operator->() const noexcept { return this; }
tile_iterator_tuple* operator->() noexcept { return this; }
- tile_ref tile;
- std::size_t i;
- local_coords pos;
+ tile_ref x;
+ std::size_t k;
+ local_coords pt;
};
class tile_iterator final {
chunk* c;
std::size_t pos;
+ friend bool operator==(const tile_iterator&, const tile_iterator&) noexcept;
+
public:
explicit tile_iterator(chunk& c, std::size_t pos) noexcept;
tile_iterator(const tile_iterator&) noexcept;
tile_iterator& operator=(const tile_iterator&) noexcept;
- std::strong_ordering operator<=>(const tile_iterator&) const noexcept;
void swap(tile_iterator& other) noexcept;
tile_iterator& operator++() noexcept;
diff --git a/src/tile.cpp b/src/tile.cpp
index 4bf3ae3e..920ee2e5 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -29,27 +29,41 @@ pass_mode_ref::operator pass_mode() const noexcept
return pass_mode(ret);
}
-bool operator==(const tile_proto&, const tile_proto&) noexcept = default;
+bool operator==(const tile_proto& a, const tile_proto& b) noexcept {
+ return a.ground_image() == b.ground_image() &&
+ a.wall_north_image() == b.wall_north_image() &&
+ a.wall_west_image() == b.wall_west_image();
+};
-tile_ref::tile_ref(struct chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{i}
-{
-}
+tile_image_proto tile_proto::ground_image() const noexcept { return { ground_atlas, ground_variant }; }
+tile_image_proto tile_proto::wall_north_image() const noexcept { return { wall_north_atlas, wall_north_variant }; }
+tile_image_proto tile_proto::wall_west_image() const noexcept { return { wall_west_atlas, wall_west_variant }; }
+
+tile_ref::tile_ref(struct chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{i} {}
+
+std::shared_ptr<tile_atlas> tile_ref::ground_atlas() noexcept { return _chunk->_ground_atlases[i]; }
+std::shared_ptr<tile_atlas> tile_ref::wall_north_atlas() noexcept { return _chunk->_wall_north_atlases[i]; }
+std::shared_ptr<tile_atlas> tile_ref::wall_west_atlas() noexcept { return _chunk->_wall_west_atlases[i]; }
+
+std::shared_ptr<const tile_atlas> tile_ref::ground_atlas() const noexcept { return _chunk->_ground_atlases[i]; }
+std::shared_ptr<const tile_atlas> tile_ref::wall_north_atlas() const noexcept { return _chunk->_wall_north_atlases[i]; }
+std::shared_ptr<const tile_atlas> tile_ref::wall_west_atlas() const noexcept { return _chunk->_wall_west_atlases[i]; }
tile_image_ref tile_ref::ground() noexcept { return {_chunk->_ground_atlases[i], _chunk->_ground_variants[i] }; }
tile_image_ref tile_ref::wall_north() noexcept { return {_chunk->_wall_north_atlases[i], _chunk->_wall_north_variants[i] }; }
tile_image_ref tile_ref::wall_west() noexcept { return {_chunk->_wall_west_atlases[i], _chunk->_wall_west_variants[i] }; }
-tile_image_proto tile_ref::ground() const noexcept { return {_chunk->_ground_atlases[i], _chunk->_ground_variants[i] }; }
-tile_image_proto tile_ref::wall_north() const noexcept { return {_chunk->_wall_north_atlases[i], _chunk->_wall_north_variants[i] }; }
-tile_image_proto tile_ref::wall_west() const noexcept { return {_chunk->_wall_west_atlases[i], _chunk->_wall_west_variants[i] }; }
+tile_image_proto tile_ref::ground() const noexcept { return { _chunk->_ground_atlases[i], _chunk->_ground_variants[i] }; }
+tile_image_proto tile_ref::wall_north() const noexcept { return { _chunk->_wall_north_atlases[i], _chunk->_wall_north_variants[i] }; }
+tile_image_proto tile_ref::wall_west() const noexcept { return { _chunk->_wall_west_atlases[i], _chunk->_wall_west_variants[i] }; }
pass_mode_ref tile_ref::pass_mode() noexcept { return { *_chunk, i }; }
-pass_mode tile_ref::pass_mode() const noexcept { return pass_mode_ref { *const_cast<chunk*>(_chunk), i }; }
+pass_mode tile_ref::pass_mode() const noexcept { return pass_mode_ref { *const_cast<struct chunk*>(_chunk), i }; }
tile_ref::operator tile_proto() const noexcept
{
return {
- _chunk->_ground_atlases[i], _chunk->_wall_north_atlases[i], _chunk->_wall_west_atlases[i],
+ _chunk->_ground_atlases[i], _chunk->_wall_north_atlases[i], _chunk->_wall_west_atlases[i],
_chunk->_ground_variants[i], _chunk->_wall_north_variants[i], _chunk->_wall_west_variants[i],
pass_mode(),
};
diff --git a/src/tile.hpp b/src/tile.hpp
index 4bfeb84a..8061035f 100644
--- a/src/tile.hpp
+++ b/src/tile.hpp
@@ -6,7 +6,8 @@ namespace floormat {
struct chunk;
-enum pass_mode : std::uint8_t { pass_ok, pass_blocked, pass_shoot_through, };
+// zero is the default, see bitset in chunk.hpp
+enum pass_mode : std::uint8_t { pass_shoot_through, pass_ok, pass_blocked, };
struct pass_mode_ref final
{
@@ -26,6 +27,10 @@ struct tile_proto final
std::uint16_t ground_variant = 0xffff, wall_north_variant = 0xffff, wall_west_variant = 0xffff;
pass_mode pass_mode = pass_mode::pass_shoot_through;
+ tile_image_proto ground_image() const noexcept;
+ tile_image_proto wall_north_image() const noexcept;
+ tile_image_proto wall_west_image() const noexcept;
+
friend bool operator==(const tile_proto& a, const tile_proto& b) noexcept;
};
@@ -41,6 +46,14 @@ struct tile_ref final
tile_image_proto wall_north() const noexcept;
tile_image_proto wall_west() const noexcept;
+ std::shared_ptr<tile_atlas> ground_atlas() noexcept;
+ std::shared_ptr<tile_atlas> wall_north_atlas() noexcept;
+ std::shared_ptr<tile_atlas> wall_west_atlas() noexcept;
+
+ std::shared_ptr<const tile_atlas> ground_atlas() const noexcept;
+ std::shared_ptr<const tile_atlas> wall_north_atlas() const noexcept;
+ std::shared_ptr<const tile_atlas> wall_west_atlas() const noexcept;
+
pass_mode_ref pass_mode() noexcept;
enum pass_mode pass_mode() const noexcept;
diff --git a/src/world.hpp b/src/world.hpp
index ae7b6240..9b58ff3d 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -29,7 +29,7 @@ private:
public:
explicit world();
- struct pair final { chunk& c; tile& t; }; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
+ struct pair final { chunk& c; tile_ref t; };
template<typename Hash, typename Alloc, typename Pred>
explicit world(std::unordered_map<chunk_coords, chunk, Hash, Alloc, Pred>&& chunks);
diff --git a/test/json.cpp b/test/json.cpp
index 927e7355..0cb65278 100644
--- a/test/json.cpp
+++ b/test/json.cpp
@@ -19,14 +19,14 @@ static chunk make_test_chunk()
tiles = loader.tile_atlas("tiles", {8, 5});
constexpr auto N = TILE_MAX_DIM;
chunk c;
- for (auto& [x, k, pt] : c) {
- x.ground = { tiles, decltype(tile_image::variant)(k % tiles->num_tiles()) };
+ for (auto [x, k, pt] : c) {
+ x.ground() = { tiles, variant_t(k % tiles->num_tiles()) };
}
constexpr auto K = N/2;
- c[{K, K }].wall_north = { metal1, 0 };
- c[{K, K }].wall_west = { metal2, 0 };
- c[{K, K+1}].wall_north = { metal1, 0 };
- c[{K+1, K }].wall_west = { metal2, 0 };
+ c[{K, K }].wall_north() = { metal1, 0 };
+ c[{K, K }].wall_west() = { metal2, 0 };
+ c[{K, K+1}].wall_north() = { metal1, 0 };
+ c[{K+1, K }].wall_west() = { metal2, 0 };
return c;
}
diff --git a/test/serializer.cpp b/test/serializer.cpp
index db08a9f8..c1ab5fef 100644
--- a/test/serializer.cpp
+++ b/test/serializer.cpp
@@ -15,14 +15,14 @@ static chunk make_test_chunk()
tiles = loader.tile_atlas("tiles", {8, 5});
constexpr auto N = TILE_MAX_DIM;
chunk c;
- for (auto& [x, k, pt] : c) {
- x.ground = { tiles, decltype(tile_image::variant)(k % tiles->num_tiles()) };
+ for (auto [x, k, pt] : c) {
+ x.ground() = { tiles, variant_t(k % tiles->num_tiles()) };
}
constexpr auto K = N/2;
- c[{K, K }].wall_north = { metal1, 0 };
- c[{K, K }].wall_west = { metal2, 0 };
- c[{K, K+1}].wall_north = { metal1, 0 };
- c[{K+1, K }].wall_west = { metal2, 0 };
+ c[{K, K }].wall_north() = { metal1, 0 };
+ c[{K, K }].wall_west() = { metal2, 0 };
+ c[{K, K+1}].wall_north() = { metal1, 0 };
+ c[{K+1, K }].wall_west() = { metal2, 0 };
return c;
}
diff --git a/test/tile-iter.cpp b/test/tile-iter.cpp
index 9303a764..6bfd1a0b 100644
--- a/test/tile-iter.cpp
+++ b/test/tile-iter.cpp
@@ -10,6 +10,7 @@ static inline bool always_false()
bool floormat::test_tile_iter() // NOLINT(readability-function-size)
{
+#if 0
if (always_false())
{
const chunk c;
@@ -22,23 +23,18 @@ bool floormat::test_tile_iter() // NOLINT(readability-function-size)
for (auto&& [x, k, pt] : c)
static_assert(std::is_same_v<decltype(x), const tile&>);
}
+#endif
if (always_false())
{
chunk c;
- for (auto& [x, k, pt] : c)
- static_assert(std::is_same_v<decltype(x), tile&>);
- for (const auto& [x, k, pt] : c)
- static_assert(std::is_same_v<decltype(x), const tile&>);
for (auto [x, k, pt] : c)
- static_assert(std::is_same_v<decltype(x), tile&>);
+ static_assert(std::is_same_v<decltype(x), tile_ref>);
#if 0
// warns
for (const auto [x, k, pt] : c)
static_assert(std::is_same_v<decltype(x), const tile&>);
-#endif
for (auto&& [x, k, pt] : c)
static_assert(std::is_same_v<decltype(x), tile&>);
-#if 0
// fails to compile
for (const auto&& [x, k, pt] : c)
static_assert(std::is_same_v<decltype(x), const tile&>);