1 /***************************************************************************
2 * Mechanized Assault and Exploration Reloaded Projectfile *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 #include "ui/graphical/menu/windows/windowstorage/windowstorage.h"
21 #include "pcx.h"
22 #include "main.h"
23 #include "video.h"
24 #include "game/data/units/unit.h"
25 #include "game/data/units/building.h"
26 #include "game/data/units/vehicle.h"
27 #include "game/data/base/base.h"
28 #include "game/data/player/player.h"
29 #include "ui/graphical/menu/widgets/label.h"
30 #include "ui/graphical/menu/widgets/pushbutton.h"
31 #include "ui/graphical/menu/widgets/image.h"
32 #include "ui/graphical/menu/widgets/special/resourcebar.h"
33 #include "ui/graphical/menu/dialogs/dialogok.h"
34 #include "ui/graphical/application.h"
35 #include "ui/graphical/game/widgets/unitdetailsstored.h"
36 #include "ui/graphical/game/widgets/turntimeclockwidget.h"
37
38 //------------------------------------------------------------------------------
cWindowStorage(const cUnit & unit_,std::shared_ptr<const cTurnTimeClock> turnTimeClock)39 cWindowStorage::cWindowStorage (const cUnit& unit_, std::shared_ptr<const cTurnTimeClock> turnTimeClock) :
40 cWindow (nullptr),
41 unit (unit_),
42 canRepairReloadUpgrade (unit_.isABuilding()),
43 canStorePlanes (unit_.data.storeUnitsImageType == sUnitData::STORE_UNIT_IMG_PLANE),
44 canStoreShips (unit_.data.storeUnitsImageType == sUnitData::STORE_UNIT_IMG_SHIP),
45 columns (canStorePlanes ? 2 : 3),
46 page (0)
47 {
48 AutoSurface background (LoadPCX (GFXOD_STORAGE));
49 if (!canStorePlanes)
50 {
51 AutoSurface surface (LoadPCX (GFXOD_STORAGE_GROUND));
52 SDL_BlitSurface (surface.get(), nullptr, background.get(), nullptr);
53 }
54 setSurface (std::move (background));
55
56 auto turnTimeClockWidget = addChild (std::make_unique<cTurnTimeClockWidget> (cBox<cPosition> (cPosition (523, 17), cPosition (523 + 62, 17 + 10))));
57 turnTimeClockWidget->setTurnTimeClock (std::move (turnTimeClock));
58
59 //
60 // Units
61 //
62 const int stepX = canStorePlanes ? 227 : 155;
63 const int stepImageX = canStorePlanes ? 227 : 155;
64 const int startX = canStorePlanes ? 42 : 8;
65 const int nameLabelX = canStorePlanes ? 190 : 118;
66
67 for (size_t x = 0; x < columns; x++)
68 {
69 for (size_t y = 0; y < maxRows; y++)
70 {
71 const auto index = x + y * columns;
72 activateButtons[index] = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (startX + x * stepX, 191 + y * 236), ePushButtonType::Angular, lngPack.i18n ("Text~Others~Active"), FONT_LATIN_NORMAL));
73 signalConnectionManager.connect (activateButtons[index]->clicked, std::bind (&cWindowStorage::activateClicked, this, index));
74
75 reloadButtons[index] = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (startX + x * stepX, 191 + 25 + y * 236), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Reload") : "", FONT_LATIN_NORMAL));
76 signalConnectionManager.connect (reloadButtons[index]->clicked, std::bind (&cWindowStorage::reloadClicked, this, index));
77
78 repairButtons[index] = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (75 + startX + x * stepX, 191 + y * 236), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Repair") : "", FONT_LATIN_NORMAL));
79 signalConnectionManager.connect (repairButtons[index]->clicked, std::bind (&cWindowStorage::repairClicked, this, index));
80
81 upgradeButtons[index] = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (75 + startX + x * stepX, 191 + 25 + y * 236), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Upgrade") : "", FONT_LATIN_NORMAL));
82 signalConnectionManager.connect (upgradeButtons[index]->clicked, std::bind (&cWindowStorage::upgradeClicked, this, index));
83
84 unitImages[index] = addChild (std::make_unique<cImage> (getPosition() + cPosition (17 + x * stepImageX, 9 + y * 236)));
85 unitNames[index] = addChild (std::make_unique<cLabel> (cBox<cPosition> (getPosition() + cPosition (17 + x * stepImageX + 5, 9 + y * 236 + 5), getPosition() + cPosition (17 + x * stepImageX + 5 + nameLabelX, 9 + y * 236 + 5 + 118)), ""));
86 unitNames[index]->setWordWrap (true);
87
88 unitDetails[index] = addChild (std::make_unique<cUnitDetailsStored> (cBox<cPosition> (getPosition() + cPosition (17 + x * stepImageX + (canStorePlanes ? 35 : 0), 145 + y * 236), getPosition() + cPosition (17 + x * stepImageX + 130 + (canStorePlanes ? 35 : 0), 145 + y * 236 + 40))));
89 }
90 }
91
92 //
93 // Metal Bar
94 //
95 auto metalValue = 0;
96 if (unit.isABuilding())
97 {
98 const auto& building = static_cast<const cBuilding&> (unit);
99
100 metalValue = building.SubBase->getMetal();
101
102 signalConnectionManager.connect (building.SubBase->metalChanged, [&]()
103 {
104 metalBar->setValue (building.SubBase->getMetal());
105 });
106 }
107
108 metalBarAmountLabel = addChild (std::make_unique<cLabel> (cBox<cPosition> (getPosition() + cPosition (536, 85), getPosition() + cPosition (536 + 40, 85 + 10)), iToStr (metalValue), FONT_LATIN_NORMAL, eAlignmentType::CenterHorizontal));
109 metalBar = addChild (std::make_unique<cResourceBar> (cBox<cPosition> (getPosition() + cPosition (546, 106), getPosition() + cPosition (546 + 20, 106 + 115)), 0, metalValue, eResourceBarType::Metal, eOrientationType::Vertical));
110 signalConnectionManager.connect (metalBar->valueChanged, [&]() { metalBarAmountLabel->setText (iToStr (metalBar->getValue())); });
111 metalBar->disable();
112
113 //
114 // Buttons
115 //
116 upButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (504, 426), ePushButtonType::ArrowUpBig));
117 signalConnectionManager.connect (upButton->clicked, std::bind (&cWindowStorage::upClicked, this));
118
119 downButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (532, 426), ePushButtonType::ArrowDownBig));
120 signalConnectionManager.connect (downButton->clicked, std::bind (&cWindowStorage::downClicked, this));
121
122 activateAllButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (518, 246), ePushButtonType::Angular, lngPack.i18n ("Text~Others~Active"), FONT_LATIN_NORMAL));
123 signalConnectionManager.connect (activateAllButton->clicked, std::bind (&cWindowStorage::activateAllClicked, this));
124
125 reloadAllButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (518, 246 + 25), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Reload") : "", FONT_LATIN_NORMAL));
126 signalConnectionManager.connect (reloadAllButton->clicked, std::bind (&cWindowStorage::reloadAllClicked, this));
127
128 repairAllButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (518, 246 + 25 * 2), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Repair") : "", FONT_LATIN_NORMAL));
129 signalConnectionManager.connect (repairAllButton->clicked, std::bind (&cWindowStorage::repairAllClicked, this));
130
131 upgradeAllButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (518, 246 + 25 * 3), ePushButtonType::Angular, canRepairReloadUpgrade ? lngPack.i18n ("Text~Others~Upgrade") : "", FONT_LATIN_NORMAL));
132 signalConnectionManager.connect (upgradeAllButton->clicked, std::bind (&cWindowStorage::upgradeAllClicked, this));
133
134 auto doneButton = addChild (std::make_unique<cPushButton> (getPosition() + cPosition (518, 371), ePushButtonType::Angular, lngPack.i18n ("Text~Others~Done"), FONT_LATIN_NORMAL));
135 signalConnectionManager.connect (doneButton->clicked, std::bind (&cWindowStorage::doneClicked, this));
136
137 updateUnitsWidgets();
138 updateGlobalButtons();
139 updateUpDownButtons();
140
141 signalConnectionManager.connect (unit.destroyed, std::bind (&cWindowStorage::closeOnUnitDestruction, this));
142 }
143
144 //------------------------------------------------------------------------------
updateUnitButtons(const cVehicle & storedUnit,size_t positionIndex)145 void cWindowStorage::updateUnitButtons (const cVehicle& storedUnit, size_t positionIndex)
146 {
147 const auto& upgraded = *storedUnit.getOwner()->getUnitDataCurrentVersion (storedUnit.data.ID);
148
149 activateButtons[positionIndex]->unlock();
150 if (storedUnit.data.getAmmo() != storedUnit.data.getAmmoMax() && metalBar->getValue() >= 1) reloadButtons[positionIndex]->unlock();
151 else reloadButtons[positionIndex]->lock();
152 if (storedUnit.data.getHitpoints() != storedUnit.data.getHitpointsMax() && metalBar->getValue() >= 1) repairButtons[positionIndex]->unlock();
153 else repairButtons[positionIndex]->lock();
154 if (storedUnit.data.getVersion() != upgraded.getVersion() && metalBar->getValue() >= 1) upgradeButtons[positionIndex]->unlock();
155 else upgradeButtons[positionIndex]->lock();
156 }
157
158 //------------------------------------------------------------------------------
updateUnitName(const cVehicle & storedUnit,size_t positionIndex)159 void cWindowStorage::updateUnitName (const cVehicle& storedUnit, size_t positionIndex)
160 {
161 auto name = storedUnit.getDisplayName();
162
163 const auto& upgraded = *storedUnit.getOwner()->getUnitDataCurrentVersion (storedUnit.data.ID);
164 if (storedUnit.data.getVersion() != upgraded.getVersion())
165 {
166 name += "\n(" + lngPack.i18n ("Text~Comp~Dated") + ")";
167 }
168 unitNames[positionIndex]->setText (name);
169 }
170
171 //------------------------------------------------------------------------------
updateUnitsWidgets()172 void cWindowStorage::updateUnitsWidgets()
173 {
174 unitsSignalConnectionManager.disconnectAll();
175
176 for (size_t x = 0; x < columns; x++)
177 {
178 for (size_t y = 0; y < maxRows; y++)
179 {
180 const auto positionIndex = x + y * columns;
181 const auto unitIndex = page * columns * maxRows + positionIndex;
182
183 if (unitIndex < unit.storedUnits.size())
184 {
185 const auto& storedUnit = *unit.storedUnits[unitIndex];
186
187 AutoSurface surface (SDL_CreateRGBSurface (0, storedUnit.uiData->storage->w, storedUnit.uiData->storage->h, Video.getColDepth(), 0, 0, 0, 0));
188 SDL_BlitSurface (storedUnit.uiData->storage.get(), nullptr, surface.get(), nullptr);
189 unitImages[positionIndex]->setImage (surface.get());
190
191 unitDetails[positionIndex]->setUnit (&storedUnit);
192
193 updateUnitName (storedUnit, positionIndex);
194 updateUnitButtons (storedUnit, positionIndex);
195
196 unitsSignalConnectionManager.connect (storedUnit.data.versionChanged, std::bind (&cWindowStorage::updateUnitName, this, std::ref (storedUnit), positionIndex));
197
198 unitsSignalConnectionManager.connect (storedUnit.data.hitpointsChanged, std::bind (&cWindowStorage::updateUnitButtons, this, std::ref (storedUnit), positionIndex));
199 unitsSignalConnectionManager.connect (storedUnit.data.ammoChanged, std::bind (&cWindowStorage::updateUnitButtons, this, std::ref (storedUnit), positionIndex));
200 unitsSignalConnectionManager.connect (storedUnit.data.hitpointsMaxChanged, std::bind (&cWindowStorage::updateUnitButtons, this, std::ref (storedUnit), positionIndex));
201 unitsSignalConnectionManager.connect (storedUnit.data.ammoMaxChanged, std::bind (&cWindowStorage::updateUnitButtons, this, std::ref (storedUnit), positionIndex));
202 unitsSignalConnectionManager.connect (storedUnit.data.versionChanged, std::bind (&cWindowStorage::updateUnitButtons, this, std::ref (storedUnit), positionIndex));
203
204 unitsSignalConnectionManager.connect (storedUnit.data.hitpointsChanged, std::bind (&cWindowStorage::updateGlobalButtons, this));
205 unitsSignalConnectionManager.connect (storedUnit.data.ammoChanged, std::bind (&cWindowStorage::updateGlobalButtons, this));
206 unitsSignalConnectionManager.connect (storedUnit.data.hitpointsMaxChanged, std::bind (&cWindowStorage::updateGlobalButtons, this));
207 unitsSignalConnectionManager.connect (storedUnit.data.ammoMaxChanged, std::bind (&cWindowStorage::updateGlobalButtons, this));
208 unitsSignalConnectionManager.connect (storedUnit.data.versionChanged, std::bind (&cWindowStorage::updateGlobalButtons, this));
209 }
210 else
211 {
212 unitNames[positionIndex]->setText ("");
213
214 SDL_Surface* srcSurface;
215 if (canStoreShips) srcSurface = GraphicsData.gfx_edock.get();
216 else if (canStorePlanes) srcSurface = GraphicsData.gfx_ehangar.get();
217 else srcSurface = GraphicsData.gfx_edepot.get();
218
219 AutoSurface surface (SDL_CreateRGBSurface (0, srcSurface->w, srcSurface->h, Video.getColDepth(), 0, 0, 0, 0));
220 SDL_BlitSurface (srcSurface, nullptr, surface.get(), nullptr);
221 unitImages[positionIndex]->setImage (surface.get());
222
223 unitDetails[positionIndex]->setUnit (nullptr);
224
225 activateButtons[positionIndex]->lock();
226 reloadButtons[positionIndex]->lock();
227 repairButtons[positionIndex]->lock();
228 upgradeButtons[positionIndex]->lock();
229 }
230 }
231 }
232 }
233
234 //------------------------------------------------------------------------------
updateGlobalButtons()235 void cWindowStorage::updateGlobalButtons()
236 {
237 if (unit.storedUnits.empty()) activateAllButton->lock();
238 else activateAllButton->unlock();
239
240 reloadAllButton->lock();
241 repairAllButton->lock();
242 upgradeAllButton->lock();
243 if (canRepairReloadUpgrade && metalBar->getValue() >= 1)
244 {
245 for (size_t i = 0; i != unit.storedUnits.size(); ++i)
246 {
247 const auto& vehicle = *unit.storedUnits[i];
248 const auto& upgraded = *vehicle.getOwner()->getUnitDataCurrentVersion (vehicle.data.ID);
249
250 if (vehicle.data.getAmmo() != vehicle.data.getAmmoMax()) reloadAllButton->unlock();
251 if (vehicle.data.getHitpoints() != vehicle.data.getHitpointsMax()) repairAllButton->unlock();
252 if (vehicle.data.getVersion() != upgraded.getVersion()) upgradeAllButton->unlock();
253 }
254 }
255 }
256
257 //------------------------------------------------------------------------------
updateUpDownButtons()258 void cWindowStorage::updateUpDownButtons()
259 {
260 if (page > 0) upButton->unlock();
261 else upButton->lock();
262
263 const auto pageSize = columns * maxRows;
264 const auto maxPage = unit.storedUnits.size() / pageSize;
265
266 if (page < maxPage) downButton->unlock();
267 else downButton->lock();
268 }
269
270 //------------------------------------------------------------------------------
upClicked()271 void cWindowStorage::upClicked()
272 {
273 assert (page > 0);
274 --page;
275 updateUpDownButtons();
276 updateUnitsWidgets();
277 }
278
279 //------------------------------------------------------------------------------
downClicked()280 void cWindowStorage::downClicked()
281 {
282 ++page;
283 updateUpDownButtons();
284 updateUnitsWidgets();
285 }
286
287 //------------------------------------------------------------------------------
activateClicked(size_t index)288 void cWindowStorage::activateClicked (size_t index)
289 {
290 activate (page * columns * maxRows + index);
291 }
292
293 //------------------------------------------------------------------------------
reloadClicked(size_t index)294 void cWindowStorage::reloadClicked (size_t index)
295 {
296 reload (page * columns * maxRows + index);
297 }
298
299 //------------------------------------------------------------------------------
repairClicked(size_t index)300 void cWindowStorage::repairClicked (size_t index)
301 {
302 repair (page * columns * maxRows + index);
303 }
304
305 //------------------------------------------------------------------------------
upgradeClicked(size_t index)306 void cWindowStorage::upgradeClicked (size_t index)
307 {
308 upgrade (page * columns * maxRows + index);
309 }
310
311 //------------------------------------------------------------------------------
activateAllClicked()312 void cWindowStorage::activateAllClicked()
313 {
314 activateAll();
315 }
316
317 //------------------------------------------------------------------------------
reloadAllClicked()318 void cWindowStorage::reloadAllClicked()
319 {
320 reloadAll();
321 }
322
323 //------------------------------------------------------------------------------
repairAllClicked()324 void cWindowStorage::repairAllClicked()
325 {
326 repairAll();
327 }
328
329 //------------------------------------------------------------------------------
upgradeAllClicked()330 void cWindowStorage::upgradeAllClicked()
331 {
332 upgradeAll();
333 }
334
335 //------------------------------------------------------------------------------
doneClicked()336 void cWindowStorage::doneClicked()
337 {
338 close();
339 }
340
341 //------------------------------------------------------------------------------
closeOnUnitDestruction()342 void cWindowStorage::closeOnUnitDestruction()
343 {
344 close();
345 auto application = getActiveApplication();
346 if (application)
347 {
348 application->show (std::make_shared<cDialogOk> (lngPack.i18n ("Text~Others~Unit_destroyed")));
349 }
350 }
351