aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp')
-rw-r--r--libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp
new file mode 100644
index 0000000..5a451cd
--- /dev/null
+++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIButton.cpp
@@ -0,0 +1,531 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CGUIButton.h"
6#ifdef _IRR_COMPILE_WITH_GUI_
7
8#include "IGUISkin.h"
9#include "IGUIEnvironment.h"
10#include "IVideoDriver.h"
11#include "IGUIFont.h"
12#include "os.h"
13
14namespace irr
15{
16namespace gui
17{
18
19//! constructor
20CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
21 s32 id, core::rect<s32> rectangle, bool noclip)
22: IGUIButton(environment, parent, id, rectangle),
23 SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0),
24 ClickTime(0), HoverTime(0), FocusTime(0),
25 IsPushButton(false), Pressed(false),
26 UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
27{
28 #ifdef _DEBUG
29 setDebugName("CGUIButton");
30 #endif
31 setNotClipped(noclip);
32
33 // Initialize the sprites.
34 for (u32 i=0; i<EGBS_COUNT; ++i)
35 ButtonSprites[i].Index = -1;
36
37 // This element can be tabbed.
38 setTabStop(true);
39 setTabOrder(-1);
40}
41
42
43//! destructor
44CGUIButton::~CGUIButton()
45{
46 if (OverrideFont)
47 OverrideFont->drop();
48
49 if (Image)
50 Image->drop();
51
52 if (PressedImage)
53 PressedImage->drop();
54
55 if (SpriteBank)
56 SpriteBank->drop();
57}
58
59
60//! Sets if the images should be scaled to fit the button
61void CGUIButton::setScaleImage(bool scaleImage)
62{
63 ScaleImage = scaleImage;
64}
65
66
67//! Returns whether the button scale the used images
68bool CGUIButton::isScalingImage() const
69{
70 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
71 return ScaleImage;
72}
73
74
75//! Sets if the button should use the skin to draw its border
76void CGUIButton::setDrawBorder(bool border)
77{
78 DrawBorder = border;
79}
80
81
82void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
83{
84 if (sprites)
85 sprites->grab();
86
87 if (SpriteBank)
88 SpriteBank->drop();
89
90 SpriteBank = sprites;
91}
92
93
94void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
95{
96 if (SpriteBank)
97 {
98 ButtonSprites[(u32)state].Index = index;
99 ButtonSprites[(u32)state].Color = color;
100 ButtonSprites[(u32)state].Loop = loop;
101 }
102 else
103 {
104 ButtonSprites[(u32)state].Index = -1;
105 }
106}
107
108
109//! called if an event happened.
110bool CGUIButton::OnEvent(const SEvent& event)
111{
112 if (!isEnabled())
113 return IGUIElement::OnEvent(event);
114
115 switch(event.EventType)
116 {
117 case EET_KEY_INPUT_EVENT:
118 if (event.KeyInput.PressedDown &&
119 (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
120 {
121 if (!IsPushButton)
122 setPressed(true);
123 else
124 setPressed(!Pressed);
125
126 return true;
127 }
128 if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
129 {
130 setPressed(false);
131 return true;
132 }
133 else
134 if (!event.KeyInput.PressedDown && Pressed &&
135 (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
136 {
137
138 if (!IsPushButton)
139 setPressed(false);
140
141 if (Parent)
142 {
143 SEvent newEvent;
144 newEvent.EventType = EET_GUI_EVENT;
145 newEvent.GUIEvent.Caller = this;
146 newEvent.GUIEvent.Element = 0;
147 newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
148 Parent->OnEvent(newEvent);
149 }
150 return true;
151 }
152 break;
153 case EET_GUI_EVENT:
154 if (event.GUIEvent.Caller == this)
155 {
156 if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
157 {
158 if (!IsPushButton)
159 setPressed(false);
160 FocusTime = os::Timer::getTime();
161 }
162 else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
163 {
164 FocusTime = os::Timer::getTime();
165 }
166 else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
167 {
168 HoverTime = os::Timer::getTime();
169 }
170 }
171 break;
172 case EET_MOUSE_INPUT_EVENT:
173 if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
174 {
175 if (Environment->hasFocus(this) &&
176 !AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
177 {
178 Environment->removeFocus(this);
179 return false;
180 }
181
182 if (!IsPushButton)
183 setPressed(true);
184
185 Environment->setFocus(this);
186 return true;
187 }
188 else
189 if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
190 {
191 bool wasPressed = Pressed;
192
193 if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
194 {
195 if (!IsPushButton)
196 setPressed(false);
197 return true;
198 }
199
200 if (!IsPushButton)
201 setPressed(false);
202 else
203 {
204 setPressed(!Pressed);
205 }
206
207 if ((!IsPushButton && wasPressed && Parent) ||
208 (IsPushButton && wasPressed != Pressed))
209 {
210 SEvent newEvent;
211 newEvent.EventType = EET_GUI_EVENT;
212 newEvent.GUIEvent.Caller = this;
213 newEvent.GUIEvent.Element = 0;
214 newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
215 Parent->OnEvent(newEvent);
216 }
217
218 return true;
219 }
220 break;
221 default:
222 break;
223 }
224
225 return Parent ? Parent->OnEvent(event) : false;
226}
227
228
229//! draws the element and its children
230void CGUIButton::draw()
231{
232 if (!IsVisible)
233 return;
234
235 IGUISkin* skin = Environment->getSkin();
236 video::IVideoDriver* driver = Environment->getVideoDriver();
237
238 // todo: move sprite up and text down if the pressed state has a sprite
239 const core::position2di spritePos = AbsoluteRect.getCenter();
240
241 if (!Pressed)
242 {
243 if (DrawBorder)
244 skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
245
246 if (Image)
247 {
248 core::position2d<s32> pos = spritePos;
249 pos.X -= ImageRect.getWidth() / 2;
250 pos.Y -= ImageRect.getHeight() / 2;
251
252 driver->draw2DImage(Image,
253 ScaleImage? AbsoluteRect :
254 core::recti(pos, ImageRect.getSize()),
255 ImageRect, &AbsoluteClippingRect,
256 0, UseAlphaChannel);
257 }
258 }
259 else
260 {
261 if (DrawBorder)
262 skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
263
264 if (PressedImage)
265 {
266 core::position2d<s32> pos = spritePos;
267 pos.X -= PressedImageRect.getWidth() / 2;
268 pos.Y -= PressedImageRect.getHeight() / 2;
269
270 if (Image == PressedImage && PressedImageRect == ImageRect)
271 {
272 pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
273 pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
274 }
275 driver->draw2DImage(PressedImage,
276 ScaleImage? AbsoluteRect :
277 core::recti(pos, PressedImageRect.getSize()),
278 PressedImageRect, &AbsoluteClippingRect,
279 0, UseAlphaChannel);
280 }
281 }
282
283 if (SpriteBank)
284 {
285 // pressed / unpressed animation
286 u32 state = Pressed ? (u32)EGBS_BUTTON_DOWN : (u32)EGBS_BUTTON_UP;
287 if (ButtonSprites[state].Index != -1)
288 {
289 SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
290 &AbsoluteClippingRect, ButtonSprites[state].Color, ClickTime, os::Timer::getTime(),
291 ButtonSprites[state].Loop, true);
292 }
293
294 // focused / unfocused animation
295 state = Environment->hasFocus(this) ? (u32)EGBS_BUTTON_FOCUSED : (u32)EGBS_BUTTON_NOT_FOCUSED;
296 if (ButtonSprites[state].Index != -1)
297 {
298 SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
299 &AbsoluteClippingRect, ButtonSprites[state].Color, FocusTime, os::Timer::getTime(),
300 ButtonSprites[state].Loop, true);
301 }
302
303 // mouse over / off animation
304 if (isEnabled())
305 {
306 state = Environment->getHovered() == this ? (u32)EGBS_BUTTON_MOUSE_OVER : (u32)EGBS_BUTTON_MOUSE_OFF;
307 if (ButtonSprites[state].Index != -1)
308 {
309 SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
310 &AbsoluteClippingRect, ButtonSprites[state].Color, HoverTime, os::Timer::getTime(),
311 ButtonSprites[state].Loop, true);
312 }
313 }
314 }
315
316 if (Text.size())
317 {
318 IGUIFont* font = getActiveFont();
319
320 core::rect<s32> rect = AbsoluteRect;
321 if (Pressed)
322 {
323 rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
324 rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
325 }
326
327 if (font)
328 font->draw(Text.c_str(), rect,
329 skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
330 true, true, &AbsoluteClippingRect);
331 }
332
333 IGUIElement::draw();
334}
335
336
337//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
338void CGUIButton::setOverrideFont(IGUIFont* font)
339{
340 if (OverrideFont == font)
341 return;
342
343 if (OverrideFont)
344 OverrideFont->drop();
345
346 OverrideFont = font;
347
348 if (OverrideFont)
349 OverrideFont->grab();
350}
351
352//! Gets the override font (if any)
353IGUIFont * CGUIButton::getOverrideFont() const
354{
355 return OverrideFont;
356}
357
358//! Get the font which is used right now for drawing
359IGUIFont* CGUIButton::getActiveFont() const
360{
361 if ( OverrideFont )
362 return OverrideFont;
363 IGUISkin* skin = Environment->getSkin();
364 if (skin)
365 return skin->getFont(EGDF_BUTTON);
366 return 0;
367}
368
369//! Sets an image which should be displayed on the button when it is in normal state.
370void CGUIButton::setImage(video::ITexture* image)
371{
372 if (image)
373 image->grab();
374 if (Image)
375 Image->drop();
376
377 Image = image;
378 if (image)
379 ImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
380
381 if (!PressedImage)
382 setPressedImage(Image);
383}
384
385
386//! Sets the image which should be displayed on the button when it is in its normal state.
387void CGUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos)
388{
389 setImage(image);
390 ImageRect = pos;
391}
392
393
394//! Sets an image which should be displayed on the button when it is in pressed state.
395void CGUIButton::setPressedImage(video::ITexture* image)
396{
397 if (image)
398 image->grab();
399
400 if (PressedImage)
401 PressedImage->drop();
402
403 PressedImage = image;
404 if (image)
405 PressedImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
406}
407
408
409//! Sets the image which should be displayed on the button when it is in its pressed state.
410void CGUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos)
411{
412 setPressedImage(image);
413 PressedImageRect = pos;
414}
415
416
417//! Sets if the button should behave like a push button. Which means it
418//! can be in two states: Normal or Pressed. With a click on the button,
419//! the user can change the state of the button.
420void CGUIButton::setIsPushButton(bool isPushButton)
421{
422 IsPushButton = isPushButton;
423}
424
425
426//! Returns if the button is currently pressed
427bool CGUIButton::isPressed() const
428{
429 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
430 return Pressed;
431}
432
433
434//! Sets the pressed state of the button if this is a pushbutton
435void CGUIButton::setPressed(bool pressed)
436{
437 if (Pressed != pressed)
438 {
439 ClickTime = os::Timer::getTime();
440 Pressed = pressed;
441 }
442}
443
444
445//! Returns whether the button is a push button
446bool CGUIButton::isPushButton() const
447{
448 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
449 return IsPushButton;
450}
451
452
453//! Sets if the alpha channel should be used for drawing images on the button (default is false)
454void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
455{
456 UseAlphaChannel = useAlphaChannel;
457}
458
459
460//! Returns if the alpha channel should be used for drawing images on the button
461bool CGUIButton::isAlphaChannelUsed() const
462{
463 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
464 return UseAlphaChannel;
465}
466
467
468bool CGUIButton::isDrawingBorder() const
469{
470 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
471 return DrawBorder;
472}
473
474
475//! Writes attributes of the element.
476void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
477{
478 IGUIButton::serializeAttributes(out,options);
479
480 out->addBool ("PushButton", IsPushButton );
481 if (IsPushButton)
482 out->addBool("Pressed", Pressed);
483
484 out->addTexture ("Image", Image);
485 out->addRect ("ImageRect", ImageRect);
486 out->addTexture ("PressedImage", PressedImage);
487 out->addRect ("PressedImageRect", PressedImageRect);
488
489 out->addBool ("UseAlphaChannel", isAlphaChannelUsed());
490 out->addBool ("Border", isDrawingBorder());
491 out->addBool ("ScaleImage", isScalingImage());
492
493 // out->addString ("OverrideFont", OverrideFont);
494}
495
496
497//! Reads attributes of the element
498void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
499{
500 IGUIButton::deserializeAttributes(in,options);
501
502 IsPushButton = in->getAttributeAsBool("PushButton");
503 Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false;
504
505 core::rect<s32> rec = in->getAttributeAsRect("ImageRect");
506 if (rec.isValid())
507 setImage( in->getAttributeAsTexture("Image"), rec);
508 else
509 setImage( in->getAttributeAsTexture("Image") );
510
511 rec = in->getAttributeAsRect("PressedImageRect");
512 if (rec.isValid())
513 setPressedImage( in->getAttributeAsTexture("PressedImage"), rec);
514 else
515 setPressedImage( in->getAttributeAsTexture("PressedImage") );
516
517 setDrawBorder(in->getAttributeAsBool("Border"));
518 setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));
519 setScaleImage(in->getAttributeAsBool("ScaleImage"));
520
521 // setOverrideFont(in->getAttributeAsString("OverrideFont"));
522
523 updateAbsolutePosition();
524}
525
526
527} // end namespace gui
528} // end namespace irr
529
530#endif // _IRR_COMPILE_WITH_GUI_
531