1 /*
2  * Copyright 2010-2014 OpenXcom Developers.
3  *
4  * This file is part of OpenXcom.
5  *
6  * OpenXcom is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * OpenXcom is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "SelectDestinationState.h"
20 #include <cmath>
21 #include "../Engine/Game.h"
22 #include "../Engine/Screen.h"
23 #include "../Engine/Action.h"
24 #include "../Resource/ResourcePack.h"
25 #include "../Engine/Language.h"
26 #include "../Engine/Palette.h"
27 #include "../Engine/Surface.h"
28 #include "../Interface/Window.h"
29 #include "Globe.h"
30 #include "../Interface/Text.h"
31 #include "../Interface/TextButton.h"
32 #include "../Savegame/Waypoint.h"
33 #include "MultipleTargetsState.h"
34 #include "../Savegame/SavedGame.h"
35 #include "../Savegame/Craft.h"
36 #include "../Ruleset/RuleCraft.h"
37 #include "ConfirmCydoniaState.h"
38 #include "../Engine/Options.h"
39 
40 namespace OpenXcom
41 {
42 
43 /**
44  * Initializes all the elements in the Select Destination window.
45  * @param game Pointer to the core game.
46  * @param craft Pointer to the craft to target.
47  * @param globe Pointer to the Geoscape globe.
48  */
SelectDestinationState(Game * game,Craft * craft,Globe * globe)49 SelectDestinationState::SelectDestinationState(Game *game, Craft *craft, Globe *globe) : State(game), _craft(craft), _globe(globe)
50 {
51 	int dx = _game->getScreen()->getDX();
52 	int dy = _game->getScreen()->getDY();
53 	_screen = false;
54 
55 	// Create objects
56 	_btnRotateLeft = new InteractiveSurface(12, 10, 259 + dx * 2, 176 + dy);
57 	_btnRotateRight = new InteractiveSurface(12, 10, 283 + dx * 2, 176 + dy);
58 	_btnRotateUp = new InteractiveSurface(13, 12, 271 + dx * 2, 162 + dy);
59 	_btnRotateDown = new InteractiveSurface(13, 12, 271 + dx * 2, 187 + dy);
60 	_btnZoomIn = new InteractiveSurface(23, 23, 295 + dx * 2, 156 + dy);
61 	_btnZoomOut = new InteractiveSurface(13, 17, 300 + dx * 2, 182 + dy);
62 
63 	_window = new Window(this, 256, 28, 0, 0);
64 	_window->setX(dx);
65 	_window->setDY(0);
66 	_btnCancel = new TextButton(60, 12, 110 + dx, 8);
67 	_btnCydonia = new TextButton(60, 12, 180 + dx, 8);
68 	_txtTitle = new Text(100, 16, 10 + dx, 6);
69 
70 	// Set palette
71 	setPalette("PAL_GEOSCAPE", 0);
72 
73 	add(_btnRotateLeft);
74 	add(_btnRotateRight);
75 	add(_btnRotateUp);
76 	add(_btnRotateDown);
77 	add(_btnZoomIn);
78 	add(_btnZoomOut);
79 
80 	add(_window);
81 	add(_btnCancel);
82 	add(_btnCydonia);
83 	add(_txtTitle);
84 
85 	// Set up objects
86 	_globe->onMouseClick((ActionHandler)&SelectDestinationState::globeClick);
87 
88 	_btnRotateLeft->onMousePress((ActionHandler)&SelectDestinationState::btnRotateLeftPress);
89 	_btnRotateLeft->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease);
90 	_btnRotateLeft->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateLeftPress, Options::keyGeoLeft);
91 	_btnRotateLeft->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease, Options::keyGeoLeft);
92 
93 	_btnRotateRight->onMousePress((ActionHandler)&SelectDestinationState::btnRotateRightPress);
94 	_btnRotateRight->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease);
95 	_btnRotateRight->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateRightPress, Options::keyGeoRight);
96 	_btnRotateRight->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease, Options::keyGeoRight);
97 
98 	_btnRotateUp->onMousePress((ActionHandler)&SelectDestinationState::btnRotateUpPress);
99 	_btnRotateUp->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease);
100 	_btnRotateUp->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateUpPress, Options::keyGeoUp);
101 	_btnRotateUp->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease, Options::keyGeoUp);
102 
103 	_btnRotateDown->onMousePress((ActionHandler)&SelectDestinationState::btnRotateDownPress);
104 	_btnRotateDown->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease);
105 	_btnRotateDown->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateDownPress, Options::keyGeoDown);
106 	_btnRotateDown->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease, Options::keyGeoDown);
107 
108 	_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, SDL_BUTTON_LEFT);
109 	_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInRightClick, SDL_BUTTON_RIGHT);
110 	_btnZoomIn->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, Options::keyGeoZoomIn);
111 
112 	_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, SDL_BUTTON_LEFT);
113 	_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutRightClick, SDL_BUTTON_RIGHT);
114 	_btnZoomOut->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, Options::keyGeoZoomOut);
115 
116 	// dirty hacks to get the rotate buttons to work in "classic" style
117 	_btnRotateLeft->setListButton();
118 	_btnRotateRight->setListButton();
119 	_btnRotateUp->setListButton();
120 	_btnRotateDown->setListButton();
121 
122 	_window->setColor(Palette::blockOffset(15)-1);
123 	_window->setBackground(_game->getResourcePack()->getSurface("BACK01.SCR"));
124 
125 	_btnCancel->setColor(Palette::blockOffset(8)+5);
126 	_btnCancel->setText(tr("STR_CANCEL_UC"));
127 	_btnCancel->onMouseClick((ActionHandler)&SelectDestinationState::btnCancelClick);
128 	_btnCancel->onKeyboardPress((ActionHandler)&SelectDestinationState::btnCancelClick, Options::keyCancel);
129 
130 	_txtTitle->setColor(Palette::blockOffset(15)-1);
131 	_txtTitle->setText(tr("STR_SELECT_DESTINATION"));
132 	_txtTitle->setVerticalAlign(ALIGN_MIDDLE);
133 	_txtTitle->setWordWrap(true);
134 
135 	if (!_craft->getRules()->getSpacecraft() || !_game->getSavedGame()->isResearched("STR_CYDONIA_OR_BUST"))
136 	{
137 		_btnCydonia->setVisible(false);
138 	}
139 	else
140 	{
141 		_btnCydonia->setColor(Palette::blockOffset(8)+5);
142 		_btnCydonia->setText(tr("STR_CYDONIA"));
143 		_btnCydonia->onMouseClick((ActionHandler)&SelectDestinationState::btnCydoniaClick);
144 	}
145 }
146 
147 /**
148  *
149  */
~SelectDestinationState()150 SelectDestinationState::~SelectDestinationState()
151 {
152 
153 }
154 
155 /**
156  * Stop the globe movement.
157  */
init()158 void SelectDestinationState::init()
159 {
160 	State::init();
161 	_globe->rotateStop();
162 }
163 
164 /**
165  * Runs the globe rotation timer.
166  */
think()167 void SelectDestinationState::think()
168 {
169 	State::think();
170 	_globe->think();
171 }
172 
173 /**
174  * Handles the globe.
175  * @param action Pointer to an action.
176  */
handle(Action * action)177 void SelectDestinationState::handle(Action *action)
178 {
179 	State::handle(action);
180 	_globe->handle(action, this);
181 }
182 
183 /**
184  * Processes any left-clicks for picking a target,
185  * or right-clicks to scroll the globe.
186  * @param action Pointer to an action.
187  */
globeClick(Action * action)188 void SelectDestinationState::globeClick(Action *action)
189 {
190 	double lon, lat;
191 	int mouseX = (int)floor(action->getAbsoluteXMouse()), mouseY = (int)floor(action->getAbsoluteYMouse());
192 	_globe->cartToPolar(mouseX, mouseY, &lon, &lat);
193 
194 	// Ignore window clicks
195 	if (mouseY < 28)
196 	{
197 		return;
198 	}
199 
200 	// Clicking on a valid target
201 	if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
202 	{
203 		std::vector<Target*> v = _globe->getTargets(mouseX, mouseY, true);
204 		if (v.empty())
205 		{
206 			Waypoint *w = new Waypoint();
207 			w->setLongitude(lon);
208 			w->setLatitude(lat);
209 			v.push_back(w);
210 		}
211 		_game->pushState(new MultipleTargetsState(_game, v, _craft, 0));
212 	}
213 }
214 
215 /**
216  * Starts rotating the globe to the left.
217  * @param action Pointer to an action.
218  */
btnRotateLeftPress(Action *)219 void SelectDestinationState::btnRotateLeftPress(Action *)
220 {
221 	_globe->rotateLeft();
222 }
223 
224 /**
225  * Stops rotating the globe to the left.
226  * @param action Pointer to an action.
227  */
btnRotateLeftRelease(Action *)228 void SelectDestinationState::btnRotateLeftRelease(Action *)
229 {
230 	_globe->rotateStopLon();
231 }
232 
233 /**
234  * Starts rotating the globe to the right.
235  * @param action Pointer to an action.
236  */
btnRotateRightPress(Action *)237 void SelectDestinationState::btnRotateRightPress(Action *)
238 {
239 	_globe->rotateRight();
240 }
241 
242 /**
243  * Stops rotating the globe to the right.
244  * @param action Pointer to an action.
245  */
btnRotateRightRelease(Action *)246 void SelectDestinationState::btnRotateRightRelease(Action *)
247 {
248 	_globe->rotateStopLon();
249 }
250 
251 /**
252  * Starts rotating the globe upwards.
253  * @param action Pointer to an action.
254  */
btnRotateUpPress(Action *)255 void SelectDestinationState::btnRotateUpPress(Action *)
256 {
257 	_globe->rotateUp();
258 }
259 
260 /**
261  * Stops rotating the globe upwards.
262  * @param action Pointer to an action.
263  */
btnRotateUpRelease(Action *)264 void SelectDestinationState::btnRotateUpRelease(Action *)
265 {
266 	_globe->rotateStopLat();
267 }
268 
269 /**
270  * Starts rotating the globe downwards.
271  * @param action Pointer to an action.
272  */
btnRotateDownPress(Action *)273 void SelectDestinationState::btnRotateDownPress(Action *)
274 {
275 	_globe->rotateDown();
276 }
277 
278 /**
279  * Stops rotating the globe downwards.
280  * @param action Pointer to an action.
281  */
btnRotateDownRelease(Action *)282 void SelectDestinationState::btnRotateDownRelease(Action *)
283 {
284 	_globe->rotateStopLat();
285 }
286 
287 /**
288  * Zooms into the globe.
289  * @param action Pointer to an action.
290  */
btnZoomInLeftClick(Action *)291 void SelectDestinationState::btnZoomInLeftClick(Action *)
292 {
293 	_globe->zoomIn();
294 }
295 
296 /**
297  * Zooms the globe maximum.
298  * @param action Pointer to an action.
299  */
btnZoomInRightClick(Action *)300 void SelectDestinationState::btnZoomInRightClick(Action *)
301 {
302 	_globe->zoomMax();
303 }
304 
305 /**
306  * Zooms out of the globe.
307  * @param action Pointer to an action.
308  */
btnZoomOutLeftClick(Action *)309 void SelectDestinationState::btnZoomOutLeftClick(Action *)
310 {
311 	_globe->zoomOut();
312 }
313 
314 /**
315  * Zooms the globe minimum.
316  * @param action Pointer to an action.
317  */
btnZoomOutRightClick(Action *)318 void SelectDestinationState::btnZoomOutRightClick(Action *)
319 {
320 	_globe->zoomMin();
321 }
322 
323 /**
324  * Returns to the previous screen.
325  * @param action Pointer to an action.
326  */
btnCancelClick(Action *)327 void SelectDestinationState::btnCancelClick(Action *)
328 {
329 	_game->popState();
330 }
331 
btnCydoniaClick(Action *)332 void SelectDestinationState::btnCydoniaClick(Action *)
333 {
334 	if (_craft->getNumSoldiers() > 0 || _craft->getNumVehicles() > 0)
335 	{
336 		_game->pushState(new ConfirmCydoniaState(_game, _craft));
337 	}
338 }
339 
340 /**
341  * Updates the scale.
342  * @param dX delta of X;
343  * @param dY delta of Y;
344  */
resize(int & dX,int & dY)345 void SelectDestinationState::resize(int &dX, int &dY)
346 {
347 	for (std::vector<Surface*>::const_iterator i = _surfaces.begin(); i != _surfaces.end(); ++i)
348 	{
349 		(*i)->setX((*i)->getX() + dX / 2);
350 		if (*i != _window && *i != _btnCancel && *i != _txtTitle && *i != _btnCydonia)
351 		{
352 			(*i)->setY((*i)->getY() + dY / 2);
353 		}
354 	}
355 }
356 }
357