+\r
+//! Set element properties from a StyleSpec corresponding to the button state\r
+void GUIButton::setFromState()\r
+{\r
+ StyleSpec::State state = StyleSpec::STATE_DEFAULT;\r
+\r
+ if (isPressed())\r
+ state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_PRESSED);\r
+\r
+ if (isHovered())\r
+ state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_HOVERED);\r
+\r
+ setFromStyle(StyleSpec::getStyleFromStatePropagation(Styles, state));\r
+}\r
+\r
+//! Set element properties from a StyleSpec\r
+void GUIButton::setFromStyle(const StyleSpec& style)\r
+{\r
+ bool hovered = (style.getState() & StyleSpec::STATE_HOVERED) != 0;\r
+ bool pressed = (style.getState() & StyleSpec::STATE_PRESSED) != 0;\r
+\r
+ if (style.isNotDefault(StyleSpec::BGCOLOR)) {\r
+\r
+ setColor(style.getColor(StyleSpec::BGCOLOR));\r
+\r
+ // If we have a propagated hover/press color, we need to automatically\r
+ // lighten/darken it\r
+ if (!Styles[style.getState()].isNotDefault(StyleSpec::BGCOLOR)) {\r
+ for (size_t i = 0; i < 4; i++) {\r
+ if (pressed) {\r
+ Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD);\r
+ } else if (hovered) {\r
+ Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD);\r
+ }\r
+ }\r
+ }\r
+\r
+ } else {\r
+ for (size_t i = 0; i < 4; i++) {\r
+ video::SColor base =\r
+ Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);\r
+ if (pressed) {\r
+ Colors[i] = multiplyColorValue(base, COLOR_PRESSED_MOD);\r
+ } else if (hovered) {\r
+ Colors[i] = multiplyColorValue(base, COLOR_HOVERED_MOD);\r
+ } else {\r
+ Colors[i] = base;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (style.isNotDefault(StyleSpec::TEXTCOLOR)) {\r
+ setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));\r
+ } else {\r
+ setOverrideColor(video::SColor(255,255,255,255));\r
+ OverrideColorEnabled = false;\r
+ }\r
+ setNotClipped(style.getBool(StyleSpec::NOCLIP, false));\r
+ setDrawBorder(style.getBool(StyleSpec::BORDER, true));\r
+ setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));\r
+ setOverrideFont(style.getFont());\r
+\r
+ if (style.isNotDefault(StyleSpec::BGIMG)) {\r
+ video::ITexture *texture = style.getTexture(StyleSpec::BGIMG,\r
+ getTextureSource());\r
+ setImage(guiScalingImageButton(\r
+ Environment->getVideoDriver(), texture,\r
+ AbsoluteRect.getWidth(), AbsoluteRect.getHeight()));\r
+ setScaleImage(true);\r
+ } else {\r
+ setImage(nullptr);\r
+ }\r
+\r
+ BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle);\r
+\r
+ // Child padding and offset\r
+ Padding = style.getRect(StyleSpec::PADDING, core::rect<s32>());\r
+ Padding = core::rect<s32>(\r
+ Padding.UpperLeftCorner + BgMiddle.UpperLeftCorner,\r
+ Padding.LowerRightCorner + BgMiddle.LowerRightCorner);\r
+\r
+ GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());\r
+ core::vector2d<s32> defaultPressOffset(\r
+ skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),\r
+ skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y));\r
+ ContentOffset = style.getVector2i(StyleSpec::CONTENT_OFFSET, isPressed()\r
+ ? defaultPressOffset\r
+ : core::vector2d<s32>(0));\r
+\r
+ core::rect<s32> childBounds(\r
+ Padding.UpperLeftCorner.X + ContentOffset.X,\r
+ Padding.UpperLeftCorner.Y + ContentOffset.Y,\r
+ AbsoluteRect.getWidth() + Padding.LowerRightCorner.X + ContentOffset.X,\r
+ AbsoluteRect.getHeight() + Padding.LowerRightCorner.Y + ContentOffset.Y);\r
+\r
+ for (IGUIElement *child : getChildren()) {\r
+ child->setRelativePosition(childBounds);\r
+ }\r
+}\r
+\r
+//! Set the styles used for each state\r
+void GUIButton::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles)\r
+{\r
+ Styles = styles;\r
+ setFromState();\r
+}\r