1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name icons.cpp - The icons. */
12 //
13 // (c) Copyright 1998-2012 by Lutz Sammer and Jimmy Salmon
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #include "icons.h"
39
40 #include "menus.h"
41 #include "player.h"
42 #include "translate.h"
43 #include "ui.h"
44 #include "unit.h"
45 #include "video.h"
46
47 #include <map>
48
49 /*----------------------------------------------------------------------------
50 -- Variables
51 ----------------------------------------------------------------------------*/
52
53 typedef std::map<std::string, CIcon *> IconMap;
54 static IconMap Icons; /// Map of ident to icon.
55
56
57 /*----------------------------------------------------------------------------
58 -- Functions
59 ----------------------------------------------------------------------------*/
60
61 /**
62 ** CIcon constructor
63 */
CIcon(const std::string & ident)64 CIcon::CIcon(const std::string &ident) : G(NULL), GScale(NULL), Frame(0), Ident(ident)
65 {
66 }
67
68 /**
69 ** CIcon destructor
70 */
~CIcon()71 CIcon::~CIcon()
72 {
73 CPlayerColorGraphic::Free(this->G);
74 CPlayerColorGraphic::Free(this->GScale);
75 }
76
77 /**
78 ** Create a new icon
79 **
80 ** @param ident Icon identifier
81 **
82 ** @return New icon
83 */
New(const std::string & ident)84 /* static */ CIcon *CIcon::New(const std::string &ident)
85 {
86 CIcon *&icon = Icons[ident];
87
88 if (icon == NULL) {
89 icon = new CIcon(ident);
90 }
91 return icon;
92 }
93
94 /**
95 ** Get an icon
96 **
97 ** @param ident Icon identifier
98 **
99 ** @return The icon
100 */
Get(const std::string & ident)101 /* static */ CIcon *CIcon::Get(const std::string &ident)
102 {
103 IconMap::iterator it = Icons.find(ident);
104 if (it == Icons.end()) {
105 DebugPrint("icon not found: %s\n" _C_ ident.c_str());
106 }
107 return it->second;
108 }
109
Load()110 void CIcon::Load()
111 {
112 Assert(G);
113 G->Load();
114 if (Preference.GrayscaleIcons) {
115 GScale = G->Clone(true);
116 }
117 if (Frame >= G->NumFrames) {
118 DebugPrint("Invalid icon frame: %s - %d\n" _C_ Ident.c_str() _C_ Frame);
119 Frame = 0;
120 }
121 }
122
123 /**
124 ** Draw icon at pos.
125 **
126 ** @param player Player pointer used for icon colors
127 ** @param pos display pixel position
128 */
DrawIcon(const PixelPos & pos,const int player) const129 void CIcon::DrawIcon(const PixelPos &pos, const int player) const
130 {
131 if (player != -1 ) {
132 this->G->DrawPlayerColorFrameClip(player, this->Frame, pos.x, pos.y);
133 } else {
134 this->G->DrawFrameClip(this->Frame, pos.x, pos.y);
135 }
136 }
137
138 /**
139 ** Draw grayscale icon at pos.
140 **
141 ** @param pos display pixel position
142 */
DrawGrayscaleIcon(const PixelPos & pos,const int player) const143 void CIcon::DrawGrayscaleIcon(const PixelPos &pos, const int player) const
144 {
145 if (this->GScale) {
146 if (player != -1) {
147 this->GScale->DrawPlayerColorFrameClip(player, this->Frame, pos.x, pos.y);
148 } else {
149 this->GScale->DrawFrameClip(this->Frame, pos.x, pos.y);
150 }
151 }
152 }
153
154 /**
155 ** Draw cooldown spell effect on icon at pos.
156 **
157 ** @param pos display pixel position
158 ** @param percent cooldown percent
159 */
DrawCooldownSpellIcon(const PixelPos & pos,const int percent) const160 void CIcon::DrawCooldownSpellIcon(const PixelPos &pos, const int percent) const
161 {
162 // TO-DO: implement more effect types (clock-like)
163 if (this->GScale) {
164 this->GScale->DrawFrameClip(this->Frame, pos.x, pos.y);
165 const int height = (G->Height * (100 - percent)) / 100;
166 this->G->DrawSubClip(G->frame_map[Frame].x, G->frame_map[Frame].y + G->Height - height,
167 G->Width, height, pos.x, pos.y + G->Height - height);
168 } else {
169 DebugPrint("Enable grayscale icon drawing in your game to achieve special effects for cooldown spell icons");
170 this->DrawIcon(pos);
171 }
172 }
173
174 /**
175 ** Draw unit icon 'icon' with border on x,y
176 **
177 ** @param style Button style
178 ** @param flags State of icon (clicked, mouse over...)
179 ** @param pos display pixel position
180 ** @param text Optional text to display
181 */
DrawUnitIcon(const ButtonStyle & style,unsigned flags,const PixelPos & pos,const std::string & text,int player) const182 void CIcon::DrawUnitIcon(const ButtonStyle &style, unsigned flags,
183 const PixelPos &pos, const std::string &text, int player) const
184 {
185 ButtonStyle s(style);
186
187 s.Default.Sprite = s.Hover.Sprite = s.Clicked.Sprite = this->G;
188 s.Default.Frame = s.Hover.Frame = s.Clicked.Frame = this->Frame;
189 if (!(flags & IconSelected) && (flags & IconAutoCast)) {
190 s.Default.BorderColorRGB = UI.ButtonPanel.AutoCastBorderColorRGB;
191 s.Default.BorderColor = 0;
192 s.Default.BorderSize = 2;
193 }
194 if (Preference.IconsShift && Preference.IconFrameG && Preference.PressedIconFrameG) {
195 int shift = 0;
196 if (!(flags & IconClicked)) {
197 int xoffset = (s.Width - Preference.IconFrameG->Width) / 2;
198 int yoffset = (s.Height - Preference.IconFrameG->Height) / 2;
199 Preference.IconFrameG->DrawClip(pos.x + xoffset, pos.y + yoffset);
200 } else { // Shift the icon a bit to make it look like it's been pressed.
201 shift = 1;
202 int xoffset = (s.Width - Preference.PressedIconFrameG->Width) / 2 + shift;
203 int yoffset = (s.Height - Preference.PressedIconFrameG->Height) / 2 + shift;
204 Preference.PressedIconFrameG->DrawClip(pos.x + xoffset, pos.y + yoffset);
205 }
206 DrawUIButton(&s, flags, pos.x + shift, pos.y + shift, text, player);
207 if (flags & IconSelected) {
208 Video.DrawRectangle(ColorGreen, pos.x + shift, pos.y + shift, s.Width, s.Height);
209 }
210 } else if (Preference.IconsShift) {
211 // Left and top edge of Icon
212 Video.DrawHLine(ColorWhite, pos.x - 1, pos.y - 1, 49);
213 Video.DrawVLine(ColorWhite, pos.x - 1, pos.y, 40);
214 Video.DrawVLine(ColorWhite, pos.x, pos.y + 38, 2);
215 Video.DrawHLine(ColorWhite, pos.x + 46, pos.y, 2);
216
217 // Bottom and Right edge of Icon
218 Video.DrawHLine(ColorGray, pos.x + 1, pos.y + 38, 47);
219 Video.DrawHLine(ColorGray, pos.x + 1, pos.y + 39, 47);
220 Video.DrawVLine(ColorGray, pos.x + 46, pos.y + 1, 37);
221 Video.DrawVLine(ColorGray, pos.x + 47, pos.y + 1, 37);
222
223 Video.DrawRectangle(ColorBlack, pos.x - 3, pos.y - 3, 52, 44);
224 Video.DrawRectangle(ColorBlack, pos.x - 4, pos.y - 4, 54, 46);
225
226 if (flags & IconActive) { // Code to make a border appear around the icon when the mouse hovers over it.
227 Video.DrawRectangle(ColorGray, pos.x - 4, pos.y - 4, 54, 46);
228 DrawUIButton(&s, flags, pos.x, pos.y, text, player);
229 }
230
231 if (flags & IconClicked) { // Shift the icon a bit to make it look like it's been pressed.
232 DrawUIButton(&s, flags, pos.x + 1, pos.y + 1, text, player);
233 if (flags & IconSelected) {
234 Video.DrawRectangle(ColorGreen, pos.x + 1, pos.y + 1, 46, 38);
235 }
236 Video.DrawRectangle(ColorGray, pos.x, pos.y, 48, 40);
237 Video.DrawVLine(ColorDarkGray, pos.x - 1, pos.y - 1, 40);
238 Video.DrawHLine(ColorDarkGray, pos.x - 1, pos.y - 1, 49);
239 Video.DrawHLine(ColorDarkGray, pos.x - 1, pos.y + 39, 2);
240
241 Video.DrawRectangle(ColorGray, pos.x - 4, pos.y - 4, 54, 46);
242 } else {
243 DrawUIButton(&s, flags, pos.x, pos.y, text, player);
244 if (flags & IconSelected) {
245 Video.DrawRectangle(ColorGreen, pos.x, pos.y, 46, 38);
246 }
247 }
248 } else {
249 DrawUIButton(&s, flags, pos.x, pos.y, text, player);
250 }
251 }
252
253 /**
254 ** Load the Icon
255 */
LoadNoLog()256 bool IconConfig::LoadNoLog()
257 {
258 if (Name.empty()) {
259 return false;
260 }
261
262 Icon = CIcon::Get(Name);
263 return Icon != NULL;
264 }
265
266 /**
267 ** Load the Icon
268 */
Load()269 bool IconConfig::Load()
270 {
271 if (LoadNoLog() == true) {
272 ShowLoadProgress(_("Icon %s"), this->Name.c_str());
273 return true;
274 } else {
275 fprintf(stderr, _("Can't find icon %s\n"), this->Name.c_str());
276 return false;
277 }
278 }
279
280 /**
281 ** Load the graphics for the icons.
282 */
LoadIcons()283 void LoadIcons()
284 {
285 for (IconMap::iterator it = Icons.begin(); it != Icons.end(); ++it) {
286 CIcon &icon = *(*it).second;
287
288 ShowLoadProgress(_("Icons %s"), icon.G->File.c_str());
289 icon.Load();
290 }
291 }
292
293 /**
294 ** Clean up memory used by the icons.
295 */
CleanIcons()296 void CleanIcons()
297 {
298 for (IconMap::iterator it = Icons.begin(); it != Icons.end(); ++it) {
299 CIcon *icon = (*it).second;
300 delete icon;
301 }
302 Icons.clear();
303 }
304
305 //@}
306