Files
@ r28822:57cd1bc354de
Branch filter:
Location: cpp/openttd-patchpack/source/src/tilematrix_type.hpp
r28822:57cd1bc354de
3.9 KiB
text/x-c++hdr
Codechange: Add `GetVisibleRangeIterators()` to `Scrollbar`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file tilematrix_type.hpp Template for storing a value per area of the map. */
#ifndef TILEMATRIX_TYPE_HPP
#define TILEMATRIX_TYPE_HPP
#include "core/alloc_func.hpp"
#include "tilearea_type.h"
/**
* A simple matrix that stores one value per N*N square of the map.
* Storage is only allocated for the part of the map that has values
* assigned.
*
* @note No constructor is called for newly allocated values, you
* have to do this yourself if needed.
* @tparam T The type of the stored items.
* @tparam N Grid size.
*/
template <typename T, uint N>
class TileMatrix {
/** Allocates space for a new tile in the matrix.
* @param tile Tile to add.
*/
void AllocateStorage(TileIndex tile)
{
uint old_left = TileX(this->area.tile) / N;
uint old_top = TileY(this->area.tile) / N;
uint old_w = this->area.w / N;
uint old_h = this->area.h / N;
/* Add the square the tile is in to the tile area. We do this
* by adding top-left and bottom-right of the square. */
uint grid_x = (TileX(tile) / N) * N;
uint grid_y = (TileY(tile) / N) * N;
this->area.Add(TileXY(grid_x, grid_y));
this->area.Add(TileXY(grid_x + N - 1, grid_y + N - 1));
/* Allocate new storage. */
T *new_data = CallocT<T>(this->area.w / N * this->area.h / N);
if (old_w > 0) {
/* Copy old data if present. */
uint offs_x = old_left - TileX(this->area.tile) / N;
uint offs_y = old_top - TileY(this->area.tile) / N;
for (uint row = 0; row < old_h; row++) {
MemCpyT(&new_data[(row + offs_y) * this->area.w / N + offs_x], &this->data[row * old_w], old_w);
}
}
free(this->data);
this->data = new_data;
}
public:
static const uint GRID = N;
TileArea area; ///< Area covered by the matrix.
T *data; ///< Pointer to data array.
TileMatrix() : area(INVALID_TILE, 0, 0), data(nullptr) {}
~TileMatrix()
{
free(this->data);
}
/**
* Get the total covered area.
* @return The area covered by the matrix.
*/
const TileArea &GetArea() const
{
return this->area;
}
/**
* Get the area of the matrix square that contains a specific tile.
* @param tile The tile to get the map area for.
* @param extend Extend the area by this many squares on all sides.
* @return Tile area containing the tile.
*/
static TileArea GetAreaForTile(TileIndex tile, uint extend = 0)
{
uint tile_x = (TileX(tile) / N) * N;
uint tile_y = (TileY(tile) / N) * N;
uint w = N, h = N;
w += std::min(extend * N, tile_x);
h += std::min(extend * N, tile_y);
tile_x -= std::min(extend * N, tile_x);
tile_y -= std::min(extend * N, tile_y);
w += std::min(extend * N, Map::SizeX() - tile_x - w);
h += std::min(extend * N, Map::SizeY() - tile_y - h);
return TileArea(TileXY(tile_x, tile_y), w, h);
}
/**
* Extend the coverage area to include a tile.
* @param tile The tile to include.
*/
void Add(TileIndex tile)
{
if (!this->area.Contains(tile)) {
this->AllocateStorage(tile);
}
}
/**
* Get the value associated to a tile index.
* @param tile The tile to get the value for.
* @return Pointer to the value.
*/
T *Get(TileIndex tile)
{
this->Add(tile);
tile -= this->area.tile;
uint x = TileX(tile) / N;
uint y = TileY(tile) / N;
return &this->data[y * this->area.w / N + x];
}
/** Array access operator, see #Get. */
inline T &operator[](TileIndex tile)
{
return *this->Get(tile);
}
};
#endif /* TILEMATRIX_TYPE_HPP */
|