157 lines
4.8 KiB
C++
157 lines
4.8 KiB
C++
/*
|
|
Copyright 2016, 2017 Michele "King_DuckZ" Santullo
|
|
|
|
This file is part of MyCurry.
|
|
|
|
MyCurry is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
MyCurry is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with MyCurry. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "worldgrid.hpp"
|
|
#include "worldsizenotifiable.hpp"
|
|
#include <cassert>
|
|
#include <utility>
|
|
#include <algorithm>
|
|
|
|
namespace curry {
|
|
WorldGrid::WorldGrid (vec2us parTileSize) :
|
|
m_tile_size(parTileSize),
|
|
m_world_size(0),
|
|
m_layer_count(0)
|
|
{
|
|
}
|
|
|
|
const vec2us& WorldGrid::tile_size() const {
|
|
return m_tile_size;
|
|
}
|
|
|
|
const vec2us& WorldGrid::world_size() const {
|
|
return m_world_size;
|
|
}
|
|
|
|
const TileIndex* WorldGrid::tile (const vec2us& parIndex) const {
|
|
const std::size_t index = parIndex.x() + parIndex.y() * m_world_size.x();
|
|
assert(m_layer_count);
|
|
assert(not m_layers.empty());
|
|
assert(index < tile_count());
|
|
assert(index * m_layer_count + m_layer_count <= m_layers.size());
|
|
return m_layers.data() + index * m_layer_count;
|
|
}
|
|
|
|
void WorldGrid::add_layer (vec2us parWorldSize, const std::vector<TileIndex>& parLayer) {
|
|
assert(parLayer.size() == tile_count());
|
|
|
|
std::vector<TileIndex> new_vec;
|
|
new_vec.reserve((m_layer_count + 1) * tile_count());
|
|
auto curr_tiles = m_layers.cbegin();
|
|
for (auto tile : parLayer) {
|
|
std::copy_n(curr_tiles, m_layer_count, std::back_inserter(new_vec));
|
|
std::advance(curr_tiles, m_layer_count);
|
|
new_vec.push_back(tile);
|
|
}
|
|
++m_layer_count;
|
|
set_world_size(parWorldSize);
|
|
std::swap(m_layers, new_vec);
|
|
}
|
|
|
|
void WorldGrid::set_layers (vec2us parWorldSize, const std::vector<std::vector<TileIndex>>& parLayers) {
|
|
if (parLayers.empty()) {
|
|
unload_layers();
|
|
return;
|
|
}
|
|
|
|
assert(not parLayers.empty());
|
|
std::vector<TileIndex> new_vec;
|
|
new_vec.reserve(parLayers.size() * parLayers.front().size());
|
|
for (std::size_t z = 0; z < parLayers.front().size(); ++z) {
|
|
for (std::size_t t = 0; t < parLayers.size(); ++t) {
|
|
assert(parLayers[t].size() == parLayers.front().size());
|
|
new_vec.push_back(parLayers[t][z]);
|
|
}
|
|
}
|
|
|
|
m_layer_count = static_cast<uint16_t>(parLayers.size());
|
|
std::swap(m_layers, new_vec);
|
|
set_world_size(parWorldSize);
|
|
}
|
|
|
|
uint16_t WorldGrid::layer_count() const {
|
|
return m_layer_count;
|
|
}
|
|
|
|
std::size_t WorldGrid::tile_count() const {
|
|
assert((layer_count() and not m_layers.empty()) or (m_layers.size() % layer_count() == 0));
|
|
return (layer_count() ? m_layers.size() / layer_count() : 0);
|
|
}
|
|
|
|
void WorldGrid::unload_layers() {
|
|
m_layers.clear();
|
|
m_layer_count = 0;
|
|
}
|
|
|
|
void WorldGrid::set_world_size (const vec2us& parSize) {
|
|
if (parSize != m_world_size) {
|
|
m_world_size = parSize;
|
|
|
|
for (auto& observer : m_world_size_watchers) {
|
|
observer->world_size_changed(m_world_size, world_size_pixel(*this));
|
|
}
|
|
}
|
|
}
|
|
|
|
auto WorldGrid::register_observer (WorldSizeNotifiable* parWatcher) -> WorldSizeWatcherTicket {
|
|
assert(parWatcher);
|
|
return m_world_size_watchers.Add(parWatcher);
|
|
}
|
|
|
|
void WorldGrid::unregister_observer (WorldSizeWatcherTicket parTicket) {
|
|
m_world_size_watchers.Remove(parTicket);
|
|
}
|
|
|
|
void WorldGrid::set_tile_properties (const std::vector<TileProperty>& parProperties) {
|
|
m_tile_properties.resize(parProperties.size());
|
|
std::copy(parProperties.begin(), parProperties.end(), m_tile_properties.begin());
|
|
}
|
|
|
|
const TileProperty& WorldGrid::tile_property (const TileIndex* parIndex) const {
|
|
assert(parIndex);
|
|
assert(static_cast<size_t>(*parIndex) < m_tile_properties.size());
|
|
return m_tile_properties[static_cast<size_t>(*parIndex)];
|
|
}
|
|
|
|
vec2i world_size_pixel (const WorldGrid& parWorld) {
|
|
return parWorld.tile_size() * parWorld.world_size();
|
|
}
|
|
|
|
vec2us pixel_to_world_tile (const WorldGrid& parWorld, const vec2f& parPos) {
|
|
assert(position_is_on_map(parWorld, parPos));
|
|
const auto retval = vector_cast<vec2us>(
|
|
parPos / vector_cast<vec2f>(parWorld.tile_size())
|
|
);
|
|
assert(world_tile_to_pixel(parWorld, retval) <= parPos);
|
|
return retval;
|
|
}
|
|
|
|
vec2f world_tile_to_pixel (const WorldGrid& parWorld, const vec2us& parTile) {
|
|
assert(parTile < parWorld.world_size());
|
|
return vector_cast<vec2f>(parTile) * vector_cast<vec2f>(parWorld.tile_size());
|
|
}
|
|
|
|
bool position_is_on_map (const WorldGrid& parWorld, const vec2i& parPos) {
|
|
assert(parWorld.tile_size() > vec2us(0));
|
|
|
|
return parPos >= vec2i(0) and
|
|
parPos / vector_cast<vec2i>(parWorld.tile_size()) < parWorld.world_size();
|
|
}
|
|
} //namespace curry
|