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/widgets/special/resourcebar.h"
21 
22 #include "main.h"
23 #include "settings.h"
24 #include "video.h"
25 #include "input/mouse/mouse.h"
26 #include "output/sound/sounddevice.h"
27 #include "output/sound/soundchannel.h"
28 
29 //------------------------------------------------------------------------------
cResourceBar(const cBox<cPosition> & area,int minValue_,int maxValue_,eResourceBarType type,eOrientationType orientation_,cSoundChunk * clickSound_)30 cResourceBar::cResourceBar (const cBox<cPosition>& area, int minValue_, int maxValue_, eResourceBarType type, eOrientationType orientation_, cSoundChunk* clickSound_) :
31 	cClickableWidget (area),
32 	clickSound (clickSound_),
33 	orientation (orientation_),
34 	additionalArea (orientation == eOrientationType::Horizontal ? 8 : 0, orientation == eOrientationType::Vertical ? 8 : 0),
35 	minValue (minValue_),
36 	maxValue (maxValue_),
37 	currentValue (maxValue_),
38 	fixedMinEnabled (false),
39 	fixedMinValue (minValue_),
40 	fixedMaxEnabled (false),
41 	fixedMaxValue (maxValue_),
42 	inverted (false),
43 	stepSize (1)
44 {
45 	assert (minValue <= maxValue);
46 	assert (minValue >= 0 && maxValue >= 0);
47 
48 	createSurface (type);
49 
50 	resize (getSize() + additionalArea * 2);
51 	move (additionalArea * -1);
52 }
53 
54 //------------------------------------------------------------------------------
draw(SDL_Surface & destination,const cBox<cPosition> & clipRect)55 void cResourceBar::draw (SDL_Surface& destination, const cBox<cPosition>& clipRect)
56 {
57 	if (surface != nullptr && (maxValue - minValue) > 0)
58 	{
59 		const bool horizontal = orientation == eOrientationType::Horizontal;
60 
61 		SDL_Rect src;
62 		src.h = horizontal ? surface->h : (currentValue * surface->h / maxValue);
63 		src.w = horizontal ? (currentValue * surface->w / maxValue) : surface->w;
64 		src.x = horizontal ? surface->w - src.w : 0;
65 		src.y = 0;
66 
67 		SDL_Rect dest;
68 		dest.h = dest.w = 0;
69 		dest.x = getPosition().x() + additionalArea.x();
70 		dest.y = getPosition().y() + (horizontal ? 0 : surface->h - src.h) + additionalArea.y();
71 
72 		if (inverted && horizontal)
73 		{
74 			dest.x += surface->w - src.w;
75 			src.x = 0;
76 		}
77 
78 		SDL_BlitSurface (surface.get(), &src, &destination, &dest);
79 	}
80 
81 	cClickableWidget::draw (destination, clipRect);
82 }
83 
84 //------------------------------------------------------------------------------
setType(eResourceBarType type)85 void cResourceBar::setType (eResourceBarType type)
86 {
87 	createSurface (type);
88 }
89 
90 //------------------------------------------------------------------------------
setStepSize(int stepSize_)91 void cResourceBar::setStepSize (int stepSize_)
92 {
93 	stepSize = stepSize_;
94 	setValue (getValue());
95 }
96 
97 //------------------------------------------------------------------------------
getMinValue() const98 int cResourceBar::getMinValue() const
99 {
100 	return minValue;
101 }
102 
103 //------------------------------------------------------------------------------
setMinValue(int minValue_)104 void cResourceBar::setMinValue (int minValue_)
105 {
106 	minValue = minValue_;
107 	setValue (getValue());
108 }
109 
110 //------------------------------------------------------------------------------
getMaxValue() const111 int cResourceBar::getMaxValue() const
112 {
113 	return maxValue;
114 }
115 
116 //------------------------------------------------------------------------------
setMaxValue(int maxValue_)117 void cResourceBar::setMaxValue (int maxValue_)
118 {
119 	maxValue = maxValue_;
120 	setValue (getValue());
121 }
122 
123 //------------------------------------------------------------------------------
getFixedMinValue() const124 int cResourceBar::getFixedMinValue() const
125 {
126 	return fixedMinEnabled ? fixedMinValue : minValue;
127 }
128 
129 //------------------------------------------------------------------------------
setFixedMinValue(int fixedMinValue_)130 void cResourceBar::setFixedMinValue (int fixedMinValue_)
131 {
132 	fixedMinValue = std::max (fixedMinValue_, minValue);
133 	fixedMinEnabled = true;
134 	setValue (getValue());
135 }
136 
137 //------------------------------------------------------------------------------
getFixedMaxValue() const138 int cResourceBar::getFixedMaxValue() const
139 {
140 	return fixedMaxEnabled ? fixedMaxValue : maxValue;
141 }
142 
143 //------------------------------------------------------------------------------
setFixedMaxValue(int fixedMaxValue_)144 void cResourceBar::setFixedMaxValue (int fixedMaxValue_)
145 {
146 	fixedMaxValue = std::min (fixedMaxValue_, maxValue);
147 	fixedMaxEnabled = true;
148 	setValue (getValue());
149 }
150 
151 //------------------------------------------------------------------------------
isInverted() const152 bool cResourceBar::isInverted() const
153 {
154 	return inverted;
155 }
156 
157 //------------------------------------------------------------------------------
setInverted(bool inverted_)158 void cResourceBar::setInverted (bool inverted_)
159 {
160 	inverted = inverted_;
161 }
162 
163 //------------------------------------------------------------------------------
getValue() const164 int cResourceBar::getValue() const
165 {
166 	return currentValue;
167 }
168 
169 //------------------------------------------------------------------------------
setValue(int value)170 void cResourceBar::setValue (int value)
171 {
172 	value = std::max (minValue, value);
173 	value = std::min (maxValue, value);
174 
175 	if (value < (maxValue / stepSize) * stepSize && value % stepSize != 0)
176 	{
177 		value = Round ((float)value / stepSize) * stepSize;
178 	}
179 
180 	value = std::max (getFixedMinValue(), value);
181 	value = std::min (getFixedMaxValue(), value);
182 
183 	if (value != currentValue)
184 	{
185 		currentValue = value;
186 		valueChanged();
187 	}
188 }
189 
190 //------------------------------------------------------------------------------
increase(int offset)191 void cResourceBar::increase (int offset)
192 {
193 	setValue (getValue() + offset);
194 }
195 
196 //------------------------------------------------------------------------------
decrease(int offset)197 void cResourceBar::decrease (int offset)
198 {
199 	increase (-offset);
200 }
201 
202 //------------------------------------------------------------------------------
handleClicked(cApplication & application,cMouse & mouse,eMouseButtonType button)203 bool cResourceBar::handleClicked (cApplication& application, cMouse& mouse, eMouseButtonType button)
204 {
205 	if (button == eMouseButtonType::Left)
206 	{
207 		if (clickSound) cSoundDevice::getInstance().playSoundEffect (*clickSound);
208 
209 		const auto valueRange = maxValue - minValue;
210 		switch (orientation)
211 		{
212 			default:
213 			case eOrientationType::Horizontal:
214 				setValue (minValue + (mouse.getPosition().x() - (getPosition().x() + additionalArea.x())) * valueRange / (getSize().x() - additionalArea.x() * 2));
215 				break;
216 			case eOrientationType::Vertical:
217 				setValue (minValue + valueRange - (mouse.getPosition().y() - (getPosition().y() + additionalArea.y())) * valueRange / (getSize().y() - additionalArea.y() * 2));
218 				break;
219 		}
220 
221 		return true;
222 	}
223 	return false;
224 }
225 
226 //------------------------------------------------------------------------------
createSurface(eResourceBarType type)227 void cResourceBar::createSurface (eResourceBarType type)
228 {
229 	cPosition srcPosition;
230 	switch (orientation)
231 	{
232 		default:
233 		case eOrientationType::Horizontal:
234 			switch (type)
235 			{
236 				default:
237 				case eResourceBarType::Metal:
238 					srcPosition.x() = 156;
239 					srcPosition.y() = 339;
240 					break;
241 				case eResourceBarType::Oil:
242 					srcPosition.x() = 156;
243 					srcPosition.y() = 369;
244 					break;
245 				case eResourceBarType::Gold:
246 					srcPosition.x() = 156;
247 					srcPosition.y() = 400;
248 					break;
249 				case eResourceBarType::Blocked:
250 					srcPosition.x() = 156;
251 					srcPosition.y() = 307;
252 					break;
253 				case eResourceBarType::MetalSlim:
254 					srcPosition.x() = 156;
255 					srcPosition.y() = 256;
256 					break;
257 				case eResourceBarType::OilSlim:
258 					srcPosition.x() = 156;
259 					srcPosition.y() = 273;
260 					break;
261 				case eResourceBarType::GoldSlim:
262 					srcPosition.x() = 156;
263 					srcPosition.y() = 290;
264 					break;
265 			}
266 			break;
267 		case eOrientationType::Vertical:
268 			switch (type)
269 			{
270 				default:
271 				case eResourceBarType::Metal:
272 					srcPosition.x() = 135;
273 					srcPosition.y() = 336;
274 					break;
275 				case eResourceBarType::Oil:
276 					srcPosition.x() = 400;
277 					srcPosition.y() = 348;
278 					break;
279 				case eResourceBarType::Gold:
280 					srcPosition.x() = 114;
281 					srcPosition.y() = 336;
282 					break;
283 			}
284 			break;
285 	}
286 
287 	cPosition size;
288 	switch (orientation)
289 	{
290 		default:
291 		case eOrientationType::Horizontal:
292 			switch (type)
293 			{
294 				default:
295 				case eResourceBarType::Metal:
296 				case eResourceBarType::Oil:
297 				case eResourceBarType::Gold:
298 				case eResourceBarType::Blocked:
299 					size.x() = 240;
300 					size.y() = 30;
301 					break;
302 				case eResourceBarType::MetalSlim:
303 				case eResourceBarType::OilSlim:
304 				case eResourceBarType::GoldSlim:
305 					size.x() = 223;
306 					size.y() = 16;
307 					break;
308 			}
309 			break;
310 		case eOrientationType::Vertical:
311 			size.x() = 20;
312 			size.y() = 115;
313 			break;
314 	}
315 
316 	surface = AutoSurface (SDL_CreateRGBSurface (0, size.x(), size.y(), Video.getColDepth(), 0, 0, 0, 0));
317 
318 	SDL_SetColorKey (surface.get(), SDL_TRUE, 0xFF00FF);
319 	SDL_FillRect (surface.get(), nullptr, 0xFF00FF);
320 
321 	SDL_Rect src = {srcPosition.x(), srcPosition.y(), size.x(), size.y()};
322 	SDL_BlitSurface (GraphicsData.gfx_hud_stuff.get(), &src, surface.get(), nullptr);
323 }
324