Add templated versions of CeilDiv and Ceil maths functions
[openttd-joker.git] / src / plans_base.h
blob268a44c7258d385e73e5c06b685a4a517f0217d8
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file plans_base.h Base class for plans. */
12 #ifndef PLANS_BASE_H
13 #define PLANS_BASE_H
15 #include "plans_func.h"
16 #include "core/pool_type.hpp"
17 #include "company_type.h"
18 #include "company_func.h"
19 #include "command_func.h"
20 #include "map_func.h"
21 #include "date_func.h"
22 #include "viewport_func.h"
23 #include "core/endian_func.hpp"
24 #include <vector>
26 typedef Pool<Plan, PlanID, 16, 64000> PlanPool;
27 typedef std::vector<TileIndex> TileVector;
28 typedef std::vector<PlanLine*> PlanLineVector;
29 extern PlanPool _plan_pool;
31 struct PlanLine {
32 bool visible;
33 bool focused;
34 TileVector tiles;
36 PlanLine()
38 this->visible = true;
39 this->focused = false;
42 ~PlanLine()
44 this->Clear();
47 void Clear()
49 this->tiles.clear();
52 bool AppendTile(TileIndex tile)
54 const uint cnt = (uint) this->tiles.size();
56 if (cnt > 0) {
57 const TileIndex last_tile = this->tiles[cnt - 1];
58 if (last_tile == tile) return false;
59 MarkTileLineDirty(last_tile, tile);
61 if (cnt > 1) {
62 const TileIndex t0 = this->tiles[cnt - 2];
63 const int x0 = (int)TileX(t0);
64 const int y0 = (int)TileY(t0);
65 const TileIndex t1 = this->tiles[cnt - 1];
66 const int x1 = (int)TileX(t1);
67 const int y1 = (int)TileY(t1);
68 const int x2 = (int)TileX(tile);
69 const int y2 = (int)TileY(tile);
71 if ((y1 - y0) * (x2 - x1) == (y2 - y1) * (x1 - x0)) { // Same direction.
72 if (abs(x2 - x1) <= abs(x2 - x0) && abs(y2 - y1) <= abs(y2 - y0)) { // Tile i+1 is between i and i+2.
73 /* The new tile is in the continuity, just update the last tile. */
74 this->tiles[cnt - 1] = tile;
75 MarkTileLineDirty(t1, tile);
76 return true;
82 if (this->tiles.size() * sizeof(TileIndex) >= MAX_CMD_TEXT_LENGTH) return false;
84 this->tiles.push_back(tile);
85 return true;
88 void SetFocus(bool focused)
90 if (this->focused != focused) this->MarkDirty();
91 this->focused = focused;
94 bool ToggleVisibility()
96 this->SetVisibility(!this->visible);
97 return this->visible;
100 void SetVisibility(bool visible)
102 if (this->visible != visible) this->MarkDirty();
103 this->visible = visible;
106 void MarkDirty()
108 const uint sz = (uint) this->tiles.size();
109 for (uint i = 1; i < sz; i++) {
110 MarkTileLineDirty(this->tiles[i - 1], this->tiles[i]);
114 TileIndex *Export(uint *buffer_length)
116 const uint cnt = (uint) this->tiles.size();
117 const uint datalen = sizeof(TileIndex) * cnt;
118 TileIndex *buffer = (TileIndex *)malloc(datalen);
119 if (buffer) {
120 for (uint i = 0; i < cnt; i++) {
121 buffer[i] = TO_LE32(this->tiles[i]);
123 if (buffer_length) *buffer_length = datalen;
125 return buffer;
128 void Import(const TileIndex* data, const uint data_length)
130 for (uint i = data_length; i != 0; i--, data++) {
131 this->tiles.push_back(FROM_LE32(*data));
135 void AddLineToCalculateCentreTile(uint64 &x, uint64 &y, uint32 &count) const
137 for (size_t i = 0; i < this->tiles.size(); i++) {
138 TileIndex t = this->tiles[i];
139 x += TileX(t);
140 y += TileY(t);
141 count++;
145 TileIndex CalculateCentreTile() const
147 uint64 x = 0;
148 uint64 y = 0;
149 uint32 count = 0;
150 this->AddLineToCalculateCentreTile(x, y, count);
151 if (count == 0) return INVALID_TILE;
152 return TileXY(x / count, y / count);
156 struct Plan : PlanPool::PoolItem<&_plan_pool> {
157 OwnerByte owner;
158 PlanLineVector lines;
159 PlanLine *temp_line;
160 bool visible;
161 bool visible_by_all;
162 bool show_lines;
163 Date creation_date;
165 Plan(Owner owner = INVALID_OWNER)
167 this->owner = owner;
168 this->creation_date = _date;
169 this->visible = false;
170 this->visible_by_all = false;
171 this->show_lines = false;
172 this->temp_line = new PlanLine();
175 ~Plan()
177 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
178 delete (*it);
180 this->lines.clear();
181 delete temp_line;
184 void SetFocus(bool focused)
186 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
187 (*it)->SetFocus(focused);
191 void SetVisibility(bool visible, bool do_lines = true)
193 this->visible = visible;
195 if (!do_lines) return;
196 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
197 (*it)->SetVisibility(visible);
201 bool ToggleVisibility()
203 this->SetVisibility(!this->visible);
204 return this->visible;
207 PlanLine *NewLine()
209 PlanLine *pl = new PlanLine();
210 if (pl) this->lines.push_back(pl);
211 return pl;
214 bool StoreTempTile(TileIndex tile)
216 return this->temp_line->AppendTile(tile);
219 bool ValidateNewLine()
221 bool ret = false;
222 if (this->temp_line->tiles.size() > 1) {
223 uint buffer_length = 0;
224 const TileIndex *buffer = this->temp_line->Export(&buffer_length);
225 if (buffer) {
226 _current_plan->SetVisibility(true, false);
227 ret = DoCommandP(0, _current_plan->index, (uint32) this->temp_line->tiles.size(), CMD_ADD_PLAN_LINE, NULL, (const char *)buffer, true, buffer_length);
228 free(buffer);
230 _current_plan->temp_line->MarkDirty();
231 this->temp_line->Clear();
233 return ret;
236 bool IsListable()
238 return (this->owner == _local_company || this->visible_by_all);
241 bool IsVisible()
243 if (!this->IsListable()) return false;
244 return this->visible;
247 bool ToggleVisibilityByAll()
249 if (_current_plan->owner == _local_company) DoCommandP(0, _current_plan->index, !this->visible_by_all, CMD_CHANGE_PLAN_VISIBILITY);
250 return this->visible_by_all;
253 TileIndex CalculateCentreTile() const
255 uint64 x = 0;
256 uint64 y = 0;
257 uint32 count = 0;
258 for (PlanLineVector::const_iterator it = lines.begin(); it != lines.end(); it++) {
259 (*it)->AddLineToCalculateCentreTile(x, y, count);
261 if (count == 0) return INVALID_TILE;
262 return TileXY(x / count, y / count);
266 #define FOR_ALL_PLANS_FROM(var, start) FOR_ALL_ITEMS_FROM(Plan, plan_index, var, start)
267 #define FOR_ALL_PLANS(var) FOR_ALL_PLANS_FROM(var, 0)
269 #endif /* PLANS_BASE_H */