summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/chunk.hpp17
-rw-r--r--src/floor-mesh.hpp4
-rw-r--r--src/local-coords.hpp32
-rw-r--r--src/tile-atlas.hpp2
-rw-r--r--src/tile-defs.hpp9
-rw-r--r--src/tile-iterator.cpp8
-rw-r--r--src/tile-iterator.hpp96
-rw-r--r--src/tile.cpp2
-rw-r--r--src/tile.hpp26
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