diff options
-rw-r--r-- | draw/floor.hpp | 3 | ||||
-rw-r--r-- | src/chunk.hpp | 17 | ||||
-rw-r--r-- | src/tile-image.cpp | 29 | ||||
-rw-r--r-- | src/tile-image.hpp | 19 | ||||
-rw-r--r-- | src/tile-iterator.cpp | 12 | ||||
-rw-r--r-- | src/tile-iterator.hpp | 99 | ||||
-rw-r--r-- | src/tile.cpp | 66 | ||||
-rw-r--r-- | src/tile.hpp | 54 |
8 files changed, 194 insertions, 105 deletions
diff --git a/draw/floor.hpp b/draw/floor.hpp index f81a7593..4a273dfc 100644 --- a/draw/floor.hpp +++ b/draw/floor.hpp @@ -12,7 +12,8 @@ namespace floormat { struct tile_shader; struct chunk; -struct tile; +struct tile_ref; +struct tile_proto; struct floor_mesh final { diff --git a/src/chunk.hpp b/src/chunk.hpp index 3bf66920..5ffc1680 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -3,29 +3,40 @@ #include "tile-iterator.hpp" #include <type_traits> #include <array> +#include <bitset> namespace floormat { template<typename T> class basic_tile_iterator; +struct tile_ref; +struct pass_mode_ref; + 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 using iterator = basic_tile_iterator<tile>; using const_iterator = basic_tile_iterator<const tile>; +#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 bool empty(bool force = false) const noexcept; @@ -35,7 +46,11 @@ struct chunk final fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(chunk); private: - std::array<tile, TILE_COUNT> _tiles = {}; + 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; mutable bool _maybe_empty = true; }; diff --git a/src/tile-image.cpp b/src/tile-image.cpp index 784bd4f5..c9dc24f4 100644 --- a/src/tile-image.cpp +++ b/src/tile-image.cpp @@ -2,10 +2,33 @@ namespace floormat { -bool operator==(const tile_image& a, const tile_image& b) noexcept +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} { - return a.atlas == b.atlas && a.variant == b.variant; } -} // namespace floormat +tile_image_ref& tile_image_ref::operator=(tile_image_ref&& ref) noexcept +{ + atlas = ref.atlas; + variant = ref.variant; + return *this; +} + +tile_image_ref& tile_image_ref::operator=(const tile_image_proto& proto) noexcept +{ + atlas = proto.atlas; + variant = proto.variant; + return *this; +} + +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 }; +} +} // namespace floormat diff --git a/src/tile-image.hpp b/src/tile-image.hpp index 79a0bacc..033d3916 100644 --- a/src/tile-image.hpp +++ b/src/tile-image.hpp @@ -1,20 +1,29 @@ #pragma once #include "compat/integer-types.hpp" -#include <compare> -#include <memory> namespace floormat { struct tile_atlas; -struct tile_image final +struct tile_image_proto final { std::shared_ptr<tile_atlas> atlas; std::uint16_t variant = (std::uint16_t)-1; - explicit operator bool() const noexcept { return !!atlas; } + friend bool operator==(const tile_image_proto& a, const tile_image_proto& b) noexcept; }; -bool operator==(const tile_image& a, const tile_image& b) noexcept; +struct tile_image_ref final +{ + std::shared_ptr<tile_atlas>& atlas; + std::uint16_t& variant; + + 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; +}; } // namespace floormat diff --git a/src/tile-iterator.cpp b/src/tile-iterator.cpp index 97e34008..b454576a 100644 --- a/src/tile-iterator.cpp +++ b/src/tile-iterator.cpp @@ -3,7 +3,15 @@ namespace floormat { -template class basic_tile_iterator<tile>; -template class basic_tile_iterator<const tile>; +basic_tile_iterator::basic_tile_iterator(chunk& c, std::size_t pos) noexcept : + c{&c}, pos{pos} +{ +} + +basic_tile_iterator::basic_tile_iterator(const basic_tile_iterator&) noexcept = default; +basic_tile_iterator& basic_tile_iterator::operator=(const basic_tile_iterator&) noexcept = default; +std::strong_ordering basic_tile_iterator::operator<=>(const basic_tile_iterator&) const noexcept = default; +void basic_tile_iterator::swap(basic_tile_iterator& other) { std::swap(c, other.c); std::swap(pos, other.pos); } + } // namespace floormat diff --git a/src/tile-iterator.hpp b/src/tile-iterator.hpp index 20191afa..91d85cad 100644 --- a/src/tile-iterator.hpp +++ b/src/tile-iterator.hpp @@ -1,6 +1,7 @@ #pragma once #include "local-coords.hpp" +#include "tile.hpp" #include <iterator> #include <tuple> #include <utility> @@ -8,94 +9,32 @@ namespace floormat { -struct tile; -template<typename T> class basic_tile_iterator; -template<typename T> struct tile_tuple; +struct tile_tuple final { + const tile_tuple* operator->() const noexcept { return this; } + tile_tuple* operator->() noexcept { return this; } -} // namespace floormat - -namespace std { - -template<typename T> struct tuple_size<floormat::tile_tuple<T>> : std::integral_constant<std::size_t, 3> {}; - -template<> struct tuple_element<0, floormat::tile_tuple<floormat::tile>> { using type = floormat::tile&; }; -template<> struct tuple_element<0, floormat::tile_tuple<const floormat::tile>> { using type = const floormat::tile&; }; -template<> struct tuple_element<0, const floormat::tile_tuple<floormat::tile>> { using type = const floormat::tile&; }; - -template<typename T> struct tuple_element<1, floormat::tile_tuple<T>> { using type = std::size_t; }; -template<typename T> struct tuple_element<2, floormat::tile_tuple<T>> { using type = floormat::local_coords; }; - -} // namespace std - -namespace floormat { - -template<typename T> -struct tile_tuple { - tile_tuple(T* ptr, std::size_t pos) : data{ptr, pos} {} - tile_tuple(const tile_tuple<T>&) = default; - tile_tuple<T>& operator=(const tile_tuple<T>&) = default; - - template <std::size_t N> - typename std::tuple_element<N, tile_tuple<T>>::type get() - { - auto& [ptr, pos] = data; - if constexpr(N == 0) - return ptr[pos]; - else if constexpr(N == 1) - return pos; - else if constexpr(N == 2) - return local_coords{pos}; - else - return std::void_t<std::integral_constant<int, N>>(); - } - - template <std::size_t N> - typename std::tuple_element<N, const tile_tuple<const T>>::type get() const { - return const_cast<tile_tuple<T>&>(*this).get<N>(); - } - - auto operator<=>(const tile_tuple<T>&) const noexcept = default; - -protected: - std::tuple<T*, std::size_t> data = {nullptr, 0}; + tile_ref tile; + std::size_t i; + local_coords pos; }; -} // namespace floormat - -namespace floormat { +class basic_tile_iterator final { + chunk* c; + std::size_t pos; -template<typename T> -class basic_tile_iterator final : private tile_tuple<T> { public: - explicit basic_tile_iterator(T* ptr, std::size_t pos) noexcept : tile_tuple<T>{ptr, pos} {} - basic_tile_iterator(const basic_tile_iterator&) = default; - basic_tile_iterator<T>& operator=(const basic_tile_iterator<T>&) = default; + explicit basic_tile_iterator(chunk& c, std::size_t pos) noexcept; + basic_tile_iterator(const basic_tile_iterator&) noexcept; + basic_tile_iterator& operator=(const basic_tile_iterator&) noexcept; - auto operator<=>(const basic_tile_iterator<T>&) const noexcept = default; - void swap(basic_tile_iterator<T>& other) { std::swap(this->data, other.data); } + std::strong_ordering operator<=>(const basic_tile_iterator&) const noexcept; + void swap(basic_tile_iterator& other); - basic_tile_iterator<T>& operator++() { auto& [ptr, pos] = this->data; pos++; return *this; } - basic_tile_iterator<T> operator++(int) { auto tmp = *this; operator++(); return tmp; } - tile_tuple<T>* operator->() { return this; } - tile_tuple<T>& operator*() { return *this; } + basic_tile_iterator& operator++(); + basic_tile_iterator operator++(int); + tile_tuple operator->(); + tile_tuple operator*(); }; -extern template class basic_tile_iterator<tile>; -extern template class basic_tile_iterator<const tile>; - } // namespace floormat -namespace std { - -template<typename Tile> -class iterator_traits<floormat::basic_tile_iterator<Tile>> { - using T = floormat::basic_tile_iterator<Tile>; -public: - using difference_type = std::ptrdiff_t; - using value_type = T; - using reference = T&; - using pointer = T*; - using iterator_category = std::input_iterator_tag; //usually std::forward_iterator_tag or similar -}; - -} // namespace std diff --git a/src/tile.cpp b/src/tile.cpp index 7e988a27..4bf3ae3e 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -1,13 +1,69 @@ #include "tile.hpp" +#include "chunk.hpp" namespace floormat { -bool operator==(const tile& a, const tile& b) noexcept +pass_mode_ref::pass_mode_ref(chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{i} { - return a.ground == b.ground && - a.wall_north == b.wall_north && - a.wall_west == b.wall_west && - a.passability == b.passability; +} + +pass_mode_ref& pass_mode_ref::operator=(pass_mode x) noexcept +{ + auto& bitset = _chunk->_passability; + bitset[i*2 + 0] = x & 1; + bitset[i*2 + 1] = x >> 1 & 1; + return *this; +} + +pass_mode_ref& pass_mode_ref::operator=(const pass_mode_ref& x) noexcept +{ + return operator=(pass_mode(x)); // NOLINT(misc-unconventional-assign-operator) +} + +pass_mode_ref::operator pass_mode() const noexcept +{ + auto& bitset = _chunk->_passability; + std::uint8_t ret = 0; + ret |= (std::uint8_t)bitset[i*2 + 1]; + ret |= (std::uint8_t)bitset[i*2 + 0] << 1; + return pass_mode(ret); +} + +bool operator==(const tile_proto&, const tile_proto&) noexcept = default; + +tile_ref::tile_ref(struct chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{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] }; } + +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 }; } + +tile_ref::operator tile_proto() const noexcept +{ + return { + _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(), + }; +} + +bool operator==(const tile_ref& a, const tile_ref& b) noexcept +{ + if (a._chunk == b._chunk && a.i == b.i) + return true; + else + return a.ground() == b.ground() && + a.wall_north() == b.wall_north() && + a.wall_west() == b.wall_west() && + a.pass_mode() == b.pass_mode(); } } // namespace floormat diff --git a/src/tile.hpp b/src/tile.hpp index 52d06b9d..4bfeb84a 100644 --- a/src/tile.hpp +++ b/src/tile.hpp @@ -4,19 +4,57 @@ namespace floormat { -struct tile final +struct chunk; + +enum pass_mode : std::uint8_t { pass_ok, pass_blocked, pass_shoot_through, }; + +struct pass_mode_ref final { - enum pass_mode : std::uint8_t { pass_ok, pass_blocked, pass_shoot_through, }; + pass_mode_ref(chunk& c, std::uint8_t i) noexcept; + pass_mode_ref& operator=(pass_mode x) noexcept; + pass_mode_ref& operator=(const pass_mode_ref& x) noexcept; + operator pass_mode() const noexcept; - tile_image ground, wall_north, wall_west; - pass_mode passability = pass_ok; +private: + chunk* _chunk; + std::uint8_t i; +}; - constexpr tile() = default; +struct tile_proto final +{ + std::shared_ptr<tile_atlas> ground_atlas, wall_north_atlas, wall_west_atlas; + std::uint16_t ground_variant = 0xffff, wall_north_variant = 0xffff, wall_west_variant = 0xffff; + pass_mode pass_mode = pass_mode::pass_shoot_through; - fm_DECLARE_DEPRECATED_COPY_ASSIGNMENT(tile); - fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(tile); + friend bool operator==(const tile_proto& a, const tile_proto& b) noexcept; }; -bool operator==(const tile& a, const tile& b) noexcept; +struct tile_ref final +{ + tile_ref(struct chunk& c, std::uint8_t i) noexcept; + + tile_image_ref ground() noexcept; + tile_image_ref wall_north() noexcept; + tile_image_ref wall_west() noexcept; + + tile_image_proto ground() const noexcept; + tile_image_proto wall_north() const noexcept; + tile_image_proto wall_west() const noexcept; + + pass_mode_ref pass_mode() noexcept; + enum pass_mode pass_mode() const noexcept; + + explicit operator tile_proto() const noexcept; + + struct chunk& chunk() noexcept { return *_chunk; } + const struct chunk& chunk() const noexcept { return *_chunk; } + std::size_t index() const noexcept { return i; } + + friend bool operator==(const tile_ref& a, const tile_ref& b) noexcept; + +private: + struct chunk* _chunk; + std::uint8_t i; +}; } //namespace floormat |