#pragma once #include #include #include "common/Vec2.h" constexpr size_t DynamicExtent = std::numeric_limits::max(); template struct extentStorage { constexpr extentStorage(size_t) {} constexpr size_t getExtent() const { return Extent; } constexpr void setExtent(size_t) {} }; template<> struct extentStorage { size_t extent; constexpr extentStorage(size_t extent): extent(extent) {} constexpr size_t getExtent() const { return extent; } constexpr void setExtent(size_t extent) { this->extent = extent; } }; template struct xExtent: extentStorage { using extentStorage::extentStorage; }; template struct yExtent: extentStorage { using extentStorage::extentStorage; }; // A class that contains some container T and lets you index into it as if it // were a 2D array of size Width x Height, in row-major order. template class PlaneAdapter: xExtent, yExtent { friend class VideoBuffer; // TODO: remove using value_type = std::remove_reference_t()[0])>; using iterator = decltype(std::begin(std::declval())); using const_iterator = decltype(std::begin(std::declval())); size_t getWidth() const { return xExtent::getExtent(); } size_t getHeight() const { return yExtent::getExtent(); } public: T Base; PlaneAdapter(): xExtent(0), yExtent(0), Base() {} PlaneAdapter(PlaneAdapter const &) = default; PlaneAdapter(PlaneAdapter &&) = default; // PlaneAdapter can be constructed from (Vec2, T &&) // PlaneAdapter can be constructed from (Vec2, T &) PlaneAdapter(Vec2 size, T &&base): xExtent(size.X), yExtent(size.Y), Base(std::forward(base)) {} template PlaneAdapter(Vec2 size, Args&&... args): xExtent(size.X), yExtent(size.Y), Base(getWidth() * getHeight(), std::forward(args)...) {} PlaneAdapter &operator=(PlaneAdapter const &) = default; PlaneAdapter &operator=(PlaneAdapter &&) = default; Vec2 Size() const { return Vec2(getWidth(), getHeight()); } void SetSize(Vec2 size) { xExtent::setExtent(size.X); yExtent::setExtent(size.Y); } iterator RowIterator(Vec2 p) { return std::begin(Base) + (p.X + p.Y * getWidth()); } const_iterator RowIterator(Vec2 p) const { return std::begin(Base) + (p.X + p.Y * getWidth()); } value_type *data() { return std::data(Base); } value_type const *data() const { return std::data(Base); } value_type &operator[](Vec2 p) { return Base[p.X + p.Y * getWidth()]; } value_type const &operator[](Vec2 p) const { return Base[p.X + p.Y * getWidth()]; } };