]> git.lizzy.rs Git - dragonfireclient.git/blob - src/gui/guiButton.cpp
Remove the dependency on FGIMG/BGIMG from the hovered/pressed variants
[dragonfireclient.git] / src / gui / guiButton.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "guiButton.h"\r
6 \r
7 \r
8 #include "client/guiscalingfilter.h"\r
9 #include "client/tile.h"\r
10 #include "IGUISkin.h"\r
11 #include "IGUIEnvironment.h"\r
12 #include "IVideoDriver.h"\r
13 #include "IGUIFont.h"\r
14 #include "irrlicht_changes/static_text.h"\r
15 #include "porting.h"\r
16 #include "StyleSpec.h"\r
17 \r
18 using namespace irr;\r
19 using namespace gui;\r
20 \r
21 // Multiply with a color to get the default corresponding hovered color\r
22 #define COLOR_HOVERED_MOD 1.25f\r
23 \r
24 // Multiply with a color to get the default corresponding pressed color\r
25 #define COLOR_PRESSED_MOD 0.85f\r
26 \r
27 //! constructor\r
28 GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent,\r
29                         s32 id, core::rect<s32> rectangle, bool noclip)\r
30 : IGUIButton(environment, parent, id, rectangle),\r
31         SpriteBank(0), OverrideFont(0),\r
32         OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)),\r
33         ClickTime(0), HoverTime(0), FocusTime(0),\r
34         ClickShiftState(false), ClickControlState(false),\r
35         IsPushButton(false), Pressed(false),\r
36         UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)\r
37 {\r
38         setNotClipped(noclip);\r
39 \r
40         // This element can be tabbed.\r
41         setTabStop(true);\r
42         setTabOrder(-1);\r
43 \r
44         // PATCH\r
45         for (size_t i = 0; i < 4; i++) {\r
46                 Colors[i] = Environment->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);\r
47                 HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(),\r
48                         core::clamp<u32>(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255),\r
49                         core::clamp<u32>(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255),\r
50                         core::clamp<u32>(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255));\r
51                 PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(),\r
52                         core::clamp<u32>(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255),\r
53                         core::clamp<u32>(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255),\r
54                         core::clamp<u32>(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255));\r
55         }\r
56         \r
57         StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id);\r
58         StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);\r
59         // END PATCH\r
60 }\r
61 \r
62 //! destructor\r
63 GUIButton::~GUIButton()\r
64 {\r
65         if (OverrideFont)\r
66                 OverrideFont->drop();\r
67 \r
68         if (SpriteBank)\r
69                 SpriteBank->drop();\r
70 }\r
71 \r
72 \r
73 //! Sets if the images should be scaled to fit the button\r
74 void GUIButton::setScaleImage(bool scaleImage)\r
75 {\r
76         ScaleImage = scaleImage;\r
77 }\r
78 \r
79 \r
80 //! Returns whether the button scale the used images\r
81 bool GUIButton::isScalingImage() const\r
82 {\r
83         return ScaleImage;\r
84 }\r
85 \r
86 \r
87 //! Sets if the button should use the skin to draw its border\r
88 void GUIButton::setDrawBorder(bool border)\r
89 {\r
90         DrawBorder = border;\r
91 }\r
92 \r
93 \r
94 void GUIButton::setSpriteBank(IGUISpriteBank* sprites)\r
95 {\r
96         if (sprites)\r
97                 sprites->grab();\r
98 \r
99         if (SpriteBank)\r
100                 SpriteBank->drop();\r
101 \r
102         SpriteBank = sprites;\r
103 }\r
104 \r
105 void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)\r
106 {\r
107         ButtonSprites[(u32)state].Index = index;\r
108         ButtonSprites[(u32)state].Color = color;\r
109         ButtonSprites[(u32)state].Loop  = loop;\r
110         ButtonSprites[(u32)state].Scale = scale;\r
111 }\r
112 \r
113 //! Get the sprite-index for the given state or -1 when no sprite is set\r
114 s32 GUIButton::getSpriteIndex(EGUI_BUTTON_STATE state) const\r
115 {\r
116         return ButtonSprites[(u32)state].Index;\r
117 }\r
118 \r
119 //! Get the sprite color for the given state. Color is only used when a sprite is set.\r
120 video::SColor GUIButton::getSpriteColor(EGUI_BUTTON_STATE state) const\r
121 {\r
122         return ButtonSprites[(u32)state].Color;\r
123 }\r
124 \r
125 //! Returns if the sprite in the given state does loop\r
126 bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const\r
127 {\r
128         return ButtonSprites[(u32)state].Loop;\r
129 }\r
130 \r
131 //! Returns if the sprite in the given state is scaled\r
132 bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const\r
133 {\r
134         return ButtonSprites[(u32)state].Scale;\r
135 }\r
136 \r
137 //! called if an event happened.\r
138 bool GUIButton::OnEvent(const SEvent& event)\r
139 {\r
140         if (!isEnabled())\r
141                 return IGUIElement::OnEvent(event);\r
142 \r
143         switch(event.EventType)\r
144         {\r
145         case EET_KEY_INPUT_EVENT:\r
146                 if (event.KeyInput.PressedDown &&\r
147                         (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))\r
148                 {\r
149                         if (!IsPushButton)\r
150                                 setPressed(true);\r
151                         else\r
152                                 setPressed(!Pressed);\r
153 \r
154                         return true;\r
155                 }\r
156                 if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)\r
157                 {\r
158                         setPressed(false);\r
159                         return true;\r
160                 }\r
161                 else\r
162                 if (!event.KeyInput.PressedDown && Pressed &&\r
163                         (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))\r
164                 {\r
165 \r
166                         if (!IsPushButton)\r
167                                 setPressed(false);\r
168 \r
169                         if (Parent)\r
170                         {\r
171                                 ClickShiftState = event.KeyInput.Shift;\r
172                                 ClickControlState = event.KeyInput.Control;\r
173 \r
174                                 SEvent newEvent;\r
175                                 newEvent.EventType = EET_GUI_EVENT;\r
176                                 newEvent.GUIEvent.Caller = this;\r
177                                 newEvent.GUIEvent.Element = 0;\r
178                                 newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;\r
179                                 Parent->OnEvent(newEvent);\r
180                         }\r
181                         return true;\r
182                 }\r
183                 break;\r
184         case EET_GUI_EVENT:\r
185                 if (event.GUIEvent.Caller == this)\r
186                 {\r
187                         if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)\r
188                         {\r
189                                 if (!IsPushButton)\r
190                                         setPressed(false);\r
191                                 FocusTime = (u32)porting::getTimeMs();\r
192                         }\r
193                         else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)\r
194                         {\r
195                                 FocusTime = (u32)porting::getTimeMs();\r
196                         }\r
197                         else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)\r
198                         {\r
199                                 HoverTime = (u32)porting::getTimeMs();\r
200                         }\r
201                 }\r
202                 break;\r
203         case EET_MOUSE_INPUT_EVENT:\r
204                 if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)\r
205                 {\r
206                         if (!IsPushButton)\r
207                                 setPressed(true);\r
208 \r
209                         return true;\r
210                 }\r
211                 else\r
212                 if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)\r
213                 {\r
214                         bool wasPressed = Pressed;\r
215 \r
216                         if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )\r
217                         {\r
218                                 if (!IsPushButton)\r
219                                         setPressed(false);\r
220                                 return true;\r
221                         }\r
222 \r
223                         if (!IsPushButton)\r
224                                 setPressed(false);\r
225                         else\r
226                         {\r
227                                 setPressed(!Pressed);\r
228                         }\r
229 \r
230                         if ((!IsPushButton && wasPressed && Parent) ||\r
231                                 (IsPushButton && wasPressed != Pressed))\r
232                         {\r
233                                 ClickShiftState = event.MouseInput.Shift;\r
234                                 ClickControlState = event.MouseInput.Control;\r
235 \r
236                                 SEvent newEvent;\r
237                                 newEvent.EventType = EET_GUI_EVENT;\r
238                                 newEvent.GUIEvent.Caller = this;\r
239                                 newEvent.GUIEvent.Element = 0;\r
240                                 newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;\r
241                                 Parent->OnEvent(newEvent);\r
242                         }\r
243 \r
244                         return true;\r
245                 }\r
246                 break;\r
247         default:\r
248                 break;\r
249         }\r
250 \r
251         return Parent ? Parent->OnEvent(event) : false;\r
252 }\r
253 \r
254 \r
255 //! draws the element and its children\r
256 void GUIButton::draw()\r
257 {\r
258         if (!IsVisible)\r
259                 return;\r
260 \r
261         // PATCH\r
262         GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());\r
263         video::IVideoDriver* driver = Environment->getVideoDriver();\r
264         // END PATCH\r
265 \r
266         if (DrawBorder)\r
267         {\r
268                 if (!Pressed)\r
269                 {\r
270                         // PATCH\r
271                         skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect,\r
272                                 isHovered() ? HoveredColors : Colors);\r
273                         // END PATCH\r
274                 }\r
275                 else\r
276                 {\r
277                         // PATCH\r
278                         skin->drawColored3DButtonPanePressed(this,\r
279                                         AbsoluteRect, &AbsoluteClippingRect, PressedColors);\r
280                         // END PATCH\r
281                 }\r
282         }\r
283 \r
284         const core::position2di buttonCenter(AbsoluteRect.getCenter());\r
285         EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed);\r
286         if ( ButtonImages[(u32)imageState].Texture )\r
287         {\r
288                 core::position2d<s32> pos(buttonCenter);\r
289                 core::rect<s32> sourceRect(ButtonImages[(u32)imageState].SourceRect);\r
290                 if ( sourceRect.getWidth() == 0 && sourceRect.getHeight() == 0 )\r
291                         sourceRect = core::rect<s32>(core::position2di(0,0), ButtonImages[(u32)imageState].Texture->getOriginalSize());\r
292 \r
293                 pos.X -= sourceRect.getWidth() / 2;\r
294                 pos.Y -= sourceRect.getHeight() / 2;\r
295 \r
296                 if ( Pressed )\r
297                 {\r
298                         // Create a pressed-down effect by moving the image when it looks identical to the unpressed state image\r
299                         EGUI_BUTTON_IMAGE_STATE unpressedState = getImageState(false);\r
300                         if ( unpressedState == imageState || ButtonImages[(u32)imageState] == ButtonImages[(u32)unpressedState] )\r
301                         {\r
302                                 pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);\r
303                                 pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);\r
304                         }\r
305                 }\r
306 \r
307                 driver->draw2DImage(ButtonImages[(u32)imageState].Texture,\r
308                                 ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),\r
309                                 sourceRect, &AbsoluteClippingRect,\r
310                                 0, UseAlphaChannel);\r
311         }\r
312 \r
313         if (SpriteBank)\r
314         {\r
315                 core::position2di pos(buttonCenter);\r
316 \r
317                 if (isEnabled())\r
318                 {\r
319                         // pressed / unpressed animation\r
320                         EGUI_BUTTON_STATE state = Pressed ? EGBS_BUTTON_DOWN : EGBS_BUTTON_UP;\r
321                         drawSprite(state, ClickTime, pos);\r
322 \r
323                         // focused / unfocused animation\r
324                         state = Environment->hasFocus(this) ? EGBS_BUTTON_FOCUSED : EGBS_BUTTON_NOT_FOCUSED;\r
325                         drawSprite(state, FocusTime, pos);\r
326 \r
327                         // mouse over / off animation\r
328                         state = isHovered() ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;\r
329                         drawSprite(state, HoverTime, pos);\r
330                 }\r
331                 else\r
332                 {\r
333                         // draw disabled\r
334 //                      drawSprite(EGBS_BUTTON_DISABLED, 0, pos);\r
335                 }\r
336         }\r
337 \r
338         IGUIElement::draw();\r
339 }\r
340 \r
341 void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)\r
342 {\r
343         u32 stateIdx = (u32)state;\r
344 \r
345         if (ButtonSprites[stateIdx].Index != -1)\r
346         {\r
347                 if ( ButtonSprites[stateIdx].Scale )\r
348                 {\r
349                         const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};\r
350                         SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,\r
351                                         &AbsoluteClippingRect, colors[0], // FIXME: remove [0]\r
352                                         porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);\r
353                 }\r
354                 else\r
355                 {\r
356                         SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,\r
357                                 &AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),\r
358                                 ButtonSprites[stateIdx].Loop, true);\r
359                 }\r
360         }\r
361 }\r
362 \r
363 EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const\r
364 {\r
365         // PATCH\r
366         return getImageState(pressed, ButtonImages);\r
367         // END PATCH\r
368 }\r
369 \r
370 EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed, const ButtonImage* images) const\r
371 {\r
372         // figure state we should have\r
373         EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED;\r
374         bool focused = Environment->hasFocus((IGUIElement*)this);\r
375         bool mouseOver = isHovered();\r
376         if (isEnabled())\r
377         {\r
378                 if ( pressed )\r
379                 {\r
380                         if ( focused && mouseOver )\r
381                                 state = EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER;\r
382                         else if ( focused )\r
383                                 state = EGBIS_IMAGE_DOWN_FOCUSED;\r
384                         else if ( mouseOver )\r
385                                 state = EGBIS_IMAGE_DOWN_MOUSEOVER;\r
386                         else\r
387                                 state = EGBIS_IMAGE_DOWN;\r
388                 }\r
389                 else // !pressed\r
390                 {\r
391                         if ( focused && mouseOver )\r
392                                 state = EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER;\r
393                         else if ( focused )\r
394                                 state = EGBIS_IMAGE_UP_FOCUSED;\r
395                         else if ( mouseOver )\r
396                                 state = EGBIS_IMAGE_UP_MOUSEOVER;\r
397                         else\r
398                                 state = EGBIS_IMAGE_UP;\r
399                 }\r
400         }\r
401 \r
402         // find a compatible state that has images\r
403         while ( state != EGBIS_IMAGE_UP && !images[(u32)state].Texture )\r
404         {\r
405                 // PATCH\r
406                 switch ( state )\r
407                 {\r
408                         case EGBIS_IMAGE_UP_FOCUSED:\r
409                                 state = EGBIS_IMAGE_UP;\r
410                                 break;\r
411                         case EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER:\r
412                                 state = EGBIS_IMAGE_UP_FOCUSED;\r
413                                 break;\r
414                         case EGBIS_IMAGE_DOWN_MOUSEOVER:\r
415                                 state = EGBIS_IMAGE_DOWN;\r
416                                 break;\r
417                         case EGBIS_IMAGE_DOWN_FOCUSED:\r
418                                 state = EGBIS_IMAGE_DOWN;\r
419                                 break;\r
420                         case EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER:\r
421                                 state = EGBIS_IMAGE_DOWN_FOCUSED;\r
422                                 break;\r
423                         case EGBIS_IMAGE_DISABLED:\r
424                                 if ( pressed )\r
425                                         state = EGBIS_IMAGE_DOWN;\r
426                                 else\r
427                                         state = EGBIS_IMAGE_UP;\r
428                                 break;\r
429                         default:\r
430                                 state = EGBIS_IMAGE_UP;\r
431                 }\r
432                 // END PATCH\r
433         }\r
434 \r
435         return state;\r
436 }\r
437 \r
438 //! sets another skin independent font. if this is set to zero, the button uses the font of the skin.\r
439 void GUIButton::setOverrideFont(IGUIFont* font)\r
440 {\r
441         if (OverrideFont == font)\r
442                 return;\r
443 \r
444         if (OverrideFont)\r
445                 OverrideFont->drop();\r
446 \r
447         OverrideFont = font;\r
448 \r
449         if (OverrideFont)\r
450                 OverrideFont->grab();\r
451 \r
452         StaticText->setOverrideFont(font);\r
453 }\r
454 \r
455 //! Gets the override font (if any)\r
456 IGUIFont * GUIButton::getOverrideFont() const\r
457 {\r
458         return OverrideFont;\r
459 }\r
460 \r
461 //! Get the font which is used right now for drawing\r
462 IGUIFont* GUIButton::getActiveFont() const\r
463 {\r
464         if ( OverrideFont )\r
465                 return OverrideFont;\r
466         IGUISkin* skin = Environment->getSkin();\r
467         if (skin)\r
468                 return skin->getFont(EGDF_BUTTON);\r
469         return 0;\r
470 }\r
471 \r
472 //! Sets another color for the text.\r
473 void GUIButton::setOverrideColor(video::SColor color)\r
474 {\r
475         OverrideColor = color;\r
476         OverrideColorEnabled = true;\r
477 \r
478         StaticText->setOverrideColor(color);\r
479 }\r
480 \r
481 video::SColor GUIButton::getOverrideColor() const\r
482 {\r
483         return OverrideColor;\r
484 }\r
485 \r
486 void GUIButton::enableOverrideColor(bool enable)\r
487 {\r
488         OverrideColorEnabled = enable;\r
489 }\r
490 \r
491 bool GUIButton::isOverrideColorEnabled() const\r
492 {\r
493         return OverrideColorEnabled;\r
494 }\r
495 \r
496 void GUIButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image, const core::rect<s32>& sourceRect)\r
497 {\r
498         if ( state >= EGBIS_COUNT )\r
499                 return;\r
500 \r
501         if ( image )\r
502                 image->grab();\r
503 \r
504         u32 stateIdx = (u32)state;\r
505         if ( ButtonImages[stateIdx].Texture )\r
506                 ButtonImages[stateIdx].Texture->drop();\r
507 \r
508         ButtonImages[stateIdx].Texture = image;\r
509         ButtonImages[stateIdx].SourceRect = sourceRect;\r
510 }\r
511 \r
512 // PATCH\r
513 void GUIButton::setImage(video::ITexture* image)\r
514 {\r
515         setImage(gui::EGBIS_IMAGE_UP, image);\r
516 }\r
517 \r
518 void GUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos)\r
519 {\r
520         setImage(gui::EGBIS_IMAGE_UP, image, pos);\r
521 }\r
522 \r
523 void GUIButton::setPressedImage(video::ITexture* image)\r
524 {\r
525         setImage(gui::EGBIS_IMAGE_DOWN, image);\r
526 }\r
527 \r
528 void GUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos)\r
529 {\r
530         setImage(gui::EGBIS_IMAGE_DOWN, image, pos);\r
531 }\r
532 \r
533 void GUIButton::setHoveredImage(video::ITexture* image)\r
534 {\r
535         setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image);\r
536         setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image);\r
537 }\r
538 \r
539 void GUIButton::setHoveredImage(video::ITexture* image, const core::rect<s32>& pos)\r
540 {\r
541         setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos);\r
542         setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos);\r
543 }\r
544 \r
545 //! Sets the text displayed by the button\r
546 void GUIButton::setText(const wchar_t* text)\r
547 {\r
548         StaticText->setText(text);\r
549 \r
550         IGUIButton::setText(text);\r
551 }\r
552 // END PATCH\r
553 \r
554 //! Sets if the button should behave like a push button. Which means it\r
555 //! can be in two states: Normal or Pressed. With a click on the button,\r
556 //! the user can change the state of the button.\r
557 void GUIButton::setIsPushButton(bool isPushButton)\r
558 {\r
559         IsPushButton = isPushButton;\r
560 }\r
561 \r
562 \r
563 //! Returns if the button is currently pressed\r
564 bool GUIButton::isPressed() const\r
565 {\r
566         return Pressed;\r
567 }\r
568 \r
569 // PATCH\r
570 //! Returns if this element (or one of its direct children) is hovered\r
571 bool GUIButton::isHovered() const\r
572 {\r
573         IGUIElement *hovered = Environment->getHovered();\r
574         return  hovered == this || (hovered != nullptr && hovered->getParent() == this);\r
575 }\r
576 // END PATCH\r
577 \r
578 //! Sets the pressed state of the button if this is a pushbutton\r
579 void GUIButton::setPressed(bool pressed)\r
580 {\r
581         if (Pressed != pressed)\r
582         {\r
583                 ClickTime = porting::getTimeMs();\r
584                 Pressed = pressed;\r
585 \r
586                 GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());\r
587 \r
588                 for(IGUIElement *child : getChildren())\r
589                 {\r
590                         core::rect<s32> originalRect = child->getRelativePosition();\r
591                         if (Pressed) {\r
592                                 child->setRelativePosition(originalRect +\r
593                                                 core::dimension2d<s32>(\r
594                                                         skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),\r
595                                                         skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));\r
596                         } else {\r
597                                 child->setRelativePosition(originalRect -\r
598                                                 core::dimension2d<s32>(\r
599                                                         skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),\r
600                                                         skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));\r
601                         }\r
602                 }\r
603         }\r
604 }\r
605 \r
606 \r
607 //! Returns whether the button is a push button\r
608 bool GUIButton::isPushButton() const\r
609 {\r
610         return IsPushButton;\r
611 }\r
612 \r
613 \r
614 //! Sets if the alpha channel should be used for drawing images on the button (default is false)\r
615 void GUIButton::setUseAlphaChannel(bool useAlphaChannel)\r
616 {\r
617         UseAlphaChannel = useAlphaChannel;\r
618 }\r
619 \r
620 \r
621 //! Returns if the alpha channel should be used for drawing images on the button\r
622 bool GUIButton::isAlphaChannelUsed() const\r
623 {\r
624         return UseAlphaChannel;\r
625 }\r
626 \r
627 \r
628 bool GUIButton::isDrawingBorder() const\r
629 {\r
630         return DrawBorder;\r
631 }\r
632 \r
633 \r
634 //! Writes attributes of the element.\r
635 void GUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const\r
636 {\r
637         IGUIButton::serializeAttributes(out,options);\r
638 \r
639         out->addBool    ("PushButton",          IsPushButton );\r
640         if (IsPushButton)\r
641                 out->addBool("Pressed",             Pressed);\r
642 \r
643         for ( u32 i=0; i<(u32)EGBIS_COUNT; ++i )\r
644         {\r
645                 if ( ButtonImages[i].Texture )\r
646                 {\r
647                         core::stringc name( GUIButtonImageStateNames[i] );\r
648                         out->addTexture(name.c_str(), ButtonImages[i].Texture);\r
649                         name += "Rect";\r
650                         out->addRect(name.c_str(), ButtonImages[i].SourceRect);\r
651                 }\r
652         }\r
653 \r
654         out->addBool    ("UseAlphaChannel",     UseAlphaChannel);\r
655         out->addBool    ("Border",                  DrawBorder);\r
656         out->addBool    ("ScaleImage",          ScaleImage);\r
657 \r
658         for ( u32 i=0; i<(u32)EGBS_COUNT; ++i )\r
659         {\r
660                 if ( ButtonSprites[i].Index >= 0 )\r
661                 {\r
662                         core::stringc nameIndex( GUIButtonStateNames[i] );\r
663                         nameIndex += "Index";\r
664                         out->addInt(nameIndex.c_str(), ButtonSprites[i].Index );\r
665 \r
666                         core::stringc nameColor( GUIButtonStateNames[i] );\r
667                         nameColor += "Color";\r
668                         out->addColor(nameColor.c_str(), ButtonSprites[i].Color );\r
669 \r
670                         core::stringc nameLoop( GUIButtonStateNames[i] );\r
671                         nameLoop += "Loop";\r
672                         out->addBool(nameLoop.c_str(), ButtonSprites[i].Loop );\r
673 \r
674                         core::stringc nameScale( GUIButtonStateNames[i] );\r
675                         nameScale += "Scale";\r
676                         out->addBool(nameScale.c_str(), ButtonSprites[i].Scale );\r
677                 }\r
678         }\r
679 \r
680         //   out->addString  ("OverrideFont",   OverrideFont);\r
681 }\r
682 \r
683 \r
684 //! Reads attributes of the element\r
685 void GUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)\r
686 {\r
687         IGUIButton::deserializeAttributes(in,options);\r
688 \r
689         IsPushButton    = in->getAttributeAsBool("PushButton");\r
690         Pressed         = IsPushButton ? in->getAttributeAsBool("Pressed") : false;\r
691 \r
692         core::rect<s32> rec = in->getAttributeAsRect("ImageRect");\r
693         if (rec.isValid())\r
694                 setImage( in->getAttributeAsTexture("Image"), rec);\r
695         else\r
696                 setImage( in->getAttributeAsTexture("Image") );\r
697 \r
698         rec = in->getAttributeAsRect("PressedImageRect");\r
699         if (rec.isValid())\r
700                 setPressedImage( in->getAttributeAsTexture("PressedImage"), rec);\r
701         else\r
702                 setPressedImage( in->getAttributeAsTexture("PressedImage") );\r
703 \r
704         setDrawBorder(in->getAttributeAsBool("Border"));\r
705         setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));\r
706         setScaleImage(in->getAttributeAsBool("ScaleImage"));\r
707 \r
708         //   setOverrideFont(in->getAttributeAsString("OverrideFont"));\r
709 \r
710         updateAbsolutePosition();\r
711 }\r
712 \r
713 // PATCH\r
714 GUIButton* GUIButton::addButton(IGUIEnvironment *environment, const core::rect<s32>& rectangle,\r
715                                                                 IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)\r
716 {\r
717         GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle);\r
718         if (text)\r
719                 button->setText(text);\r
720 \r
721         if ( tooltiptext )\r
722                 button->setToolTipText ( tooltiptext );\r
723 \r
724         button->drop();\r
725         return button;\r
726 }\r
727 \r
728 void GUIButton::setColor(video::SColor color)\r
729 {\r
730         float d = 0.65f;\r
731         for (size_t i = 0; i < 4; i++) {\r
732                 video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);\r
733                 Colors[i] = base.getInterpolated(color, d);\r
734                 HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(),\r
735                         core::clamp<u32>(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255),\r
736                         core::clamp<u32>(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255),\r
737                         core::clamp<u32>(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255));\r
738                 PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(),\r
739                         core::clamp<u32>(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255),\r
740                         core::clamp<u32>(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255),\r
741                         core::clamp<u32>(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255));\r
742         }\r
743 }\r
744 void GUIButton::setHoveredColor(video::SColor color)\r
745 {\r
746         float d = 0.65f;\r
747         for (size_t i = 0; i < 4; i++) {\r
748                 video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);\r
749                 HoveredColors[i] = base.getInterpolated(color, d);\r
750         }\r
751 }\r
752 void GUIButton::setPressedColor(video::SColor color)\r
753 {\r
754         float d = 0.65f;\r
755         for (size_t i = 0; i < 4; i++) {\r
756                 video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);\r
757                 PressedColors[i] = base.getInterpolated(color, d);\r
758         }\r
759 }\r
760 \r
761 //! Set element properties from a StyleSpec\r
762 void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc)\r
763 {\r
764         if (style.isNotDefault(StyleSpec::BGCOLOR)) {\r
765                 setColor(style.getColor(StyleSpec::BGCOLOR));\r
766         }\r
767         if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) {\r
768                 setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED));\r
769         }\r
770         if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) {\r
771                 setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED));\r
772         }\r
773 \r
774         if (style.isNotDefault(StyleSpec::TEXTCOLOR)) {\r
775                 setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));\r
776         }\r
777         setNotClipped(style.getBool(StyleSpec::NOCLIP, isNotClipped()));\r
778         setDrawBorder(style.getBool(StyleSpec::BORDER, DrawBorder));\r
779         setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));\r
780 \r
781         const core::position2di buttonCenter(AbsoluteRect.getCenter());\r
782         core::position2d<s32> geom(buttonCenter);\r
783         if (style.isNotDefault(StyleSpec::BGIMG)) {\r
784                 video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, tsrc);\r
785 \r
786                 setImage(guiScalingImageButton(\r
787                                         Environment->getVideoDriver(), texture, geom.X, geom.Y));\r
788                 setScaleImage(true);\r
789         }\r
790         if (style.isNotDefault(StyleSpec::BGIMG_HOVERED)) {\r
791                 video::ITexture *hovered_texture = style.getTexture(StyleSpec::BGIMG_HOVERED, tsrc);\r
792 \r
793                 setHoveredImage(guiScalingImageButton(\r
794                                         Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y));\r
795                 setScaleImage(true);\r
796         }\r
797         if (style.isNotDefault(StyleSpec::BGIMG_PRESSED)) {\r
798                 video::ITexture *pressed_texture = style.getTexture(StyleSpec::BGIMG_PRESSED, tsrc);\r
799 \r
800                 setPressedImage(guiScalingImageButton(\r
801                                         Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));\r
802                 setScaleImage(true);\r
803         }\r
804 }\r
805 // END PATCH\r