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"
27 typedef Pool
<Plan
, PlanID
, 16, 64000> PlanPool
;
28 typedef std::vector
<TileIndex
> TileVector
;
29 typedef std::vector
<PlanLine
*> PlanLineVector
;
30 extern PlanPool _plan_pool
;
40 this->focused
= false;
53 bool AppendTile(TileIndex tile
)
55 const uint cnt
= (uint
) this->tiles
.size();
58 const TileIndex last_tile
= this->tiles
[cnt
- 1];
59 if (last_tile
== tile
) return false;
60 MarkTileLineDirty(last_tile
, tile
);
63 const TileIndex t0
= this->tiles
[cnt
- 2];
64 const int x0
= (int)TileX(t0
);
65 const int y0
= (int)TileY(t0
);
66 const TileIndex t1
= this->tiles
[cnt
- 1];
67 const int x1
= (int)TileX(t1
);
68 const int y1
= (int)TileY(t1
);
69 const int x2
= (int)TileX(tile
);
70 const int y2
= (int)TileY(tile
);
72 if ((y1
- y0
) * (x2
- x1
) == (y2
- y1
) * (x1
- x0
)) { // Same direction.
73 if (abs(x2
- x1
) <= abs(x2
- x0
) && abs(y2
- y1
) <= abs(y2
- y0
)) { // Tile i+1 is between i and i+2.
74 /* The new tile is in the continuity, just update the last tile. */
75 this->tiles
[cnt
- 1] = tile
;
76 MarkTileLineDirty(t1
, tile
);
83 if (this->tiles
.size() * sizeof(TileIndex
) >= MAX_CMD_TEXT_LENGTH
) return false;
85 this->tiles
.push_back(tile
);
89 void SetFocus(bool focused
)
91 if (this->focused
!= focused
) this->MarkDirty();
92 this->focused
= focused
;
95 bool ToggleVisibility()
97 this->SetVisibility(!this->visible
);
101 void SetVisibility(bool visible
)
103 if (this->visible
!= visible
) this->MarkDirty();
104 this->visible
= visible
;
109 const uint sz
= (uint
) this->tiles
.size();
110 for (uint i
= 1; i
< sz
; i
++) {
111 MarkTileLineDirty(this->tiles
[i
- 1], this->tiles
[i
]);
115 TileIndex
*Export(uint
*buffer_length
)
117 const uint cnt
= (uint
) this->tiles
.size();
118 const uint datalen
= sizeof(TileIndex
) * cnt
;
119 TileIndex
*buffer
= (TileIndex
*)malloc(datalen
);
121 for (uint i
= 0; i
< cnt
; i
++) {
122 buffer
[i
] = TO_LE32(this->tiles
[i
]);
124 if (buffer_length
) *buffer_length
= datalen
;
129 void Import(const TileIndex
* data
, const uint data_length
)
131 for (uint i
= data_length
; i
!= 0; i
--, data
++) {
132 this->tiles
.push_back(FROM_LE32(*data
));
136 void AddLineToCalculateCentreTile(uint64
&x
, uint64
&y
, uint32
&count
) const
138 for (size_t i
= 0; i
< this->tiles
.size(); i
++) {
139 TileIndex t
= this->tiles
[i
];
146 TileIndex
CalculateCentreTile() const
151 this->AddLineToCalculateCentreTile(x
, y
, count
);
152 if (count
== 0) return INVALID_TILE
;
153 return TileXY(x
/ count
, y
/ count
);
157 struct Plan
: PlanPool::PoolItem
<&_plan_pool
> {
159 PlanLineVector lines
;
167 Plan(Owner owner
= INVALID_OWNER
)
170 this->creation_date
= _date
;
171 this->visible
= false;
172 this->visible_by_all
= false;
173 this->show_lines
= false;
174 this->temp_line
= new PlanLine();
180 for (PlanLineVector::iterator it
= lines
.begin(); it
!= lines
.end(); it
++) {
187 void SetFocus(bool focused
)
189 for (PlanLineVector::iterator it
= lines
.begin(); it
!= lines
.end(); it
++) {
190 (*it
)->SetFocus(focused
);
194 void SetVisibility(bool visible
, bool do_lines
= true)
196 this->visible
= visible
;
198 if (!do_lines
) return;
199 for (PlanLineVector::iterator it
= lines
.begin(); it
!= lines
.end(); it
++) {
200 (*it
)->SetVisibility(visible
);
204 bool ToggleVisibility()
206 this->SetVisibility(!this->visible
);
207 return this->visible
;
212 PlanLine
*pl
= new PlanLine();
213 if (pl
) this->lines
.push_back(pl
);
217 bool StoreTempTile(TileIndex tile
)
219 return this->temp_line
->AppendTile(tile
);
222 bool ValidateNewLine()
225 if (this->temp_line
->tiles
.size() > 1) {
226 uint buffer_length
= 0;
227 const TileIndex
*buffer
= this->temp_line
->Export(&buffer_length
);
229 _current_plan
->SetVisibility(true, false);
230 ret
= DoCommandP(0, _current_plan
->index
, (uint32
) this->temp_line
->tiles
.size(), CMD_ADD_PLAN_LINE
, nullptr, (const char *)buffer
, true, buffer_length
);
233 _current_plan
->temp_line
->MarkDirty();
234 this->temp_line
->Clear();
241 return (this->owner
== _local_company
|| this->visible_by_all
);
246 if (!this->IsListable()) return false;
247 return this->visible
;
252 return !this->name
.empty();
255 bool ToggleVisibilityByAll()
257 if (_current_plan
->owner
== _local_company
) DoCommandP(0, _current_plan
->index
, !this->visible_by_all
, CMD_CHANGE_PLAN_VISIBILITY
);
258 return this->visible_by_all
;
261 const char* GetNameCStr() const
266 TileIndex
CalculateCentreTile() const
271 for (PlanLineVector::const_iterator it
= lines
.begin(); it
!= lines
.end(); it
++) {
272 (*it
)->AddLineToCalculateCentreTile(x
, y
, count
);
274 if (count
== 0) return INVALID_TILE
;
275 return TileXY(x
/ count
, y
/ count
);
279 #define FOR_ALL_PLANS_FROM(var, start) FOR_ALL_ITEMS_FROM(Plan, plan_index, var, start)
280 #define FOR_ALL_PLANS(var) FOR_ALL_PLANS_FROM(var, 0)
282 #endif /* PLANS_BASE_H */