Refactoring in map reading code - part 1/2
Fixed a bug when iterating over a view that was smaller than the map size Added a class to abstract map readers
This commit is contained in:
parent
a6afd2eb54
commit
436d738620
12 changed files with 292 additions and 145 deletions
|
@ -21,7 +21,7 @@ namespace dk {
|
||||||
LayerBase ( const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize );
|
LayerBase ( const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize );
|
||||||
virtual ~LayerBase ( void ) noexcept = default;
|
virtual ~LayerBase ( void ) noexcept = default;
|
||||||
|
|
||||||
virtual void preload ( const coords& parFrom, const coords& parTo ) = 0;
|
void preload ( const coords& parFrom, const coords& parTo );
|
||||||
coords count ( void ) const { return m_mastersize / m_tilesize * m_count; }
|
coords count ( void ) const { return m_mastersize / m_tilesize * m_count; }
|
||||||
const coords& mapSize ( void ) const { return m_count; }
|
const coords& mapSize ( void ) const { return m_count; }
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@ namespace dk {
|
||||||
coords m_mastersize;
|
coords m_mastersize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual void onPreload ( const coords& parFrom, const coords& parTo ) = 0;
|
||||||
|
|
||||||
|
coords m_haveFrom;
|
||||||
|
coords m_haveTo;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t D>
|
template <typename T, size_t D>
|
||||||
|
@ -51,9 +55,10 @@ namespace dk {
|
||||||
|
|
||||||
iterator begin ( void );
|
iterator begin ( void );
|
||||||
iterator end ( void );
|
iterator end ( void );
|
||||||
virtual void preload ( const coords& parFrom, const coords& parTo );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual void onPreload ( const coords& parFrom, const coords& parTo );
|
||||||
|
|
||||||
std::vector<T> m_tiles;
|
std::vector<T> m_tiles;
|
||||||
TileMapData<T, D>& m_tilemap;
|
TileMapData<T, D>& m_tilemap;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,60 +5,27 @@
|
||||||
#include "implem/compatibility.h"
|
#include "implem/compatibility.h"
|
||||||
#include "implem/vector.hpp"
|
#include "implem/vector.hpp"
|
||||||
#include "implem/helpers.hpp"
|
#include "implem/helpers.hpp"
|
||||||
|
#include "mapreaders/mapstreambase.hpp"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <type_traits>
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace dk {
|
namespace dk {
|
||||||
namespace implem {
|
|
||||||
template <typename T>
|
|
||||||
class HasMapDimensions {
|
|
||||||
class yes { char m; };
|
|
||||||
class nope { yes m[2]; };
|
|
||||||
static yes deduce ( int a, int b = T::MapDimensions );
|
|
||||||
static nope deduce ( ... );
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
result = (sizeof(yes) == sizeof(deduce(1)))
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<Device::MapDimensions == D, std::size_t>::type err_mismatching_dimension ( const Device* ) noexcept a_pure;
|
|
||||||
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<HasMapDimensions<Device>::result == false, std::size_t>::type err_mismatching_dimension ( const Device* ) noexcept a_pure;
|
|
||||||
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<Device::MapDimensions == D, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device ( Device* parDevice );
|
|
||||||
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<HasMapDimensions<Device>::result == false, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device ( Device* parDevice );
|
|
||||||
} //namespace implem
|
|
||||||
|
|
||||||
//Customization point - specialize to enable map size retrieval for Device
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename Device::coords get_map_size_from_device ( const Device* parDevice );
|
|
||||||
|
|
||||||
template <typename T, std::size_t D>
|
template <typename T, std::size_t D>
|
||||||
class TileMapData {
|
class TileMapData {
|
||||||
public:
|
public:
|
||||||
typedef Vector<CoordinateScalarType, D> coords;
|
typedef Vector<CoordinateScalarType, D> coords;
|
||||||
|
|
||||||
TileMapData ( void ) = delete;
|
TileMapData ( void ) = delete;
|
||||||
template <typename Device>
|
explicit TileMapData ( std::unique_ptr<MapStreamBase<D>>&& parStream );
|
||||||
explicit TileMapData ( Device& parDevice );
|
|
||||||
//TODO: add an overload to initialize a TileMapData from a universal reference to std::istream
|
|
||||||
~TileMapData ( void ) noexcept = default;
|
~TileMapData ( void ) noexcept = default;
|
||||||
|
|
||||||
bool streamHasDimensionInfo ( void ) const { return m_deviceHasDim; }
|
|
||||||
void fetch ( std::vector<T>& parOut, const coords& parFrom, const coords& parTo );
|
void fetch ( std::vector<T>& parOut, const coords& parFrom, const coords& parTo );
|
||||||
const coords& mapSize ( void ) const;
|
const coords& mapSize ( void ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::istream m_stream;
|
const std::unique_ptr<MapStreamBase<D>> m_mapstream;
|
||||||
const coords m_mapSize;
|
|
||||||
const bool m_deviceHasDim;
|
|
||||||
};
|
};
|
||||||
} //namespace dk
|
} //namespace dk
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace dk {
|
||||||
public:
|
public:
|
||||||
typedef Vector<CoordinateScalarType, D> coords;
|
typedef Vector<CoordinateScalarType, D> coords;
|
||||||
|
|
||||||
|
Viewport ( const Viewport& parOther ) = default;
|
||||||
explicit Viewport ( Tyler<D>& parTyler );
|
explicit Viewport ( Tyler<D>& parTyler );
|
||||||
Viewport ( Tyler<D>& parTyler, const coords& parSize, const coords& parPos );
|
Viewport ( Tyler<D>& parTyler, const coords& parSize, const coords& parPos );
|
||||||
~Viewport ( void ) noexcept = default;
|
~Viewport ( void ) noexcept = default;
|
||||||
|
@ -32,6 +33,14 @@ namespace dk {
|
||||||
typename Layer<T, D>::iterator begin ( Layer<T, D>& parLayer ) const;
|
typename Layer<T, D>::iterator begin ( Layer<T, D>& parLayer ) const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename Layer<T, D>::iterator end ( Layer<T, D>& parLayer ) const;
|
typename Layer<T, D>::iterator end ( Layer<T, D>& parLayer ) const;
|
||||||
|
template <typename T> inline
|
||||||
|
typename Layer<T, D>::const_iterator begin ( const Layer<T, D>& parLayer ) const a_always_inline;
|
||||||
|
template <typename T> inline
|
||||||
|
typename Layer<T, D>::const_iterator end ( const Layer<T, D>& parLayer ) const a_always_inline;
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator cbegin ( const Layer<T, D>& parLayer ) const;
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator cend ( const Layer<T, D>& parLayer ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
coords m_size;
|
coords m_size;
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace dkh {
|
||||||
};
|
};
|
||||||
|
|
||||||
AsciiMapSource ( void ) = delete;
|
AsciiMapSource ( void ) = delete;
|
||||||
AsciiMapSource ( const AsciiMapSource& ) = default;
|
AsciiMapSource ( const AsciiMapSource& ) = delete;
|
||||||
AsciiMapSource ( AsciiMapSource&& parOther ) = delete;
|
AsciiMapSource ( AsciiMapSource&& parOther ) = default;
|
||||||
explicit AsciiMapSource ( const char* parFilename );
|
explicit AsciiMapSource ( const char* parFilename );
|
||||||
explicit AsciiMapSource ( const std::string& parFilename );
|
explicit AsciiMapSource ( const std::string& parFilename );
|
||||||
explicit AsciiMapSource ( std::istream& parData );
|
explicit AsciiMapSource ( std::istream& parData );
|
||||||
|
@ -29,11 +29,24 @@ namespace dkh {
|
||||||
|
|
||||||
const coords& mapSize ( void ) const noexcept { return m_mapSize; }
|
const coords& mapSize ( void ) const noexcept { return m_mapSize; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int_type underflow ( void );
|
||||||
|
virtual int_type uflow ( void );
|
||||||
|
virtual int_type pbackfail ( int_type parCh );
|
||||||
|
virtual std::streamsize showmanyc ( void );
|
||||||
|
virtual pos_type seekoff ( off_type parOff, std::ios_base::seekdir parDir, std::ios_base::openmode parWhich );
|
||||||
|
virtual pos_type seekpos( pos_type parPos, std::ios_base::openmode parWhich );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum {
|
||||||
|
DataSize = sizeof(MapTileType)
|
||||||
|
};
|
||||||
|
|
||||||
void parse_map_data ( std::istream& parSrc );
|
void parse_map_data ( std::istream& parSrc );
|
||||||
|
|
||||||
std::vector<MapTileType> m_wholedata;
|
std::vector<MapTileType> m_wholedata;
|
||||||
coords m_mapSize;
|
coords m_mapSize;
|
||||||
|
std::size_t m_bytepos;
|
||||||
};
|
};
|
||||||
} //namespace dkh
|
} //namespace dkh
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,24 @@ namespace dk {
|
||||||
LayerBase<D>::LayerBase (const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize) :
|
LayerBase<D>::LayerBase (const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize) :
|
||||||
m_count(parCount / (parMasterTileSize / parTileSize)),
|
m_count(parCount / (parMasterTileSize / parTileSize)),
|
||||||
m_tilesize(parTileSize),
|
m_tilesize(parTileSize),
|
||||||
m_mastersize(parMasterTileSize)
|
m_mastersize(parMasterTileSize),
|
||||||
|
m_haveFrom(0),
|
||||||
|
m_haveTo(0)
|
||||||
{
|
{
|
||||||
DK_ASSERT((parMasterTileSize / parTileSize) * parTileSize == parMasterTileSize);
|
DK_ASSERT((parMasterTileSize / parTileSize) * parTileSize == parMasterTileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
template <size_t D>
|
||||||
|
void LayerBase<D>::preload (const coords& parFrom, const coords& parTo) {
|
||||||
|
if (parFrom < m_haveFrom or parTo > m_haveTo) {
|
||||||
|
this->onPreload(parFrom, parTo);
|
||||||
|
m_haveFrom = parFrom;
|
||||||
|
m_haveTo = parTo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
template <typename T, size_t D>
|
template <typename T, size_t D>
|
||||||
|
@ -36,11 +49,8 @@ namespace dk {
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
///--------------------------------------------------------------------------
|
///--------------------------------------------------------------------------
|
||||||
template <typename T, size_t D>
|
template <typename T, size_t D>
|
||||||
void Layer<T, D>::preload (const coords& parFrom, const coords& parTo) {
|
void Layer<T, D>::onPreload (const coords& parFrom, const coords& parTo) {
|
||||||
m_tiles.clear();
|
m_tiles.clear();
|
||||||
const auto area = implem::area(parTo - parFrom);
|
|
||||||
m_tiles.reserve(area);
|
|
||||||
m_tilemap.fetch(m_tiles, parFrom, parTo);
|
m_tilemap.fetch(m_tiles, parFrom, parTo);
|
||||||
//m_streamer->copy(m_tiles, parFrom, parTo);:w
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
include/implem/mapstreambase.inl
Normal file
21
include/implem/mapstreambase.inl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace dk {
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
template <std::size_t D>
|
||||||
|
MapStreamBase<D>::MapStreamBase (const coords& parMapSize) :
|
||||||
|
m_mapSize(parMapSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
template <std::size_t D>
|
||||||
|
void MapStreamBase<D>::read (char* parOut, std::size_t parOutSize, const coords& parFrom, const coords& parTo) {
|
||||||
|
DK_ASSERT(parOut);
|
||||||
|
DK_ASSERT(parOutSize > 0);
|
||||||
|
DK_ASSERT(this->isReadable());
|
||||||
|
DK_ASSERT(parFrom < m_mapSize);
|
||||||
|
DK_ASSERT(parTo <= m_mapSize);
|
||||||
|
this->dataBlockRequested(parOut, parOutSize, parFrom, parTo);
|
||||||
|
}
|
||||||
|
} //namespace dk
|
|
@ -71,8 +71,8 @@ namespace dk {
|
||||||
void TileIterator<T, D, T1>::increment() {
|
void TileIterator<T, D, T1>::increment() {
|
||||||
for (size_t d = 0; d < D - 1; ++d) {
|
for (size_t d = 0; d < D - 1; ++d) {
|
||||||
++m_pos[d];
|
++m_pos[d];
|
||||||
if (m_pos[d] >= m_areato[d])
|
if (m_pos[d] >= m_to[d])
|
||||||
m_pos[d] = m_areafrom[d];
|
m_pos[d] = m_from[d];
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace dk {
|
||||||
template <typename T, size_t D, typename T1>
|
template <typename T, size_t D, typename T1>
|
||||||
void TileIterator<T, D, T1>::decrement() {
|
void TileIterator<T, D, T1>::decrement() {
|
||||||
for (size_t d = 0; d < D; ++d) {
|
for (size_t d = 0; d < D; ++d) {
|
||||||
if (m_pos[d] > m_areafrom[d]) {
|
if (m_pos[d] > m_from[d]) {
|
||||||
--m_pos[d];
|
--m_pos[d];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,9 @@
|
||||||
namespace dk {
|
namespace dk {
|
||||||
namespace implem {
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
///Only enabled if Device::MapDimensions is defined and is the same
|
|
||||||
///as D. The function's name is set to give a hint to the user as to
|
|
||||||
///why the error has occurred (they are trying to construct a
|
|
||||||
///TileMapData with a set dimension that is different from the one
|
|
||||||
///hardcoded in the device being passed in). The actual name could be
|
|
||||||
///something like get_device_dimensions().
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<Device::MapDimensions == D, std::size_t>::type err_mismatching_dimension (const Device*) noexcept {
|
|
||||||
return Device::MapDimensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
///Only enabled if Device::MapDimensions is not defined. The function's
|
|
||||||
///name is set to give a hint to the user as to why the error has
|
|
||||||
///occurred (they are trying to construct a TileMapData with a set
|
|
||||||
///dimension that is different from the one hardcoded in the device
|
|
||||||
///being passed in). The actual name could be something like
|
|
||||||
///get_device_dimensions().
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<HasMapDimensions<Device>::result == false, std::size_t>::type err_mismatching_dimension (const Device*) noexcept {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<Device::MapDimensions == D, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device (Device* parDevice) {
|
|
||||||
return parDevice->mapSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
///---------------------------------------------------------------------
|
|
||||||
template <std::size_t D, typename Device>
|
|
||||||
typename std::enable_if<HasMapDimensions<Device>::result == false, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device (Device* parDevice) {
|
|
||||||
return get_map_size_from_device<D>(parDevice);
|
|
||||||
}
|
|
||||||
} //namespace implem
|
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
template <typename T, std::size_t D>
|
template <typename T, std::size_t D>
|
||||||
template <typename Device>
|
TileMapData<T, D>::TileMapData (std::unique_ptr<MapStreamBase<D>>&& parStream) :
|
||||||
TileMapData<T, D>::TileMapData (Device& parDevice) :
|
m_mapstream(std::move(parStream))
|
||||||
m_stream(&parDevice),
|
|
||||||
m_mapSize(implem::retrieve_map_size_from_device<D>(&parDevice)),
|
|
||||||
m_deviceHasDim(D == implem::err_mismatching_dimension<D>(&parDevice))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,15 +11,24 @@ namespace dk {
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
template <typename T, std::size_t D>
|
template <typename T, std::size_t D>
|
||||||
void TileMapData<T, D>::fetch (std::vector<T>& parOut, const coords& parFrom, const coords& parTo) {
|
void TileMapData<T, D>::fetch (std::vector<T>& parOut, const coords& parFrom, const coords& parTo) {
|
||||||
//TODO: implement
|
DK_ASSERT(parFrom >= coords(0));
|
||||||
const auto count = implem::area(parTo - parFrom);
|
DK_ASSERT(parFrom < parTo);
|
||||||
std::fill_n(std::back_inserter(parOut), count, T());
|
DK_ASSERT(parFrom < m_mapstream->mapSize());
|
||||||
|
DK_ASSERT(parTo <= m_mapstream->mapSize());
|
||||||
|
|
||||||
|
const auto tileCount = implem::area(parTo - parFrom);
|
||||||
|
parOut.resize(tileCount);
|
||||||
|
m_mapstream->read(
|
||||||
|
reinterpret_cast<char*>(parOut.data()),
|
||||||
|
parOut.size() * sizeof(typename std::vector<T>::value_type),
|
||||||
|
parFrom,
|
||||||
|
parTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
template <typename T, std::size_t D>
|
template <typename T, std::size_t D>
|
||||||
const typename TileMapData<T, D>::coords& TileMapData<T, D>::mapSize() const {
|
const typename TileMapData<T, D>::coords& TileMapData<T, D>::mapSize() const {
|
||||||
return m_mapSize;
|
return m_mapstream->mapSize();
|
||||||
}
|
}
|
||||||
} //namespace dk
|
} //namespace dk
|
||||||
|
|
|
@ -20,17 +20,42 @@ namespace dk {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename Layer<T, D>::iterator Viewport<D>::begin (Layer<T, D>& parLayer) const {
|
typename Layer<T, D>::iterator Viewport<D>::begin (Layer<T, D>& parLayer) const {
|
||||||
typedef typename Layer<T, D>::iterator IterType;
|
typedef typename Layer<T, D>::iterator IterType;
|
||||||
|
return IterType(&parLayer.m_tiles, m_position, m_position + m_size, coords(0), m_tyler.map_size());
|
||||||
return IterType(&parLayer.m_tiles, m_position, m_position + m_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t D>
|
template <size_t D>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename Layer<T, D>::iterator Viewport<D>::end (Layer<T, D>& parLayer) const {
|
typename Layer<T, D>::iterator Viewport<D>::end (Layer<T, D>& parLayer) const {
|
||||||
typedef typename Layer<T, D>::iterator IterType;
|
typedef typename Layer<T, D>::iterator IterType;
|
||||||
|
|
||||||
const auto to(m_position + m_size);
|
const auto to(m_position + m_size);
|
||||||
return IterType(&parLayer.m_tiles, implem::buildPastEndCoordinate(m_position, to), to);
|
return IterType(&parLayer.m_tiles, implem::buildPastEndCoordinate(m_position, to), to, coords(0), m_tyler.map_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t D>
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator Viewport<D>::begin (const Layer<T, D>& parLayer) const {
|
||||||
|
return this->cbegin(parLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t D>
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator Viewport<D>::end (const Layer<T, D>& parLayer) const {
|
||||||
|
return this->cend(parLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t D>
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator Viewport<D>::cbegin (const Layer<T, D>& parLayer) const {
|
||||||
|
typedef typename Layer<T, D>::const_iterator IterType;
|
||||||
|
return IterType(&parLayer.m_tiles, m_position, m_position + m_size, coords(0), m_tyler.map_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t D>
|
||||||
|
template <typename T>
|
||||||
|
typename Layer<T, D>::const_iterator Viewport<D>::cend (const Layer<T, D>& parLayer) const {
|
||||||
|
typedef typename Layer<T, D>::const_iterator IterType;
|
||||||
|
const auto to(m_position + m_size);
|
||||||
|
return IterType(&parLayer.m_tiles, implem::buildPastEndCoordinate(m_position, to), to, coords(0), m_tyler.map_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t D>
|
template <size_t D>
|
||||||
|
|
32
include/mapreaders/mapstreambase.hpp
Normal file
32
include/mapreaders/mapstreambase.hpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef id3CAE7A32F0C3428EA125F91D261C0029
|
||||||
|
#define id3CAE7A32F0C3428EA125F91D261C0029
|
||||||
|
|
||||||
|
#include "primitivetypes.hpp"
|
||||||
|
#include "implem/vector.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace dk {
|
||||||
|
template <std::size_t D>
|
||||||
|
class MapStreamBase {
|
||||||
|
public:
|
||||||
|
typedef Vector<CoordinateScalarType, D> coords;
|
||||||
|
|
||||||
|
MapStreamBase ( void ) = delete;
|
||||||
|
explicit MapStreamBase ( const coords& parMapSize );
|
||||||
|
virtual ~MapStreamBase ( void ) noexcept = default;
|
||||||
|
|
||||||
|
virtual bool isReadable ( void ) const = 0;
|
||||||
|
virtual bool isWriteable ( void ) const = 0;
|
||||||
|
|
||||||
|
const coords& mapSize ( void ) const noexcept { return m_mapSize; }
|
||||||
|
void read ( char* parOut, std::size_t parOutSize, const coords& parFrom, const coords& parTo );
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual std::size_t dataBlockRequested ( char* parOut, std::size_t parOutSize, const coords& parFrom, const coords& parTo ) = 0;
|
||||||
|
const coords m_mapSize;
|
||||||
|
};
|
||||||
|
} //namespace dk
|
||||||
|
|
||||||
|
#include "implem/mapstreambase.inl"
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,5 @@
|
||||||
#include "helpers/asciimapsource.hpp"
|
#include "helpers/asciimapsource.hpp"
|
||||||
|
#include "implem/compatibility.h"
|
||||||
#include "asciimap_parser.hpp"
|
#include "asciimap_parser.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -7,32 +8,76 @@
|
||||||
|
|
||||||
namespace dkh {
|
namespace dkh {
|
||||||
namespace {
|
namespace {
|
||||||
|
char extractByte ( AsciiMapSource::MapTileType parVal, std::size_t parByte ) a_pure;
|
||||||
|
|
||||||
|
char extractByte (AsciiMapSource::MapTileType parVal, std::size_t parByte) {
|
||||||
|
return static_cast<char>(
|
||||||
|
(parVal >> (parByte * 8)) & 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
AsciiMapSource::AsciiMapSource (const char* parFilename) {
|
AsciiMapSource::AsciiMapSource (const char* parFilename) {
|
||||||
|
m_bytepos = 0;
|
||||||
std::ifstream src(parFilename);
|
std::ifstream src(parFilename);
|
||||||
parse_map_data(src);
|
parse_map_data(src);
|
||||||
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
|
|
||||||
setg(base, base, base + m_wholedata.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
AsciiMapSource::AsciiMapSource (const std::string& parFilename) {
|
AsciiMapSource::AsciiMapSource (const std::string& parFilename) {
|
||||||
|
m_bytepos = 0;
|
||||||
std::ifstream src(parFilename);
|
std::ifstream src(parFilename);
|
||||||
parse_map_data(src);
|
parse_map_data(src);
|
||||||
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
|
|
||||||
setg(base, base, base + m_wholedata.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
AsciiMapSource::AsciiMapSource (std::istream& parData) {
|
AsciiMapSource::AsciiMapSource (std::istream& parData) {
|
||||||
|
m_bytepos = 0;
|
||||||
parse_map_data(parData);
|
parse_map_data(parData);
|
||||||
char* const base = reinterpret_cast<char*>(&m_wholedata.front());
|
}
|
||||||
setg(base, base, base + m_wholedata.size());
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
AsciiMapSource::int_type AsciiMapSource::underflow() {
|
||||||
|
if (m_bytepos == m_wholedata.size() * DataSize)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
const auto index = m_bytepos / DataSize;
|
||||||
|
const auto byte = m_bytepos % DataSize;
|
||||||
|
return traits_type::to_int_type(extractByte(m_wholedata[index], byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
AsciiMapSource::int_type AsciiMapSource::uflow() {
|
||||||
|
if (m_bytepos == m_wholedata.size() * DataSize)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
const auto retval = underflow();
|
||||||
|
++m_bytepos;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
AsciiMapSource::int_type AsciiMapSource::pbackfail (int_type parCh) {
|
||||||
|
if (0 == m_bytepos or (parCh != traits_type::eof() and parCh != traits_type::to_int_type(extractByte(m_wholedata[m_bytepos / DataSize], m_bytepos % DataSize))))
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
--m_bytepos;
|
||||||
|
DK_ASSERT(underflow() == traits_type::to_int_type(parCh));
|
||||||
|
return traits_type::to_int_type(parCh);
|
||||||
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
std::streamsize AsciiMapSource::showmanyc() {
|
||||||
|
DK_ASSERT(m_bytepos <= m_wholedata.size() * DataSize);
|
||||||
|
return m_wholedata.size() * DataSize - m_bytepos;
|
||||||
}
|
}
|
||||||
|
|
||||||
///-------------------------------------------------------------------------
|
///-------------------------------------------------------------------------
|
||||||
|
@ -63,4 +108,66 @@ namespace dkh {
|
||||||
m_mapSize.x() = grammar.lengths.front();
|
m_mapSize.x() = grammar.lengths.front();
|
||||||
m_mapSize.y() = m_wholedata.size() / m_mapSize.x();
|
m_mapSize.y() = m_wholedata.size() / m_mapSize.x();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
AsciiMapSource::pos_type AsciiMapSource::seekoff (off_type parOff, std::ios_base::seekdir parDir, std::ios_base::openmode parWhich) {
|
||||||
|
using std::ios;
|
||||||
|
|
||||||
|
if (parWhich & ios::out)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
const std::size_t dataLength = DataSize * m_wholedata.size();
|
||||||
|
if (parWhich & ios::in) {
|
||||||
|
std::size_t desiredPos;
|
||||||
|
|
||||||
|
switch (parDir) {
|
||||||
|
case ios::beg:
|
||||||
|
desiredPos = static_cast<std::size_t>(parOff);
|
||||||
|
break;
|
||||||
|
case ios::cur:
|
||||||
|
desiredPos = static_cast<std::size_t>(m_bytepos + parOff);
|
||||||
|
break;
|
||||||
|
case ios::end:
|
||||||
|
desiredPos = static_cast<std::size_t>(dataLength - parOff);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_bytepos = static_cast<std::size_t>(dataLength);
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
if (desiredPos >= dataLength) {
|
||||||
|
m_bytepos = dataLength;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_bytepos = desiredPos;
|
||||||
|
return static_cast<pos_type>(m_bytepos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_bytepos = dataLength;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
///-------------------------------------------------------------------------
|
||||||
|
AsciiMapSource::pos_type AsciiMapSource::seekpos(pos_type parPos, std::ios_base::openmode parWhich) {
|
||||||
|
using std::ios;
|
||||||
|
|
||||||
|
if (parWhich & ios::out)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
const std::size_t dataLength = DataSize * m_wholedata.size();
|
||||||
|
if (parWhich & ios::in) {
|
||||||
|
if (static_cast<std::size_t>(parPos) >= dataLength) {
|
||||||
|
m_bytepos = dataLength;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_bytepos = static_cast<std::size_t>(parPos);
|
||||||
|
return static_cast<pos_type>(m_bytepos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_bytepos = static_cast<std::size_t>(parPos);
|
||||||
|
return static_cast<pos_type>(m_bytepos);
|
||||||
|
}
|
||||||
} //namespace dkh
|
} //namespace dkh
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "platformstrings.h"
|
#include "platformstrings.h"
|
||||||
#include "helpers/asciimapsource.hpp"
|
#include "helpers/asciimapsource.hpp"
|
||||||
|
#include "mapreaders/mapstreamraw.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -20,6 +21,8 @@ namespace {
|
||||||
template <typename Device, typename Tile>
|
template <typename Device, typename Tile>
|
||||||
void createLayer ( dk::Tyler<2>& parTiler, LayerWithData<Device, Tile>& parOut );
|
void createLayer ( dk::Tyler<2>& parTiler, LayerWithData<Device, Tile>& parOut );
|
||||||
void printWelcome ( void );
|
void printWelcome ( void );
|
||||||
|
void addLayer ( dk::Tyler<2>& parTiler, LayerWithData<dkh::AsciiMapSource, int>& parLayerInfo, const char* parPath );
|
||||||
|
void printViewport ( const dk::Viewport<2>& parView, const dk::Layer<int, 2>& parLayer );
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
@ -32,43 +35,13 @@ int main() {
|
||||||
dk::Tyler<2> tiler(coords2(10, 6), coords2(64));
|
dk::Tyler<2> tiler(coords2(10, 6), coords2(64));
|
||||||
|
|
||||||
LayerWithData<AsciiMapSource, int> bottomLayer;
|
LayerWithData<AsciiMapSource, int> bottomLayer;
|
||||||
bottomLayer.path = DATA_PATH"/test.map";
|
addLayer(tiler, bottomLayer, DATA_PATH"/test.map");
|
||||||
bottomLayer.device = std::unique_ptr<AsciiMapSource>(new AsciiMapSource(bottomLayer.path));
|
|
||||||
bottomLayer.tilemap = std::unique_ptr<TileMapData<int, 2>>(new TileMapData<int, 2>(*bottomLayer.device));
|
|
||||||
bottomLayer.layer = &tiler.push_layer(*bottomLayer.tilemap);
|
|
||||||
|
|
||||||
LayerWithData<AsciiMapSource, int> topLayer;
|
LayerWithData<AsciiMapSource, int> topLayer;
|
||||||
topLayer.path = DATA_PATH"/test_2.map";
|
addLayer(tiler, topLayer, DATA_PATH"/test_2.map");
|
||||||
topLayer.device = std::unique_ptr<AsciiMapSource>(new AsciiMapSource(topLayer.path));
|
|
||||||
topLayer.tilemap = std::unique_ptr<TileMapData<int, 2>>(new TileMapData<int, 2>(*topLayer.device));
|
|
||||||
topLayer.layer = &tiler.push_layer(*topLayer.tilemap);
|
|
||||||
|
|
||||||
dk::Viewport<2> viewport(tiler, coords2(10, 6), coords2(0));
|
printViewport(dk::Viewport<2>(tiler, coords2(10, 6), coords2(0)), *bottomLayer.layer);
|
||||||
{
|
printViewport(dk::Viewport<2>(tiler, coords2(4, 4), coords2(0)), *bottomLayer.layer);
|
||||||
int col = 0;
|
|
||||||
const auto tilecount = bottomLayer.layer->count();
|
|
||||||
for (auto tile : *bottomLayer.layer) {
|
|
||||||
std::cout << tile;
|
|
||||||
++col;
|
|
||||||
if (col == tilecount.x()) {
|
|
||||||
col = 0;
|
|
||||||
std::cout << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dk::Viewport<2> viewport_small(tiler, coords2(4, 4), coords2(0));
|
|
||||||
{
|
|
||||||
int col = 0;
|
|
||||||
const auto tilecount = viewport_small.count();
|
|
||||||
for (auto itTile = viewport_small.begin(*bottomLayer.layer), itTileEND = viewport_small.end(*bottomLayer.layer); itTile != itTileEND; ++itTile) {
|
|
||||||
std::cout << *itTile;
|
|
||||||
++col;
|
|
||||||
if (col == tilecount.x()) {
|
|
||||||
col = 0;
|
|
||||||
std::cout << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
std::cout << "Map size: " << tiler.map_size() << '\n';
|
std::cout << "Map size: " << tiler.map_size() << '\n';
|
||||||
|
@ -89,4 +62,25 @@ namespace {
|
||||||
#endif
|
#endif
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addLayer (dk::Tyler<2>& parTiler, LayerWithData<dkh::AsciiMapSource, int>& parLayerInfo, const char* parPath) {
|
||||||
|
parLayerInfo.path = parPath;
|
||||||
|
parLayerInfo.device = std::unique_ptr<dkh::AsciiMapSource>(new dkh::AsciiMapSource(parLayerInfo.path));
|
||||||
|
std::unique_ptr<dk::MapStreamRaw<int, 2>> stream(new dk::MapStreamRaw<int, 2>(*parLayerInfo.device));
|
||||||
|
parLayerInfo.tilemap = std::unique_ptr<dk::TileMapData<int, 2>>(new dk::TileMapData<int, 2>(std::move(stream)));
|
||||||
|
parLayerInfo.layer = &parTiler.push_layer(*parLayerInfo.tilemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printViewport (const dk::Viewport<2>& parView, const dk::Layer<int, 2>& parLayer) {
|
||||||
|
int col = 0;
|
||||||
|
const auto tilecount = parView.count();
|
||||||
|
for (auto itTile = parView.begin(parLayer), itTileEND = parView.end(parLayer); itTile != itTileEND; ++itTile) {
|
||||||
|
std::cout << *itTile;
|
||||||
|
++col;
|
||||||
|
if (col == tilecount.x()) {
|
||||||
|
col = 0;
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
Loading…
Add table
Reference in a new issue