xoreos  0.0.5
hud.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <set>
26 
27 #include "src/common/strutil.h"
28 
29 #include "src/aurora/resman.h"
30 
31 #include "src/graphics/windowman.h"
32 #include "src/graphics/graphics.h"
33 
37 
38 namespace Engines {
39 
40 namespace KotOR {
41 
42 enum Position {
50 };
51 
52 struct KnownWidget {
53  const char *name;
54  bool visible;
56 };
57 
58 static const KnownWidget kKnownWidgets[] = {
59  { "LBL_MAPVIEW", true, kPositionUpperLeft },
60  { "LBL_MAPBORDER", true, kPositionUpperLeft },
61  { "LBL_ARROW", true, kPositionUpperLeft },
62  { "LBL_PLOTXP", false, kPositionUpperLeft },
63  { "LBL_STEALTHXP", false, kPositionUpperLeft },
64  { "LBL_CASH", false, kPositionUpperLeft },
65  { "LBL_JOURNAL", false, kPositionUpperLeft },
66  { "LBL_LIGHTSHIFT", false, kPositionUpperLeft },
67  { "LBL_DARKSHIFT", false, kPositionUpperLeft },
68  { "LBL_ITEMRCVD", false, kPositionUpperLeft },
69  { "LBL_ITEMLOST", false, kPositionUpperLeft },
70 
71  { "LBL_MENUBG", true, kPositionUpperRight },
72  { "BTN_MSG", true, kPositionUpperRight },
73  { "BTN_ABI", true, kPositionUpperRight },
74  { "BTN_JOU", true, kPositionUpperRight },
75  { "BTN_INV", true, kPositionUpperRight },
76  { "BTN_CHAR", true, kPositionUpperRight },
77  { "BTN_EQU", true, kPositionUpperRight },
78  { "BTN_MAP", true, kPositionUpperRight },
79  { "BTN_OPT", true, kPositionUpperRight },
80 
81  { "LBL_MOULDING1", true, kPositionLowerLeft },
82  { "TB_SOLO", true, kPositionLowerLeft },
83  { "TB_STEALTH", true, kPositionLowerLeft },
84  { "TB_PAUSE", true, kPositionLowerLeft },
85  { "LBL_CHAR1", false, kPositionLowerLeft },
86  { "LBL_CHAR2", false, kPositionLowerLeft },
87  { "LBL_CHAR3", false, kPositionLowerLeft },
88  { "LBL_DEBILATATED1", false, kPositionLowerLeft },
89  { "LBL_DEBILATATED2", false, kPositionLowerLeft },
90  { "LBL_DEBILATATED3", false, kPositionLowerLeft },
91  { "LBL_DISABLE1", false, kPositionLowerLeft },
92  { "LBL_DISABLE2", false, kPositionLowerLeft },
93  { "LBL_DISABLE3", false, kPositionLowerLeft },
94  { "LBL_CMBTEFCTRED1", false, kPositionLowerLeft },
95  { "LBL_CMBTEFCTRED2", false, kPositionLowerLeft },
96  { "LBL_CMBTEFCTRED3", false, kPositionLowerLeft },
97  { "LBL_CMBTEFCTINC1", false, kPositionLowerLeft },
98  { "LBL_CMBTEFCTINC2", false, kPositionLowerLeft },
99  { "LBL_CMBTEFCTINC3", false, kPositionLowerLeft },
100  { "LBL_BACK1", false, kPositionLowerLeft },
101  { "LBL_BACK2", false, kPositionLowerLeft },
102  { "LBL_BACK3", false, kPositionLowerLeft },
103  { "BTN_CHAR1", false, kPositionLowerLeft },
104  { "BTN_CHAR2", false, kPositionLowerLeft },
105  { "BTN_CHAR3", false, kPositionLowerLeft },
106  { "LBL_LVLUPBG1", false, kPositionLowerLeft },
107  { "LBL_LVLUPBG2", false, kPositionLowerLeft },
108  { "LBL_LVLUPBG3", false, kPositionLowerLeft },
109  { "LBL_LEVELUP1", false, kPositionLowerLeft },
110  { "LBL_LEVELUP2", false, kPositionLowerLeft },
111  { "LBL_LEVELUP3", false, kPositionLowerLeft },
112  { "PB_VIT1", false, kPositionLowerLeft },
113  { "PB_VIT2", false, kPositionLowerLeft },
114  { "PB_VIT3", false, kPositionLowerLeft },
115  { "PB_FORCE1", false, kPositionLowerLeft },
116  { "PB_FORCE2", false, kPositionLowerLeft },
117  { "PB_FORCE3", false, kPositionLowerLeft },
118 
119  { "LBL_MOULDING3", true, kPositionLowerRight },
120  { "BTN_ACTIONDOWN0", true, kPositionLowerRight },
121  { "BTN_ACTIONDOWN1", true, kPositionLowerRight },
122  { "BTN_ACTIONDOWN2", true, kPositionLowerRight },
123  { "BTN_ACTIONDOWN3", true, kPositionLowerRight },
124  { "BTN_ACTIONUP0", true, kPositionLowerRight },
125  { "BTN_ACTIONUP1", true, kPositionLowerRight },
126  { "BTN_ACTIONUP2", true, kPositionLowerRight },
127  { "BTN_ACTIONUP3", true, kPositionLowerRight },
128  { "BTN_ACTION0", true, kPositionLowerRight },
129  { "BTN_ACTION1", true, kPositionLowerRight },
130  { "BTN_ACTION2", true, kPositionLowerRight },
131  { "BTN_ACTION3", true, kPositionLowerRight },
132  { "LBL_ACTION0", true, kPositionLowerRight },
133  { "LBL_ACTION1", true, kPositionLowerRight },
134  { "LBL_ACTION2", true, kPositionLowerRight },
135  { "LBL_ACTION3", true, kPositionLowerRight },
136  { "LBL_ACTIONDESC", false, kPositionLowerRight },
137  { "LBL_ACTIONDESCBG", false, kPositionLowerRight },
138 
139  { "LBL_CMBTMSGBG", false, kPositionUpperMid },
140  { "LBL_CMBTMODEMSG", false, kPositionUpperMid },
141 
142  { "LBL_COMBATBG1", false, kPositionLowerMid },
143  { "LBL_COMBATBG2", false, kPositionLowerMid },
144  { "LBL_COMBATBG3", false, kPositionLowerMid },
145  { "LBL_QUEUE0", false, kPositionLowerMid },
146  { "LBL_QUEUE1", false, kPositionLowerMid },
147  { "LBL_QUEUE2", false, kPositionLowerMid },
148  { "LBL_QUEUE3", false, kPositionLowerMid },
149  { "BTN_CLEARALL", false, kPositionLowerMid },
150  { "BTN_CLEARONE", false, kPositionLowerMid },
151  { "BTN_CLEARONE2", false, kPositionLowerMid },
152 
153  { "PB_HEALTH", false, kPositionNotSpecified },
154  { "LBL_HEALTHBG", false, kPositionNotSpecified },
155  { "LBL_NAMEBG", false, kPositionNotSpecified },
156  { "LBL_NAME", false, kPositionNotSpecified },
157  { "BTN_TARGET0", false, kPositionNotSpecified },
158  { "BTN_TARGET1", false, kPositionNotSpecified },
159  { "BTN_TARGET2", false, kPositionNotSpecified },
160  { "BTN_TARGETUP0", false, kPositionNotSpecified },
161  { "BTN_TARGETUP1", false, kPositionNotSpecified },
162  { "BTN_TARGETUP2", false, kPositionNotSpecified },
163  { "BTN_TARGETDOWN0", false, kPositionNotSpecified },
164  { "BTN_TARGETDOWN1", false, kPositionNotSpecified },
165  { "BTN_TARGETDOWN2", false, kPositionNotSpecified },
166 
167  // TODO: Add xbox ui widgets.
168 };
169 
170 struct Resolution {
171  int width;
172  int height;
173 
174  const char *gui;
175 
176  bool operator<(const Resolution &x) const {
177  if (width == x.width)
178  return height < x.height;
179 
180  return width < x.width;
181  }
182 };
183 
184 static const Resolution kResolution[] = {
185  { 800, 600, "mipc28x6" },
186  { 800, 600, "mi8x6" },
187  { 1024, 768, "mipc210x7" },
188  { 1280, 960, "mipc212x9" },
189  { 1280, 1024, "mipc212x10" },
190  { 1600, 1200, "mipc216x12" },
191 };
192 
193 HUD::HUD(Module &module, Engines::Console *console)
194  : GUI(console),
195  _module(&module),
196  _menu(module, console) {
197 
198  update(WindowMan.getWindowWidth(), WindowMan.getWindowHeight());
199 
200  _minimapPointer = getLabel("LBL_ARROW");
201 }
202 
203 void HUD::setReturnStrref(uint32 id) {
204  _menu.setReturnStrref(id);
205 }
206 
207 void HUD::setReturnQueryStrref(uint32 id) {
208  _menu.setReturnQueryStrref(id);
209 }
210 
211 void HUD::setReturnEnabled(bool enabled) {
212  _menu.setReturnEnabled(enabled);
213 }
214 
215 void HUD::setMinimap(const Common::UString &map, int northAxis,
216  float worldPt1X, float worldPt1Y, float worldPt2X, float worldPt2Y,
217  float mapPt1X, float mapPt1Y, float mapPt2X, float mapPt2Y) {
218 
219  WidgetLabel *mapView = getLabel("LBL_MAPVIEW");
220  if (!mapView) {
221  warning("No such GUI element \"LBL_MAPVIEW\"");
222  return;
223  }
224 
225  GfxMan.lockFrame();
226 
227  _minimap.reset(new Minimap(map, northAxis, mapPt1X, mapPt1Y, mapPt2X, mapPt2Y, worldPt1X, worldPt1Y, worldPt2X, worldPt2Y));
228  mapView->setSubScene(_minimap.get());
229 
230  GfxMan.unlockFrame();
231 }
232 
233 void HUD::setPosition(float x, float y) {
234  if (_minimap)
235  _minimap->setPosition(x, y);
236 }
237 
238 void HUD::setRotation(float angle) {
239  switch (_minimap->getNorthAxis()) {
240  case 0:
241  _minimapPointer->setRotation(angle);
242  break;
243  case 3:
244  _minimapPointer->setRotation(angle - 90.0f);
245  break;
246  default:
247  warning("Unknown north axis");
248  }
249 }
250 
251 void HUD::showContainer(Inventory &inv) {
252  _container.reset(new ContainerMenu());
253  _container->fillFromInventory(inv);
254 
255  if (sub(*_container, kStartCodeNone, true, false) == 1) {
256  Inventory &partyInventory = _module->getPC()->getInventory();
257 
258  const std::map<Common::UString, InventoryItem> &items = inv.getItems();
259  for (std::map<Common::UString, InventoryItem>::const_iterator i = items.begin();
260  i != items.end(); ++i) {
261  partyInventory.addItem(i->first, i->second.count);
262  }
263 
264  inv.removeAllItems();
265  }
266 }
267 
268 void HUD::setPortrait(uint8 n, bool visible, const Common::UString &portrait) {
269  WidgetLabel *labelBack = getLabel(Common::UString("LBL_BACK") + Common::composeString(n));
270  if (labelBack)
271  labelBack->setInvisible(!visible);
272 
273  WidgetLabel *labelChar = getLabel(Common::UString("LBL_CHAR") + Common::composeString(n));
274  if (labelChar) {
275  labelChar->setInvisible(!visible);
276  labelChar->setFill(portrait);
277  }
278 
279  WidgetProgressbar *vitals = getProgressbar(Common::UString("PB_VIT") + Common::composeString(n));
280  if (vitals)
281  vitals->setInvisible(!visible);
282 
283  if (visible) {
284  if (labelBack)
285  labelBack->show();
286  if (labelChar)
287  labelChar->show();
288  if (vitals)
289  vitals->show();
290  } else {
291  if (labelBack)
292  labelBack->hide();
293  if (labelChar)
294  labelChar->hide();
295  if (vitals)
296  vitals->hide();
297  }
298 }
299 
300 void HUD::setPartyLeader(Creature *creature) {
301  setPortrait(1, creature != 0, creature ? creature->getPortrait() : "");
302 }
303 
304 void HUD::setPartyMember1(Creature *creature) {
305  setPortrait(3, creature != 0, creature ? creature->getPortrait() : "");
306 }
307 
308 void HUD::setPartyMember2(Creature *creature) {
309  setPortrait(2, creature != 0, creature ? creature->getPortrait() : "");
310 }
311 
312 void HUD::update(int width, int height) {
313  std::set<Resolution> availableRes;
314 
315  for (size_t i = 0; i < ARRAYSIZE(kResolution); i++)
316  if (ResMan.hasResource(kResolution[i].gui, Aurora::kFileTypeGUI))
317  availableRes.insert(kResolution[i]);
318 
319  const int wWidth = width;
320  const int wHeight = height;
321 
322  const Resolution *foundRes = 0;
323  for (std::set<Resolution>::const_iterator it = availableRes.begin(); it != availableRes.end(); ++it)
324  if (it->width == wWidth && it->height == wHeight)
325  foundRes = &*it;
326 
327  bool scale = false;
328  if (!foundRes) {
329  for (std::set<Resolution>::const_iterator it = availableRes.begin(); it != availableRes.end(); ++it) {
330  if ((it->width == 800) && (it->height == 600)) {
331  foundRes = &*it;
332  break;
333  }
334  }
335  if (!foundRes)
336  throw Common::Exception("No gui with 800x600 resolution found.");
337  scale = true;
338  }
339 
340  load(foundRes->gui);
341 
342  // Make all the widgets invisible and scale them if needed.
343  for (size_t i = 0; i < ARRAYSIZE(kKnownWidgets); i++) {
344  Widget *widget = getWidget(kKnownWidgets[i].name);
345  if (!widget)
346  continue;
347 
348  widget->setInvisible(!kKnownWidgets[i].visible);
349 
350  float x, y, z;
351  if (scale) {
352  switch (kKnownWidgets[i].position) {
353  case kPositionUpperLeft:
354  widget->getPosition(x, y, z);
355  widget->setPosition(-wWidth/2 + (400 + x), wHeight/2 - (300 - y), z);
356  break;
357  case kPositionUpperRight:
358  widget->getPosition(x, y, z);
359  widget->setPosition(wWidth/2 - (400 - x), wHeight/2 - (300 - y), z);
360  break;
361  case kPositionUpperMid:
362  widget->getPosition(x, y, z);
363  widget->setPosition(x, wHeight/2 - (300 - y), z);
364  break;
365  case kPositionLowerLeft:
366  widget->getPosition(x, y, z);
367  widget->setPosition(-wWidth/2 + (400 + x), -wHeight/2 + (300 + y), z);
368  break;
369  case kPositionLowerRight:
370  widget->getPosition(x, y, z);
371  widget->setPosition(wWidth/2 - (400 - x), -wHeight/2 + (300 + y), z);
372  break;
373  case kPositionLowerMid:
374  widget->getPosition(x, y, z);
375  widget->setPosition(x, -wHeight/2 + (300 + y), z);
376  break;
377  default:
378  break;
379  }
380  }
381  }
382 }
383 
384 void HUD::initWidget(Engines::Widget &widget) {
385  // Don't know what these two are doing, but they spawn over the complete screen blocking the 3d picking.
386  if (widget.getTag() == "LBL_MAP")
387  widget.setInvisible(true);
388  if (widget.getTag() == "LBL_ARROW_MARGIN")
389  widget.setInvisible(true);
390 
391  // TGuiPanel needs to be disabled in order to ensure, it does not block 3d picking.
392  if (widget.getTag() == "TGuiPanel")
393  widget.setInvisible(true);
394 
395  // First disable all portraits
396  if (widget.getTag().contains("LBL_CHAR"))
397  widget.setInvisible(true);
398  if (widget.getTag().contains("BTN_CHAR") && widget.getTag().size() == 9)
399  widget.setInvisible(true);
400  if (widget.getTag().contains("LBL_BACK"))
401  widget.setInvisible(true);
402  if (widget.getTag().contains("PB_VIT"))
403  widget.setInvisible(true);
404  if (widget.getTag().contains("PB_FORCE"))
405  widget.setInvisible(true);
406 }
407 
408 void HUD::callbackActive(Widget &widget) {
409  if (widget.getTag() == "LBL_CHAR1") {
410  _module->switchPlayerCharacter(0);
411  return;
412  }
413  if (widget.getTag() == "LBL_CHAR2") {
414  _module->switchPlayerCharacter(2);
415  return;
416  }
417  if (widget.getTag() == "LBL_CHAR3") {
418  _module->switchPlayerCharacter(1);
419  return;
420  }
421 
422  _menu.showMenu(widget.getTag());
423  sub(_menu);
424 }
425 
426 void HUD::notifyResized(int UNUSED(oldWidth), int UNUSED(oldHeight), int newWidth, int newHeight) {
427  update(newWidth, newHeight);
428 }
429 
430 } // End of namespace KotOR
431 
432 } // End of namespace Engines
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
void setFill(const Common::UString &fill)
The global graphics manager.
virtual void setInvisible(bool invisible)
Make the widget invisible.
Definition: widget.cpp:168
A label widget for Star Wars: Knights of the Old Republic and Jade Empire.
virtual void hide()
Hide the widget.
A class holding an UTF-8 string.
Definition: ustring.h:48
const char * name
Definition: hud.cpp:53
const Common::UString & getPortrait() const
Return the object&#39;s portrait.
Definition: object.cpp:91
UString composeString(T value)
Convert any POD integer, float/double or bool type into a string.
Definition: strutil.cpp:276
uint8_t uint8
Definition: types.h:200
virtual void setPosition(float x, float y, float z)
Set the widget&#39;s position.
Definition: widget.cpp:119
void setSubScene(Graphics::Aurora::SubSceneQuad *subscene)
virtual void getPosition(float &x, float &y, float &z) const
Get the widget&#39;s position.
Definition: widget.cpp:140
static const KnownWidget kKnownWidgets[]
Definition: hud.cpp:58
The global window manager.
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
Definition: util.h:131
const char * gui
Definition: hud.cpp:174
Utility templates and functions for working with strings and streams.
void hide()
Hide the widget.
Definition: progressbar.cpp:90
A GUI.
Definition: gui.h:43
bool contains(const UString &what) const
Definition: ustring.cpp:335
#define UNUSED(x)
Definition: system.h:170
virtual void show()
Show the widget.
const Common::UString & getTag() const
Get the widget&#39;s tag.
Definition: widget.cpp:45
HUD(Module &module, ::Engines::Console *console=0)
StackException Exception
Definition: error.h:59
void warning(const char *s,...)
Definition: util.cpp:33
A progressbar widget for Star Wars: Knights of the Old Republic and Jade Empire.
void addItem(const Common::UString &tag, int count=1)
Definition: inventory.cpp:31
void show()
Show the widget.
Definition: progressbar.cpp:80
#define WindowMan
Shortcut for accessing the window manager.
Definition: windowman.h:137
static const Resolution kResolution[]
Definition: hud.cpp:184
A widget in a GUI.
Definition: widget.h:40
size_t size() const
Return the size of the string, in characters.
Definition: ustring.cpp:241
uint32_t uint32
Definition: types.h:204
virtual void setInvisible(bool invisible)
Make the widget invisible.
GUI definition, GFF.
Definition: types.h:113
The ingame HUD.
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
The global resource manager for Aurora resources.
bool operator<(const Resolution &x) const
Definition: hud.cpp:176
const std::map< Common::UString, InventoryItem > & getItems() const
Definition: inventory.cpp:67