1 /******************************************************************************
2 * Warmux is a convivial mass murder game.
3 * Copyright (C) 2001-2011 Warmux Team.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 ******************************************************************************
19 * Picture widget: A widget containing a picture
20 *****************************************************************************/
21
22 #include "gui/picture_widget.h"
23 #include "graphic/colors.h"
24 #include "graphic/sprite.h"
25 #include "graphic/video.h"
26 #include "include/app.h"
27
PictureWidget(const Point2i & _size)28 PictureWidget::PictureWidget(const Point2i & _size)
29 : Widget(_size, false)
30 , disabled(false)
31 , loaded(false)
32 , type(NO_SCALING)
33 , picture_size(0, 0)
34 , spr(NULL)
35 {
36 }
37
PictureWidget(const Point2i & _size,const std::string & resource_id,ScalingType _type)38 PictureWidget::PictureWidget(const Point2i & _size,
39 const std::string & resource_id,
40 ScalingType _type)
41 : Widget(_size, false)
42 , disabled(false)
43 , loaded(false)
44 , name(resource_id)
45 , type(_type)
46 , picture_size(0, 0)
47 , spr(NULL)
48 {
49 }
50
PictureWidget(const Surface & s,ScalingType type)51 PictureWidget::PictureWidget(const Surface & s, ScalingType type)
52 : Widget(s.GetSize(), false)
53 , disabled(false)
54 , type(type)
55 , spr(NULL)
56 {
57 SetSurface(s, type);
58 }
59
PictureWidget(Profile * profile,const xmlNode * pictureNode)60 PictureWidget::PictureWidget(Profile * profile,
61 const xmlNode * pictureNode)
62 : Widget(profile, pictureNode)
63 , disabled(false)
64 , type(NO_SCALING)
65 , spr(NULL)
66 {
67 }
68
~PictureWidget()69 PictureWidget::~PictureWidget()
70 {
71 if (spr != NULL) {
72 delete spr;
73 }
74 }
75
76 /*
77 Picture node example :
78 <Picture file="menu/image.png"
79 alpha="false"
80 x="0" y="0"
81 width="100" height="100"
82 scale="true"
83 antialiasing="true" />
84 */
LoadXMLConfiguration()85 bool PictureWidget::LoadXMLConfiguration()
86 {
87 if (NULL == profile || NULL == widgetNode) {
88 //TODO error ... xml attributs not initialized !
89 return false;
90 }
91 XmlReader * xmlFile = profile->GetXMLDocument();
92
93 std::string file("menu/pic_not_found.png");
94 xmlFile->ReadStringAttr(widgetNode, "file", file);
95
96 bool activeAlpha = false;
97 xmlFile->ReadBoolAttr(widgetNode, "alpha", activeAlpha);
98
99 file = profile->relative_path + file;
100 Surface surface(file.c_str());
101
102 if (!activeAlpha) {
103 surface = surface.DisplayFormat();
104 } else {
105 surface = surface.DisplayFormatAlpha();
106 }
107
108 ParseXMLGeometry();
109 ParseXMLMisc();
110
111 bool activeScale = false;
112 xmlFile->ReadBoolAttr(widgetNode, "scale", activeScale);
113
114 SetSurface(surface, activeScale ? FIT_SCALING : NO_SCALING);
115 return true;
116 }
117
ApplyScaling(ScalingType t)118 void PictureWidget::ApplyScaling(ScalingType t)
119 {
120 if (spr) {
121 Point2d scale(Double(size.x) / picture_size.x,
122 Double(size.y) / picture_size.y);
123
124 if (size.x==0 || size.y==0)
125 return;
126
127 switch (t) {
128 case NO_SCALING: break;
129 case X_SCALING: spr->Scale(scale.x, 1.0); break;
130 case Y_SCALING: spr->Scale(1.0, scale.x); break;
131 case STRETCH_SCALING: spr->Scale(scale.x, scale.y); break;
132 case FIT_SCALING:
133 default:
134 {
135 Double zoom = std::min(scale.x, scale.y);
136 spr->Scale(zoom, zoom);
137 break;
138 }
139 }
140 }
141
142 type = t;
143 }
144
SetSurface(const Surface & s,ScalingType type_)145 void PictureWidget::SetSurface(const Surface & s,
146 ScalingType type_)
147 {
148 if (NULL != spr) {
149 delete spr;
150 }
151
152 picture_size = s.GetSize();
153 spr = new Sprite(s);
154 type = type_;
155 loaded = true;
156 // Don't call immediately ApplyScaling(type) to save on rotozooms
157 NeedRedrawing();
158 }
159
SetNoSurface()160 void PictureWidget::SetNoSurface()
161 {
162 NeedRedrawing();
163
164 if (NULL != spr) {
165 delete spr;
166 }
167 spr = NULL;
168 }
169
Draw(const Point2i &)170 void PictureWidget::Draw(const Point2i &/*mousePosition*/)
171 {
172 if (!loaded) {
173 if (name.empty())
174 return;
175 Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml", false);
176 SetSurface(LOAD_RES_IMAGE(name), type);
177
178 // Needed to set the resizing
179 ApplyScaling(type);
180 }
181
182 if (NULL == spr) {
183 return;
184 }
185
186 Surface & surf = GetMainWindow();
187 Point2i pos = GetPicturePosition();
188
189 spr->Blit(surf, pos);
190
191 // Draw a transparency mask
192 if (disabled) {
193 surf.BoxColor(Rectanglei(pos, spr->GetSize()), defaultOptionColorBox);
194 }
195 }
196
GetPicturePosition() const197 Point2i PictureWidget::GetPicturePosition() const
198 {
199 return position + (size - spr->GetSize()) / 2;
200 }
201
GetScale() const202 Point2f PictureWidget::GetScale() const
203 {
204 return Point2f(spr->GetScaleX().tofloat(), spr->GetScaleY().tofloat());
205 }
206