xoreos  0.0.5
scrollbar.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/util.h"
26 #include "src/common/maths.h"
27 
28 #include "src/graphics/graphics.h"
29 
31 
33 
34 namespace Engines {
35 
36 namespace NWN {
37 
38 Scrollbar::Scrollbar(Type type) : Graphics::GUIElement(Graphics::GUIElement::kGUIElementFront),
39  _type(type), _x(0.0f), _y(0.0f), _z(0.0f) {
40  _texture = TextureMan.get("gui_scrollbar");
41 
42  setLength(16.0f);
43 }
44 
46  hide();
47 }
48 
49 void Scrollbar::setPosition(float x, float y, float z) {
50  GfxMan.lockFrame();
51 
52  _x = x;
53  _y = y;
54  _z = z;
55 
57 
58  GfxMan.unlockFrame();
59 }
60 
61 void Scrollbar::getPosition(float &x, float &y, float &z) const {
62  x = _x;
63  y = _y;
64  z = _z;
65 }
66 
67 bool Scrollbar::isIn(float x, float y) const {
68  if ((x < _x) || (y < _y))
69  return false;
70  if ((x > (_x + getWidth())) || (y > (_y + getHeight())))
71  return false;
72 
73  return true;
74 }
75 
76 void Scrollbar::setLength(float length) {
77  GfxMan.lockFrame();
78 
79  // Need at least the space for the 2 caps
80  _length = MAX(length, 4.0f);
81 
82  if (_type == kTypeVertical)
83  createV();
84  else if (_type == kTypeHorizontal)
85  createH();
86 
87  GfxMan.unlockFrame();
88 }
89 
90 float Scrollbar::getWidth() const {
91  if (_type == kTypeVertical)
92  return 10.0f;
93  else if (_type == kTypeHorizontal)
94  return _length;
95 
96  return 0.0f;
97 }
98 
99 float Scrollbar::getHeight() const {
100  if (_type == kTypeVertical)
101  return _length;
102  else if (_type == kTypeHorizontal)
103  return 10.0f;
104 
105  return 0.0f;
106 }
107 
109  _distance = _z;
110 }
111 
113  // The scrollbar model is opaque
115  return;
116 
117  TextureMan.set(_texture);
118 
119  glTranslatef(roundf(_x), roundf(_y), _z);
120 
121  glBegin(GL_QUADS);
122  for (std::vector<Quad>::const_iterator q = _quads.begin(); q != _quads.end(); ++q) {
123  for (int i = 0; i < 4; i++) {
124  glTexCoord2f(q->tX[i], q->tY[i]);
125  glVertex2f (q->vX[i], q->vY[i]);
126  }
127  }
128  glEnd();
129 }
130 
132  // Number of 16 pixel wide quads
133  int n = ceilf(_length / 16.0f);
134 
135  float x = 0.0f;
136  float y = 0.0f;
137 
138  // Quads + caps
139  _quads.resize(n + 2);
140 
141  // Left cap
142  _quads[0].tX[0] = 3.0f / 16.0f; _quads[0].tY[0] = 0.0f;
143  _quads[0].tX[1] = 3.0f / 16.0f; _quads[0].tY[1] = 2.0f / 16.0f;
144  _quads[0].tX[2] = 13.0f / 16.0f; _quads[0].tY[2] = 2.0f / 16.0f;
145  _quads[0].tX[3] = 13.0f / 16.0f; _quads[0].tY[3] = 0.0f;
146 
147  _quads[0].vX[0] = x ; _quads[0].vY[0] = y;
148  _quads[0].vX[1] = x + 2.0f; _quads[0].vY[1] = y;
149  _quads[0].vX[2] = x + 2.0f; _quads[0].vY[2] = y + 10.0f;
150  _quads[0].vX[3] = x ; _quads[0].vY[3] = y + 10.0f;
151 
152  x += 2.0f;
153 
154  float length = _length - 4.0f;
155 
156  // Bar
157  for (int i = 0; i < n; i++) {
158  float pLength = MIN(length, 16.0f);
159  float tLength = pLength / 16.0f;
160 
161  _quads[i + 1].tX[0] = 0.0f; _quads[i + 1].tY[0] = 3.0f / 16.0f;
162  _quads[i + 1].tX[1] = tLength; _quads[i + 1].tY[1] = 3.0f / 16.0f;
163  _quads[i + 1].tX[2] = tLength; _quads[i + 1].tY[2] = 13.0f / 16.0f;
164  _quads[i + 1].tX[3] = 0.0f; _quads[i + 1].tY[3] = 13.0f / 16.0f;
165 
166  _quads[i + 1].vX[0] = x ; _quads[i + 1].vY[0] = y;
167  _quads[i + 1].vX[1] = x + pLength; _quads[i + 1].vY[1] = y;
168  _quads[i + 1].vX[2] = x + pLength; _quads[i + 1].vY[2] = y + 10.0f;
169  _quads[i + 1].vX[3] = x ; _quads[i + 1].vY[3] = y + 10.0f;
170 
171  x += pLength;
172  length -= pLength;
173  }
174 
175  // Right cap
176  _quads[n + 1].tX[0] = 3.0f / 16.0f; _quads[n + 1].tY[0] = 14.0f / 16.0f;
177  _quads[n + 1].tX[1] = 3.0f / 16.0f; _quads[n + 1].tY[1] = 16.0f / 16.0f;
178  _quads[n + 1].tX[2] = 13.0f / 16.0f; _quads[n + 1].tY[2] = 16.0f / 16.0f;
179  _quads[n + 1].tX[3] = 13.0f / 16.0f; _quads[n + 1].tY[3] = 14.0f / 16.0f;
180 
181  _quads[n + 1].vX[0] = x ; _quads[n + 1].vY[0] = y;
182  _quads[n + 1].vX[1] = x + 2.0f; _quads[n + 1].vY[1] = y;
183  _quads[n + 1].vX[2] = x + 2.0f; _quads[n + 1].vY[2] = y + 10.0f;
184  _quads[n + 1].vX[3] = x ; _quads[n + 1].vY[3] = y + 10.0f;
185 }
186 
188  // Number of 16 pixel wide quads
189  int n = ceilf(_length / 16.0f);
190 
191  float x = 0.0f;
192  float y = 0.0f;
193 
194  // Quads + caps
195  _quads.resize(n + 2);
196 
197  // Bottom cap
198  _quads[0].tX[0] = 3.0f / 16.0f; _quads[0].tY[0] = 0.0f;
199  _quads[0].tX[1] = 3.0f / 16.0f; _quads[0].tY[1] = 2.0f / 16.0f;
200  _quads[0].tX[2] = 13.0f / 16.0f; _quads[0].tY[2] = 2.0f / 16.0f;
201  _quads[0].tX[3] = 13.0f / 16.0f; _quads[0].tY[3] = 0.0f;
202 
203  _quads[0].vX[0] = x ; _quads[0].vY[0] = y;
204  _quads[0].vX[1] = x + 10.0f; _quads[0].vY[1] = y;
205  _quads[0].vX[2] = x + 10.0f; _quads[0].vY[2] = y + 2.0f;
206  _quads[0].vX[3] = x ; _quads[0].vY[3] = y + 2.0f;
207 
208  y += 2.0f;
209 
210  float length = _length - 4.0f;
211 
212  // Bar
213  for (int i = 0; i < n; i++) {
214  float pLength = MIN(length, 16.0f);
215  float tLength = pLength / 16.0f;
216 
217  _quads[i + 1].tX[0] = 0.0f; _quads[i + 1].tY[0] = 3.0f / 16.0f;
218  _quads[i + 1].tX[1] = 0.0f; _quads[i + 1].tY[1] = 13.0f / 16.0f;
219  _quads[i + 1].tX[2] = tLength; _quads[i + 1].tY[2] = 13.0f / 16.0f;
220  _quads[i + 1].tX[3] = tLength; _quads[i + 1].tY[3] = 3.0f / 16.0f;
221 
222  _quads[i + 1].vX[0] = x ; _quads[i + 1].vY[0] = y;
223  _quads[i + 1].vX[1] = x + 10.0f; _quads[i + 1].vY[1] = y;
224  _quads[i + 1].vX[2] = x + 10.0f; _quads[i + 1].vY[2] = y + pLength;
225  _quads[i + 1].vX[3] = x ; _quads[i + 1].vY[3] = y + pLength;
226 
227  y += pLength;
228  length -= pLength;
229  }
230 
231  // Top cap
232  _quads[n + 1].tX[0] = 3.0f / 16.0f; _quads[n + 1].tY[0] = 14.0f / 16.0f;
233  _quads[n + 1].tX[1] = 3.0f / 16.0f; _quads[n + 1].tY[1] = 16.0f / 16.0f;
234  _quads[n + 1].tX[2] = 13.0f / 16.0f; _quads[n + 1].tY[2] = 16.0f / 16.0f;
235  _quads[n + 1].tX[3] = 13.0f / 16.0f; _quads[n + 1].tY[3] = 14.0f / 16.0f;
236 
237  _quads[n + 1].vX[0] = x ; _quads[n + 1].vY[0] = y;
238  _quads[n + 1].vX[1] = x + 10.0f; _quads[n + 1].vY[1] = y;
239  _quads[n + 1].vX[2] = x + 10.0f; _quads[n + 1].vY[2] = y + 2.0f;
240  _quads[n + 1].vX[3] = x ; _quads[n + 1].vY[3] = y + 2.0f;
241 }
242 
243 
245  Scrollbar::Type type, float range) :
246  NWNWidget(gui, tag), _type(type), _range(range), _state(0.0f), _scrollbar(type) {
247 
248  _scrollbar.setTag(tag);
249  _scrollbar.setClickable(true);
250 
251  setLength(1.0f);
252 }
253 
255 }
256 
258  if (isVisible())
259  return;
260 
261  if (!isInvisible())
262  _scrollbar.show();
263 
264  NWNWidget::show();
265 }
266 
268  if (!isVisible())
269  return;
270 
271  _scrollbar.hide();
272  NWNWidget::hide();
273 }
274 
275 void WidgetScrollbar::setPosition(float x, float y, float z) {
276  NWNWidget::setPosition(x, y, z);
277 
278  setState(_state);
279 }
280 
281 void WidgetScrollbar::setLength(float percent) {
282  _full = percent >= 1.0f;
283 
284  // Calculate the actual length, at 2 pixel intervals
285  _length = ceilf(MAX(_range * CLIP(percent, 0.0f, 1.0f), 10.0f));
286  if ((((int) _length) % 2) == 1)
287  _length += 1.0f;
288 
289  if (_length > _range)
290  _length = _range;
291 
293 
294  setState(_state);
295 }
296 
298  return _state;
299 }
300 
301 void WidgetScrollbar::setState(float state) {
302  _state = CLIP(state, 0.0f, 1.0f);
303 
304  float span = _range - _length; // Space to scroll in
305  float pos = _state * span; // Offset within that space
306 
307  float x, y, z;
308  getPosition(x, y, z);
309 
311  y += span - pos;
312  else if (_type == Scrollbar::kTypeHorizontal)
313  x += pos;
314 
315  _scrollbar.setPosition(x, y, z);
316 }
317 
319  return _scrollbar.getWidth();
320 }
321 
323  return _scrollbar.getHeight();
324 }
325 
327  float x, y, z;
328  _scrollbar.getPosition(x, y, z);
329 
331  return y;
332  else if (_type == Scrollbar::kTypeHorizontal)
333  return x;
334 
335  return 0.0f;
336 }
337 
338 void WidgetScrollbar::mouseDown(uint8 state, float x, float y) {
339  if (isDisabled())
340  return;
341 
342  if (_full)
343  // Can't scroll when the bar is going full length
344  return;
345 
346  // We only care about the left mouse button, pass everything else to the owner
347  if (state != SDL_BUTTON_LMASK) {
348  if (_owner)
349  _owner->mouseDown(state, x, y);
350  return;
351  }
352 
353  _dragX = x;
354  _dragY = y;
355  _dragState = _state;
356 }
357 
358 void WidgetScrollbar::mouseMove(uint8 state, float x, float y) {
359  if (isDisabled())
360  return;
361 
362  if (_full)
363  // Can't scroll when the bar is going full length
364  return;
365 
366  if (state != SDL_BUTTON_LMASK)
367  // We only care about moves with the left mouse button pressed
368  return;
369 
370  float steps = 1.0f / (_range - _length);
371 
373  setState(_dragState + ((_dragY - y) * steps));
374  else if (_type == Scrollbar::kTypeHorizontal)
375  setState(_dragState + ((x - _dragX) * steps));
376 
377  setActive(true);
378 }
379 
380 void WidgetScrollbar::mouseWheel(uint8 state, int x, int y) {
381  if (isDisabled())
382  return;
383 
384  if (_full)
385  // Can't scroll when the bar is going full length
386  return;
387 
388  if (_owner)
389  _owner->mouseWheel(state, x, y);
390 }
391 
392 } // End of namespace NWN
393 
394 } // End of namespace Engines
std::vector< Quad > _quads
Definition: scrollbar.h:86
void mouseWheel(uint8 state, int x, int y)
A mouse wheel was used on the widget.
Definition: scrollbar.cpp:380
virtual void show()
Show the object.
Definition: renderable.cpp:114
Only render transparent parts.
Definition: types.h:99
The global graphics manager.
virtual void hide()
Hide the object.
Definition: renderable.cpp:123
Widget * _owner
The widget&#39;s owner, if any.
Definition: widget.h:113
A class holding an UTF-8 string.
Definition: ustring.h:48
#define TextureMan
Shortcut for accessing the texture manager.
Definition: textureman.h:127
bool isIn(float x, float y) const
Is the point within the scrollbar?
Definition: scrollbar.cpp:67
double _distance
The distance of the object from the viewer.
Definition: renderable.h:101
void getPosition(float &x, float &y, float &z) const
Get the current position of the scrollbar.
Definition: scrollbar.cpp:61
uint8_t uint8
Definition: types.h:200
void createH()
Create a horizontal scrollbar.
Definition: scrollbar.cpp:131
float getHeight() const
Get the scrollbar&#39;s height.
Definition: scrollbar.cpp:99
The Aurora texture manager.
void setActive(bool active)
The widget&#39;s active state.
Definition: widget.cpp:268
Mathematical helpers.
virtual void getPosition(float &x, float &y, float &z) const
Get the widget&#39;s position.
Definition: widget.cpp:140
Base class for all widgets in NWN.
Definition: nwnwidget.h:45
bool isVisible() const
Is the widget visible?
Definition: widget.cpp:59
void setLength(float length)
Set the length of the scrollbar, as a fraction of the range.
Definition: scrollbar.cpp:281
void setState(float state)
Set the current state, as a fraction of the range.
Definition: scrollbar.cpp:301
void hide()
Hide the widget.
Definition: scrollbar.cpp:267
void hide()
Hide the widget.
Definition: nwnwidget.cpp:40
void render(Graphics::RenderPass pass)
Render the object.
Definition: scrollbar.cpp:112
void setLength(float length)
Set the scrollbar length.
Definition: scrollbar.cpp:76
A GUI.
Definition: gui.h:43
float getState() const
Get the current state, as a fraction of the range.
Definition: scrollbar.cpp:297
bool isInvisible() const
Is the widget invisible (never visible)?
Definition: widget.cpp:67
virtual void mouseDown(uint8 state, float x, float y)
A mouse button was pressed on the widget.
Definition: widget.cpp:191
RenderPass
Definition: types.h:97
void setClickable(bool clickable)
Set the object&#39;s clickable state.
Definition: renderable.cpp:94
void createV()
Create a vertical scrollbar.
Definition: scrollbar.cpp:187
Utility templates and functions.
void mouseMove(uint8 state, float x, float y)
The mouse was moved over the widget.
Definition: scrollbar.cpp:358
Graphics::Aurora::TextureHandle _texture
Definition: scrollbar.h:88
void setPosition(float x, float y, float z)
Set the current position of the scrollbar.
Definition: scrollbar.cpp:49
WidgetScrollbar(::Engines::GUI &gui, const Common::UString &tag, Scrollbar::Type type, float range)
Definition: scrollbar.cpp:244
void show()
Show the widget.
Definition: scrollbar.cpp:257
T MIN(T a, T b)
Definition: util.h:70
float getWidth() const
Get the scrollbar&#39;s width.
Definition: scrollbar.cpp:90
void setPosition(float x, float y, float z)
Set the widget&#39;s position.
Definition: nwnwidget.cpp:60
virtual void mouseWheel(uint8 state, int x, int y)
A mouse wheel was used on the widget.
Definition: widget.cpp:197
float getHeight() const
Get the widget&#39;s height.
Definition: scrollbar.cpp:322
A NWN scrollbar model and widget.
virtual void show()
Show the widget.
Definition: widget.cpp:71
bool isDisabled() const
Is the widget disabled?
Definition: widget.cpp:63
float getWidth() const
Get the widget&#39;s width.
Definition: scrollbar.cpp:318
void setTag(const Common::UString &tag)
Set the object&#39;s tag.
Definition: renderable.cpp:102
void calculateDistance()
Calculate the object&#39;s distance.
Definition: scrollbar.cpp:108
#define pass
Definition: fft.cpp:257
T CLIP(T v, T amin, T amax)
Definition: util.h:72
T MAX(T a, T b)
Definition: util.h:71
void setPosition(float x, float y, float z)
Set the widget&#39;s position.
Definition: scrollbar.cpp:275
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
void mouseDown(uint8 state, float x, float y)
A mouse button was pressed on the widget.
Definition: scrollbar.cpp:338