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/>.
10 /** @file plans_base.h Base class for plans. */
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"
21 #include "date_func.h"
22 #include "viewport_func.h"
23 #include "core/endian_func.hpp"
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
;
39 this->focused
= false;
52 bool AppendTile(TileIndex tile
)
54 const uint cnt
= (uint
) this->tiles
.size();
57 const TileIndex last_tile
= this->tiles
[cnt
- 1];
58 if (last_tile
== tile
) return false;
59 MarkTileLineDirty(last_tile
, tile
);
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
);
82 if (this->tiles
.size() * sizeof(TileIndex
) >= MAX_CMD_TEXT_LENGTH
) return false;
84 this->tiles
.push_back(tile
);
88 void SetFocus(bool focused
)
90 if (this->focused
!= focused
) this->MarkDirty();
91 this->focused
= focused
;
94 bool ToggleVisibility()
96 this->SetVisibility(!this->visible
);
100 void SetVisibility(bool visible
)
102 if (this->visible
!= visible
) this->MarkDirty();
103 this->visible
= visible
;
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
);
120 for (uint i
= 0; i
< cnt
; i
++) {
121 buffer
[i
] = TO_LE32(this->tiles
[i
]);
123 if (buffer_length
) *buffer_length
= datalen
;
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
];
145 TileIndex
CalculateCentreTile() const
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
> {
158 PlanLineVector lines
;
165 Plan(Owner owner
= INVALID_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();
177 for (PlanLineVector::iterator it
= lines
.begin(); it
!= lines
.end(); it
++) {
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
;
209 PlanLine
*pl
= new PlanLine();
210 if (pl
) this->lines
.push_back(pl
);
214 bool StoreTempTile(TileIndex tile
)
216 return this->temp_line
->AppendTile(tile
);
219 bool ValidateNewLine()
222 if (this->temp_line
->tiles
.size() > 1) {
223 uint buffer_length
= 0;
224 const TileIndex
*buffer
= this->temp_line
->Export(&buffer_length
);
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
);
230 _current_plan
->temp_line
->MarkDirty();
231 this->temp_line
->Clear();
238 return (this->owner
== _local_company
|| this->visible_by_all
);
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
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 */