diff options
-rw-r--r-- | src/chunk.hpp | 17 | ||||
-rw-r--r-- | src/floor-mesh.hpp | 4 | ||||
-rw-r--r-- | src/local-coords.hpp | 32 | ||||
-rw-r--r-- | src/tile-atlas.hpp | 2 | ||||
-rw-r--r-- | src/tile-defs.hpp | 9 | ||||
-rw-r--r-- | src/tile-iterator.cpp | 8 | ||||
-rw-r--r-- | src/tile-iterator.hpp | 96 | ||||
-rw-r--r-- | src/tile.cpp | 2 | ||||
-rw-r--r-- | src/tile.hpp | 26 |
9 files changed, 165 insertions, 31 deletions
diff --git a/src/chunk.hpp b/src/chunk.hpp index 6c3706b8..a22dc025 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -1,15 +1,18 @@ #pragma once #include "tile.hpp" +#include "tile-iterator.hpp" #include <type_traits> #include <array> namespace Magnum::Examples { template<typename F, typename Tile> -concept tile_iterator = requires(F fn, Tile& tile) { +concept tile_iterator_fn = requires(F fn, Tile& tile) { { fn.operator()(tile, std::size_t{}, local_coords{}) } -> std::same_as<void>; }; +template<typename T> class basic_tile_iterator; + struct chunk final { constexpr tile& operator[](local_coords xy) { return _tiles[xy.to_index()]; } @@ -19,16 +22,24 @@ struct chunk final const auto& tiles() const { return _tiles; } auto& tiles() { return _tiles; } - template<tile_iterator<tile&> F> + template<tile_iterator_fn<tile&> F> constexpr inline void foreach_tile(F&& fun) { foreach_tile_<F, chunk&>(std::forward<F>(fun)); } - template<tile_iterator<const tile&> F> + template<tile_iterator_fn<const tile&> F> constexpr inline void foreach_const_tile(F&& fun) const { const_cast<chunk*>(this)->foreach_tile_<F, const chunk&>(std::forward<F>(fun)); } + using iterator = basic_tile_iterator<tile>; + using const_iterator = basic_tile_iterator<const tile>; + + constexpr iterator begin() { return iterator{_tiles.data(), 0}; } + constexpr iterator end() { return iterator{_tiles.data(), _tiles.size()}; } + constexpr const_iterator cbegin() const { return const_iterator{_tiles.data(), 0}; } + constexpr const_iterator cend() { return const_iterator{_tiles.data(), _tiles.size()}; } + private: template<typename F, typename Self> constexpr void foreach_tile_(F&& fun); diff --git a/src/floor-mesh.hpp b/src/floor-mesh.hpp index 41351fd9..fed5867c 100644 --- a/src/floor-mesh.hpp +++ b/src/floor-mesh.hpp @@ -1,9 +1,10 @@ #pragma once -#include "tile.hpp" +#include "tile-defs.hpp" #include <array> #include <Corrade/Containers/ArrayViewStl.h> #include <Magnum/Magnum.h> #include <Magnum/Math/Vector2.h> +#include <Magnum/Math/Vector3.h> #include <Magnum/GL/Mesh.h> #include <Magnum/GL/Buffer.h> @@ -11,6 +12,7 @@ namespace Magnum::Examples { struct tile_shader; struct chunk; +struct tile; struct floor_mesh final { diff --git a/src/local-coords.hpp b/src/local-coords.hpp new file mode 100644 index 00000000..d2520a42 --- /dev/null +++ b/src/local-coords.hpp @@ -0,0 +1,32 @@ +#pragma once +#include "compat/assert.hpp" +#include "tile-defs.hpp" +#include <cstdint> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector3.h> + +namespace Magnum::Examples { + +struct local_coords final { + std::uint8_t x = 0, y = 0; + explicit constexpr local_coords(std::size_t idx); + constexpr local_coords() = default; + constexpr local_coords(std::size_t x, std::size_t y); + constexpr local_coords(std::uint8_t x, std::uint8_t y) : x{x}, y{y} {} + constexpr std::size_t to_index() const { return y*TILE_MAX_DIM + x; } +}; + +constexpr local_coords::local_coords(std::size_t index) : + x{(std::uint8_t)(index % TILE_MAX_DIM)}, + y{(std::uint8_t)(index / TILE_MAX_DIM)} +{ + ASSERT(index < TILE_COUNT); +} + +constexpr local_coords::local_coords(std::size_t x, std::size_t y) + : x{(std::uint8_t)x}, y{(std::uint8_t)y} +{ + ASSERT(x <= 0xff && y <= 0xff); +} + +} // namespace Magnum::Examples diff --git a/src/tile-atlas.hpp b/src/tile-atlas.hpp index af9e505b..2d3461cc 100644 --- a/src/tile-atlas.hpp +++ b/src/tile-atlas.hpp @@ -8,6 +8,8 @@ namespace std::filesystem { class path; } namespace Magnum::Examples { +constexpr inline Vector3 TILE_SIZE = { 64, 64, 64 }; + struct tile_atlas final { using quad = std::array<Vector3, 4>; diff --git a/src/tile-defs.hpp b/src/tile-defs.hpp new file mode 100644 index 00000000..40d1809b --- /dev/null +++ b/src/tile-defs.hpp @@ -0,0 +1,9 @@ +#pragma once +#include <cstddef> + +namespace Magnum::Examples { + +constexpr inline std::size_t TILE_MAX_DIM = 16; +constexpr inline std::size_t TILE_COUNT = TILE_MAX_DIM*TILE_MAX_DIM; + +} // namespace Magnum::Examples diff --git a/src/tile-iterator.cpp b/src/tile-iterator.cpp new file mode 100644 index 00000000..ea98a6ee --- /dev/null +++ b/src/tile-iterator.cpp @@ -0,0 +1,8 @@ +#include "tile-iterator.hpp" + +namespace Magnum::Examples { + +template class basic_tile_iterator<tile>; +template class basic_tile_iterator<const tile>; + +} // namespace Magnum::Examples diff --git a/src/tile-iterator.hpp b/src/tile-iterator.hpp new file mode 100644 index 00000000..a0ffa11c --- /dev/null +++ b/src/tile-iterator.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include "local-coords.hpp" +#include "tile.hpp" +#include <iterator> +#include <tuple> +#include <utility> +#include <type_traits> + +namespace Magnum::Examples { + +template<typename T> +class basic_tile_iterator; + +struct tile; + +} // namespace Magnum::Examples + +namespace std { + +template<typename T> +constexpr void swap(Magnum::Examples::basic_tile_iterator<T>& lhs, + Magnum::Examples::basic_tile_iterator<T>& rhs) noexcept; + +} // namespace std + +namespace Magnum::Examples { + +namespace detail { + +template<typename T> +class tile_tuple_wrapper final { + using value_type = std::tuple<T&, std::size_t, local_coords>; + value_type value; + +public: + constexpr tile_tuple_wrapper(value_type x) : value(x) {} + constexpr value_type& operator*() noexcept { return value; } + constexpr value_type* operator->() noexcept { return &value; } +}; + +} // namespace detail + +template<typename T> +class basic_tile_iterator final { + T* ptr; + std::size_t pos = 0; + + friend constexpr void swap(basic_tile_iterator<T>& lhs, basic_tile_iterator<T>& rhs) noexcept; + +public: + using value_type = std::tuple<T&, std::size_t, local_coords>; + + explicit constexpr basic_tile_iterator(T* ptr, std::size_t pos) noexcept : ptr(ptr), pos(pos) {} + constexpr ~basic_tile_iterator() noexcept = default; + + constexpr basic_tile_iterator<T>& operator=(const basic_tile_iterator<T>&) noexcept = default; + constexpr basic_tile_iterator<T>& operator++() noexcept { pos++; return *this; } + constexpr basic_tile_iterator<T> operator++(int) noexcept { auto tmp = *this; operator++(); return tmp; } + constexpr value_type operator*() const noexcept { // NOLINT(bugprone-exception-escape) + ASSERT(pos < TILE_COUNT); + return {ptr[pos], pos, local_coords{pos}}; + } + constexpr detail::tile_tuple_wrapper<T> operator->() const noexcept { // NOLINT(bugprone-exception-escape) + return {operator*()}; + } + constexpr auto operator<=>(const basic_tile_iterator<T>&) const noexcept = default; +}; + +template<typename T> +constexpr void swap(basic_tile_iterator<T>& lhs, basic_tile_iterator<T>& rhs) noexcept +{ + using std::swap; + swap(lhs.ptr, rhs.ptr); + swap(lhs.pos, rhs.ptr); +} + +extern template class basic_tile_iterator<tile>; +extern template class basic_tile_iterator<const tile>; + +} // namespace Magnum::Examples + +namespace std { + +template<typename Tile> +class iterator_traits<Magnum::Examples::basic_tile_iterator<Tile>> { + using T = typename Magnum::Examples::basic_tile_iterator<Tile>::value_type; +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 fe0e2da3..b1963415 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -2,6 +2,4 @@ namespace Magnum::Examples { - - } // namespace Magnum::Examples diff --git a/src/tile.hpp b/src/tile.hpp index f559ce79..d607a2d3 100644 --- a/src/tile.hpp +++ b/src/tile.hpp @@ -1,18 +1,15 @@ #pragma once #include "compat/defs.hpp" #include "compat/assert.hpp" +#include "tile-defs.hpp" #include <Magnum/Magnum.h> #include <Magnum/Math/Vector3.h> -#include <cstddef> #include <cstdint> #include <memory> namespace Magnum::Examples { struct tile_atlas; -constexpr inline Vector3 TILE_SIZE = { 64, 64, 64 }; -constexpr inline std::size_t TILE_MAX_DIM = 16; -constexpr inline std::size_t TILE_COUNT = TILE_MAX_DIM*TILE_MAX_DIM; struct tile_image final { @@ -34,25 +31,4 @@ struct tile final DECLARE_DEPRECATED_COPY_OPERATOR(tile); }; -struct local_coords final { - std::uint8_t x = 0, y = 0; - explicit constexpr local_coords(std::size_t idx); - constexpr local_coords() = default; - constexpr local_coords(std::size_t x, std::size_t y); - constexpr local_coords(std::uint8_t x, std::uint8_t y) : x{x}, y{y} {} - constexpr std::size_t to_index() const { return y*TILE_MAX_DIM + x; } -}; - -constexpr local_coords::local_coords(std::size_t index) : - x{(std::uint8_t)(index % TILE_MAX_DIM)}, - y{(std::uint8_t)(index / TILE_MAX_DIM)} -{ -} - -constexpr local_coords::local_coords(std::size_t x, std::size_t y) - : x{(std::uint8_t)x}, y{(std::uint8_t)y} -{ - ASSERT(x <= 0xff && y <= 0xff); -} - } //namespace Magnum::Examples |