xoreos  0.0.5
kotorjadewidget.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 "src/common/system.h"
26 #include "src/common/util.h"
27 
28 #include "src/aurora/types.h"
29 #include "src/aurora/gff3file.h"
30 #include "src/aurora/talkman.h"
31 
32 #include "src/graphics/font.h"
33 #include "src/graphics/windowman.h"
34 
42 
44 
45 namespace Engines {
46 
47 KotORJadeWidget::Extend::Extend() : x(0.0f), y(0.0f), w(0.0f), h(0.0f) {
48 }
49 
51  : fillStyle(0),
52  dimension(0),
53  innerOffset(0),
54  hasColor(false),
55  r(0.0f), g(0.0f), b(0.0f),
56  pulsing(false) {
57 }
58 
60  : strRef(Aurora::kStrRefInvalid),
61  halign(0.0f),
62  valign(0.0f),
63  r(1.0f), g(1.0f), b(1.0f),
64  pulsing(false) {
65 }
66 
68 }
69 
71  : Widget(gui, tag),
72  _width(0.0f),
73  _height(0.0f),
75  _r(1.0f), _g(1.0f), _b(1.0f), _a(1.0f),
76  _unselectedR(1.0f), _unselectedG(1.0f), _unselectedB(1.0f), _unselectedA(1.0f),
77  _wrapped(false),
78  _subScene(NULL),
79  _highlighted(false) {
80 
81 }
82 
84 }
85 
87  gff.getVector("COLOR", _r, _g, _b);
88  _a = gff.getDouble("ALPHA", 1.0);
89 
90  Extend extend = createExtend(gff);
91 
92  _width = extend.w;
93  _height = extend.h;
94 
95  Widget::setPosition(extend.x, extend.y, 0.0f);
96 
97  Border border = createBorder(gff);
98  Hilight hilight = createHilight(gff);
99 
100  if (!hilight.fill.empty()) {
101  _highlight.reset(new Graphics::Aurora::GUIQuad(hilight.fill, 0, 0, extend.w, extend.h));
102  _highlight->setPosition(extend.x, extend.y, 0.0f);
103  _highlight->setTag(getTag());
104  _highlight->setClickable(true);
105  }
106 
107  if (!border.edge.empty() && !border.corner.empty()) {
108  _border.reset(new Graphics::Aurora::BorderQuad(border.edge, border.corner, 0.0f, 0.0f, extend.w, extend.h, border.dimension));
109  _border->setPosition(extend.x, extend.y, 0.0f);
110  _border->setColor(border.r, border.g, border.b);
111  if (!border.fill.empty()) {
113  extend.w - 2 * border.dimension,
114  extend.h - 2 * border.dimension));
115  } else {
116  _quad.reset(new Graphics::Aurora::GUIQuad(border.fill, 0.0f, 0.0f,
117  extend.w - 2 * border.dimension,
118  extend.h - 2 * border.dimension));
119  }
120  _quad->setPosition(extend.x + border.dimension, extend.y + border.dimension, 0.0f);
121  } else {
122  if (!border.fill.empty()) {
123  _quad.reset(new Graphics::Aurora::HighlightableGUIQuad(border.fill, 0.0f, 0.0f, extend.w, extend.h));
124  } else {
125  _quad.reset(new Graphics::Aurora::GUIQuad(border.fill, 0.0f, 0.0f, extend.w, extend.h));
126  }
127  _quad->setPosition(extend.x, extend.y, 0.0f);
128  }
129 
130  _quad->setTag(getTag());
131  _quad->setClickable(true);
132 
133  if (border.fill.empty())
134  _quad->setColor(0.0f, 0.0f, 0.0f, 0.0f);
135  else if (!border.hasColor)
136  _quad->setColor(1.0f, 1.0f, 1.0f, 1.0f);
137  else
138  _quad->setColor(border.r, border.g, border.b, 1.0f);
139 
140  Text text = createText(gff);
141 
142  if (!text.font.empty()) {
143  Graphics::Aurora::FontHandle font = FontMan.get(text.font);
144 
145  const float fontHeight = font.getFont().getHeight();
146  float tY = extend.y, tH = extend.h;
147  if (extend.h < fontHeight) {
148  tH = fontHeight;
149  tY = extend.y - (fontHeight - extend.h);
150  }
151  _text.reset(new Graphics::Aurora::HighlightableText(font, extend.w, tH,
152  text.text, text.r, text.g, text.b, 1.0f, text.halign, text.valign));
153 
154  _text->setPosition(extend.x, tY, -1.0f);
155  _text->setTag(getTag());
156  _text->setClickable(true);
157  }
158 
159  _borderDimension = border.dimension;
160 }
161 
162 void KotORJadeWidget::setClickable(bool clickable) {
163  if (_quad)
164  _quad->setClickable(clickable);
165  if (_text)
166  _text->setClickable(clickable);
167  if (_highlight)
168  _highlight->setClickable(clickable);
169 }
170 
171 void KotORJadeWidget::setScissor(int x, int y, int width, int height) {
172  if (_quad) {
173  _quad->setScissor(true);
174  _quad->setScissor(x, y, width, height);
175  }
176 }
177 
179  if (fill.empty() && _quad) {
180  _quad->hide();
181  _quad.reset();
182  return;
183  }
184 
185  if (!_quad) {
186  float x, y, z;
187  getPosition(x, y, z);
188 
190  _quad->setPosition(x + _borderDimension, y + _borderDimension, z);
191  _quad->setTag(getTag());
192  _quad->setClickable(true);
193 
194  if (isVisible())
195  _quad->show();
196  }
197 
198  _quad->setTexture(fill);
199  _quad->setColor(1.0f, 1.0f, 1.0f, 1.0f);
200 }
201 
202 void KotORJadeWidget::setColor(float r, float g, float b, float a) {
203  if (_quad)
204  _quad->setColor(r, g, b, a);
205 }
206 
207 void KotORJadeWidget::setBorderColor(float r, float g, float b, float a) {
208  if (_border)
209  _border->setColor(r, g, b, a);
210 }
211 
212 void KotORJadeWidget::setWrapped(bool wrapped) {
213  _wrapped = wrapped;
214 }
215 
217  if (!subscene) {
218  _subScene = NULL;
219  return;
220  }
221 
222  _subScene = subscene;
224 
225  float wWidth, wHeight;
226  wWidth = WindowMan.getWindowWidth();
227  wHeight = WindowMan.getWindowHeight();
228 
229  float x, y, z;
230  getPosition(x, y, z);
231  _subScene->setPosition(x + wWidth/2, y + wHeight/2);
232 
233  // If a fill quad already exists, move the subscene a bit before it.
234  if (_quad) {
235  _quad->getPosition(x, y, z);
236  _subScene->setDistance(z - 0.000001);
237  }
238 }
239 
241  return _borderDimension;
242 }
243 
245  if (hilight.empty() && _highlight) {
246  _highlight->hide();
247  _highlight.reset();
248  return;
249  }
250 
251  if (!_highlight) {
252  float x, y, z;
253  getPosition(x, y, z);
254 
256  _highlight->setPosition(x + _borderDimension, y + _borderDimension, z);
257  _highlight->setTag(getTag());
258  _highlight->setClickable(true);
259 
260  if (isVisible())
261  _highlight->show();
262  }
263 
264  _highlight->setTexture(hilight);
265  _highlight->setColor(1.0f, 1.0f, 1.0f, 1.0f);
266 }
267 
268 void KotORJadeWidget::setHighlight(bool highlight) {
269  float r, g, b, a;
270 
271  if (_highlighted == highlight)
272  return;
273 
274  if (highlight) {
275  if (_highlight) {
276  _quad->hide();
277  _highlight->show();
278  } else {
280  if (highlightable && highlightable->isHighlightable()) {
282  _text->getHighlightedLowerBound(r, g, b, a);
283  _text->setColor(r, g, b, a);
284  _text->setHighlighted(true);
285  }
286 
287  highlightable = getQuadHighlightableComponent();
288  if (highlightable && highlightable->isHighlightable()) {
290  highlightable->getHighlightedLowerBound(r, g, b, a);
291  _quad->setColor(r, g, b, a);
292  highlightable->setHighlighted(true);
293  }
294  }
295  } else {
296  if (_highlight) {
297  _quad->show();
298  _highlight->hide();
299  } else {
301  if (highlightable && highlightable->isHighlightable()) {
302  _text->setHighlighted(false);
304  }
305 
306  highlightable = getQuadHighlightableComponent();
307  if (highlightable && highlightable->isHighlightable()) {
308  highlightable->setHighlighted(false);
310  }
311  }
312  }
313 
314  _highlighted = highlight;
315 }
316 
318  return _highlighted;
319 }
320 
322  const Graphics::Aurora::FontHandle f = FontMan.get(font);
323  const float width = f.getFont().getWidth(str);
324  const float height = f.getFont().getHeight();
325 
326  _text.reset(new Graphics::Aurora::HighlightableText(f, width, height, str));
327 
328  _text->setTag(getTag());
329  _text->setClickable(true);
330 
331  float x, y, z;
332  getPosition(x, y, z);
333 
334  _text->setPosition(x, y, z);
335 
336  _width = MAX(_width , width);
337  _height = MAX(_height, height);
338 }
339 
341  if (_text)
342  _text->setFont(fnt);
343 }
344 
346  if (_text)
347  _text->setText(text);
348 }
349 
350 void KotORJadeWidget::setTextColor(float r, float g, float b, float a) {
351  if (_text)
352  _text->setColor(r, g, b, a);
353 }
354 
356  if (_text)
357  _text->setHorizontalAlign(halign);
358 }
359 
361  if (_text)
362  _text->setVerticalAlign(valign);
363 }
364 
366  return _text ? _text->getHeight(text) : 0.0f;
367 }
368 
370  Widget::setTag(tag);
371 
372  if (_quad)
373  _quad->setTag(getTag());
374  if (_text)
375  _text->setTag(getTag());
376 }
377 
379  if (isInvisible())
380  return;
381 
382  Widget::show();
383 
384  if (_quad)
385  _quad->show();
386  if (_text)
387  _text->show();
388  if (_border)
389  _border->show();
390  if (_subScene)
391  _subScene->show();
392 }
393 
395  if (!isVisible())
396  return;
397 
398  if (_subScene)
399  _subScene->hide();
400  if (_border)
401  _border->hide();
402  if (_highlight)
403  _highlight->hide();
404  if (_quad)
405  _quad->hide();
406  if (_text)
407  _text->hide();
408 
409  Widget::hide();
410 }
411 
412 void KotORJadeWidget::setPosition(float x, float y, float z) {
413  float oX, oY, oZ;
414  getPosition(oX, oY, oZ);
415 
416  float dx = x - oX;
417  float dy = y - oY;
418  float dz = z - oZ;
419 
420  Widget::setPosition(x, y, z);
421 
422  if (_quad) {
423  _quad->getPosition(x, y, z);
424  _quad->setPosition(x + dx, y + dy, z + dz);
425  }
426 
427  if (_highlight) {
428  _highlight->getPosition(x, y, z);
429  _highlight->setPosition(x + dx, y + dy, z + dz);
430  }
431 
432  if (_text) {
433  _text->getPosition(x, y, z);
434  _text->setPosition(x + dx, y + dy, z + dz);
435  }
436 
437  if (_border) {
438  _border->getPosition(x, y, z);
439  _border->setPosition(x + dx, y + dy, z + dz);
440  }
441 }
442 
443 void KotORJadeWidget::setRotation(float angle) {
444  if (_quad)
445  _quad->setRotation(angle);
446 }
447 
448 void KotORJadeWidget::setWidth(float width) {
449  float deltaWidth = width - _width;
450  _width = width;
451 
452  if (_quad) {
453  width = _quad->getWidth();
454  _quad->setWidth(width + deltaWidth);
455  }
456 
457  if (_highlight) {
458  width = _highlight->getWidth();
459  _highlight->setWidth(width + deltaWidth);
460  }
461 
462  float height;
463 
464  if (_text) {
465  width = _text->getWidth();
466  height = _text->getHeight();
467  _text->setSize(width + deltaWidth, height);
468  }
469 
470  if (_border) {
471  _border->getSize(width, height);
472  _border->setSize(width + deltaWidth, height);
473  }
474 }
475 
476 void KotORJadeWidget::setHeight(float height) {
477  float deltaHeight = height - _height;
478  _height = height;
479 
480  if (_quad) {
481  height = _quad->getHeight();
482  _quad->setHeight(height + deltaHeight);
483  }
484 
485  if (_highlight) {
486  height = _highlight->getHeight();
487  _highlight->setHeight(height + deltaHeight);
488  }
489 
490  float width;
491 
492  if (_text) {
493  width = _text->getWidth();
494  height = _text->getHeight();
495  _text->setSize(width, height + deltaHeight);
496  }
497 
498  if (_border) {
499  _border->getSize(width, height);
500  _border->setSize(width, height + deltaHeight);
501  }
502 }
503 
505  return _width;
506 }
507 
509  return _height;
510 }
511 
512 void KotORJadeWidget::setInvisible(bool invisible) {
513  Widget::setInvisible(invisible);
514  setClickable(!invisible);
515 }
516 
518  return static_cast<Graphics::Aurora::Highlightable *>(_text.get());
519 }
520 
522  return dynamic_cast<Graphics::Aurora::Highlightable *>(_quad.get());
523 }
524 
526  Extend extend;
527  if (gff.hasField("EXTENT")) {
528  const Aurora::GFF3Struct &e = gff.getStruct("EXTENT");
529  extend.x = static_cast<float>(e.getSint("LEFT"));
530  extend.y = static_cast<float>(e.getSint("TOP"));
531  extend.w = static_cast<float>(e.getSint("WIDTH"));
532  extend.h = static_cast<float>(e.getSint("HEIGHT"));
533  }
534  return extend;
535 }
536 
538  Border border;
539 
540  if (gff.hasField("BORDER")) {
541  const Aurora::GFF3Struct &b = gff.getStruct("BORDER");
542 
543  border.corner = b.getString("CORNER");
544  border.edge = b.getString("EDGE");
545  border.fill = b.getString("FILL");
546 
547  border.fillStyle = b.getUint("FILLSTYLE");
548  border.dimension = b.getUint("DIMENSION");
549  border.innerOffset = b.getUint("INNEROFFSET");
550 
551  border.hasColor = b.hasField("COLOR");
552  b.getVector("COLOR", border.r, border.g, border.b);
553 
554  border.pulsing = b.getBool("PULSING");
555  }
556  return border;
557 }
558 
560  Text text;
561 
562  if (gff.hasField("TEXT")) {
563  const Aurora::GFF3Struct &t = gff.getStruct("TEXT");
564 
565  text.font = t.getString("FONT");
566  text.text = t.getString("TEXT");
567  text.strRef = t.getUint("STRREF", Aurora::kStrRefInvalid);
568 
569  const uint32 alignment = t.getUint("ALIGNMENT");
570 
571  t.getVector("COLOR", text.r, text.g, text.b);
572 
573  text.pulsing = t.getBool("PULSING");
574 
575 
576  if (text.text == "(Unitialized)")
577  text.text.clear();
578 
579  if (text.strRef != Aurora::kStrRefInvalid)
580  text.text = TalkMan.getString(text.strRef);
581 
582  // TODO: KotORWidget::getText(): Alignment
583  if (alignment == 10) {
586  } else if (alignment == 18) {
589  }
590  }
591 
592  return text;
593 }
594 
596  Hilight hilight;
597  if (gff.hasField("HILIGHT")) {
598  const Aurora::GFF3Struct &h = gff.getStruct("HILIGHT");
599  hilight.fill = h.getString("FILL");
600  }
601  return hilight;
602 }
603 
604 } // End of namespace Engines
int64 getSint(const Common::UString &field, int64 def=0) const
Definition: gff3file.cpp:473
Handling version V3.2/V3.3 of BioWare&#39;s GFFs (generic file format).
virtual void setHeight(float height)
Set the height of the widget.
void setClickable(bool clickable)
Set the widget clickable, or not clickable.
virtual void show()
Show the object.
Definition: renderable.cpp:114
void setScissor(int x, int y, int width, int height)
Create a scissor test over this widget.
void setDistance(float distance)
Graphics::Aurora::Highlightable * getTextHighlightableComponent() const
void setFill(const Common::UString &fill)
virtual void setInvisible(bool invisible)
Make the widget invisible.
Definition: widget.cpp:168
#define TalkMan
Shortcut for accessing the talk manager.
Definition: talkman.h:111
virtual void hide()
Hide the object.
Definition: renderable.cpp:123
bool getBool(const Common::UString &field, bool def=false) const
Definition: gff3file.cpp:510
Hilight createHilight(const Aurora::GFF3Struct &gff)
virtual void hide()
Hide the widget.
virtual void setTag(const Common::UString &tag)
Set the widget&#39;s tag.
Definition: widget.cpp:49
A class holding an UTF-8 string.
Definition: ustring.h:48
void setHighlighted(bool hightlighted)
void setTextColor(float r, float g, float b, float a)
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
Common::ScopedPtr< Graphics::Aurora::BorderQuad > _border
void setHorizontalTextAlign(float halign)
void createText(const Common::UString &font, const Common::UString &str)
Initialize the text within this widget.
const float kVAlignTop
Definition: types.h:46
Common::ScopedPtr< Graphics::Aurora::GUIQuad > _highlight
Common::ScopedPtr< Graphics::Aurora::GUIQuad > _quad
The Aurora texture manager.
void setHighlight(const Common::UString &hilight)
A handle to a font.
Definition: fonthandle.h:52
virtual void setPosition(float x, float y, float z)
Set the widget&#39;s position.
Definition: widget.cpp:119
A text object.
bool hasField(const Common::UString &field) const
Does this specific field exist?
Definition: gff3file.cpp:400
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
The global window manager.
bool isVisible() const
Is the widget visible?
Definition: widget.cpp:59
uint64 getUint(const Common::UString &field, uint64 def=0) const
Definition: gff3file.cpp:436
virtual void setRotation(float angle)
Set the rotation of the widget in degrees.
KotORJadeWidget(GUI &gui, const Common::UString &tag)
The Aurora font manager.
A GUI.
Definition: gui.h:43
bool isHighlight()
If the widget is highlighted.
bool isInvisible() const
Is the widget invisible (never visible)?
Definition: widget.cpp:67
void getVector(const Common::UString &field, float &x, float &y, float &z) const
Definition: gff3file.cpp:660
Basic Aurora graphics types.
Utility templates and functions.
float getTextHeight(const Common::UString &text) const
virtual void show()
Show the widget.
const Common::UString & getTag() const
Get the widget&#39;s tag.
Definition: widget.cpp:45
void setFont(const Common::UString &fnt)
Change the font for this widget.
double getDouble(const Common::UString &field, double def=0.0) const
Definition: gff3file.cpp:514
void setSize(int width, int height)
static const uint32 kStrRefInvalid
Definition: types.h:444
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
void setTag(const Common::UString &tag)
Set the widget&#39;s tag.
const float kHAlignCenter
Definition: types.h:43
Common base for Star Wars: Knights of the Old Republic and Jade Empire widgets.
Extend createExtend(const Aurora::GFF3Struct &gff)
const float kVAlignMiddle
Definition: types.h:47
virtual void hide()
Hide the widget.
Definition: widget.cpp:90
Basic type definitions to handle files used in BioWare&#39;s Aurora engine.
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
#define WindowMan
Shortcut for accessing the window manager.
Definition: windowman.h:137
void setVerticalTextAlign(float valign)
A widget in a GUI.
Definition: widget.h:40
Graphics::Aurora::SubSceneQuad * _subScene
A struct within a GFF3.
Definition: gff3file.h:164
virtual void show()
Show the widget.
Definition: widget.cpp:71
uint32_t uint32
Definition: types.h:204
const GFF3Struct & getStruct(const Common::UString &field) const
Definition: gff3file.cpp:728
The global talk manager for Aurora strings.
virtual void setInvisible(bool invisible)
Make the widget invisible.
Low-level detection of architecture/system properties.
void setColor(float r, float g, float b, float a)
void setPosition(int x, int y)
void setText(const Common::UString &text)
Common::UString getString(const Common::UString &field, const Common::UString &def="") const
Definition: gff3file.cpp:527
void setWrapped(bool wrapped)
void setBorderColor(float r, float g, float b, float a)
Common::ScopedPtr< Graphics::Aurora::HighlightableText > _text
A textured quad for a GUI element.
T MAX(T a, T b)
Definition: util.h:71
virtual void load(const Aurora::GFF3Struct &gff)
virtual float getHeight() const =0
Return the height of a character.
void clear()
Clear the string&#39;s contents.
Definition: ustring.cpp:236
float getWidth() const
Get the widget&#39;s width.
virtual void setWidth(float width)
Set the width of the widget.
A font.
virtual float getWidth(uint32 c) const =0
Return the width of a character.
Border createBorder(const Aurora::GFF3Struct &gff)
#define FontMan
Shortcut for accessing the font manager.
Definition: fontman.h:105
virtual void setPosition(float x, float y, float z)
Set the widget&#39;s position.
float getHeight() const
Get the widget&#39;s height.
void getHighlightedLowerBound(float &r, float &g, float &b, float &a) const
Graphics::Aurora::Highlightable * getQuadHighlightableComponent() const