Formspecs: Add state-selection to style elements (#9378)

This commit is contained in:
Hugues Ross 2020-04-11 16:39:30 -04:00 committed by GitHub
parent ba3587e776
commit f780bae05c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 462 additions and 325 deletions

@ -2188,12 +2188,12 @@ Elements
* 9-sliced background. See https://en.wikipedia.org/wiki/9-slice_scaling
* Middle is a rect which defines the middle of the 9-slice.
* `x` - The middle will be x pixels from all sides.
* `x,y` - The middle will be x pixels from the horizontal and y from the vertical.
* `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values
will be added to the width and height of the texture, allowing it to be used as the
distance from the far end.
* All numbers in middle are integers.
* `x` - The middle will be x pixels from all sides.
* `x,y` - The middle will be x pixels from the horizontal and y from the vertical.
* `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values
will be added to the width and height of the texture, allowing it to be used as the
distance from the far end.
* All numbers in middle are integers.
* Example for formspec 8x4 in 16x resolution:
image shall be sized 8 times 16px times 4 times 16px
* If `auto_clip` is `true`, the background is clipped to the formspec size
@ -2508,16 +2508,28 @@ Elements
* `span=<value>`: number of following columns to affect
(default: infinite).
### `style[<name 1>,<name 2>,...;<prop1>;<prop2>;...]`
### `style[<selector 1>,<selector 2>;<prop1>;<prop2>;...]`
* Set the style for the named element(s) `name`.
* Set the style for the element(s) matching `selector` by name.
* `selector` can be one of:
* `<name>` - An element name.
* `<name>:<state>` - An element name, a colon, and one or more states.
* `state` is a list of states separated by the `+` character.
* If a state is provided, the style will only take effect when the element is in that state.
* All provided states must be active for the style to apply.
* Note: this **must** be before the element is defined.
* See [Styling Formspecs].
### `style_type[<type 1>,<type 2>,...;<prop1>;<prop2>;...]`
### `style_type[<selector 1>,<selector 2>;<prop1>;<prop2>;...]`
* Sets the style for all elements of type(s) `type` which appear after this element.
* Set the style for the element(s) matching `selector` by type.
* `selector` can be one of:
* `<type>` - An element type.
* `<type>:<state>` - An element type, a colon, and one or more states.
* `state` is a list of states separated by the `+` character.
* If a state is provided, the style will only take effect when the element is in that state.
* All provided states must be active for the style to apply.
* See [Styling Formspecs].
Migrating to Real Coordinates
@ -2560,24 +2572,33 @@ Styling Formspecs
Formspec elements can be themed using the style elements:
style[<name 1>,<name 2>,...;<prop1>;<prop2>;...]
style_type[<type 1>,<type 2>,...;<prop1>;<prop2>;...]
style[<name 1>,<name 2>;<prop1>;<prop2>;...]
style[<name 1>:<state>,<name 2>:<state>;<prop1>;<prop2>;...]
style_type[<type 1>,<type 2>;<prop1>;<prop2>;...]
style_type[<type 1>:<state>,<type 2>:<state>;<prop1>;<prop2>;...]
Where a prop is:
property_name=property_value
A name/type can optionally be a comma separated list of names/types, like so:
world_delete,world_create,world_configure
button,image_button
For example:
style_type[button;bgcolor=#006699]
style[world_delete;bgcolor=red;textcolor=yellow]
button[4,3.95;2.6,1;world_delete;Delete]
A name/type can optionally be a comma separated list of names/types, like so:
world_delete,world_create,world_configure
button,image_button
Any name/type in the list can also be accompanied by a `+`-separated list of states, like so:
world_delete:hovered+pressed
button:pressed
States allow you to apply styles in response to changes in the element, instead of applying at all times.
Setting a property to nothing will reset it to the default value. For example:
style_type[button;bgimg=button.png;bgimg_pressed=button_pressed.png;border=false]
@ -2654,6 +2675,14 @@ Some types may inherit styles from parent types.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* textcolor - color. Default white.
### Valid States
* *all elements*
* default - Equivalent to providing no states
* button, button_exit, image_button, item_image_button
* hovered - Active when the mouse is hovering over the element
* pressed - Active when the button is pressed
Markup Language
---------------

@ -65,7 +65,10 @@ local style_fs = [[
style[one_btn13;border=false]
item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor]
style[one_btn14;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png;fgimg=bubble.png;fgimg_hovered=default_apple.png;fgimg_pressed=heart.png]
style[one_btn14;border=false;bgimg=test_bg.png;fgimg=bubble.png]
style[one_btn14:hovered;bgimg=test_bg_hovered.png;fgimg=default_apple.png;textcolor=red]
style[one_btn14:pressed;bgimg=test_bg_pressed.png;fgimg=heart.png;textcolor=green]
style[one_btn14:hovered+pressed;textcolor=blue]
image_button[0,9.6;1,1;bubble.png;one_btn14;Bg]
style[one_btn15;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png]

@ -1556,7 +1556,8 @@ bool Game::connectToServer(const std::string &playername,
} else {
registration_confirmation_shown = true;
(new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1,
&g_menumgr, client, playername, password, connection_aborted))->drop();
&g_menumgr, client, playername, password,
connection_aborted, texture_src))->drop();
}
} else {
wait_time += dtime;
@ -1711,19 +1712,19 @@ inline bool Game::handleCallbacks()
if (g_gamecallback->changepassword_requested) {
(new GUIPasswordChange(guienv, guiroot, -1,
&g_menumgr, client))->drop();
&g_menumgr, client, texture_src))->drop();
g_gamecallback->changepassword_requested = false;
}
if (g_gamecallback->changevolume_requested) {
(new GUIVolumeChange(guienv, guiroot, -1,
&g_menumgr))->drop();
&g_menumgr, texture_src))->drop();
g_gamecallback->changevolume_requested = false;
}
if (g_gamecallback->keyconfig_requested) {
(new GUIKeyChangeMenu(guienv, guiroot, -1,
&g_menumgr))->drop();
&g_menumgr, texture_src))->drop();
g_gamecallback->keyconfig_requested = false;
}

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "client/tile.h" // ITextureSource
#include "debug.h"
#include "irrlichttypes_extrabloated.h"
#include "util/string.h"
#include <array>
@ -31,25 +32,34 @@ public:
{
TEXTCOLOR,
BGCOLOR,
BGCOLOR_HOVERED,
BGCOLOR_PRESSED,
BGCOLOR_HOVERED, // Note: Deprecated property
BGCOLOR_PRESSED, // Note: Deprecated property
NOCLIP,
BORDER,
BGIMG,
BGIMG_HOVERED,
BGIMG_HOVERED, // Note: Deprecated property
BGIMG_MIDDLE,
BGIMG_PRESSED,
BGIMG_PRESSED, // Note: Deprecated property
FGIMG,
FGIMG_HOVERED,
FGIMG_PRESSED,
FGIMG_HOVERED, // Note: Deprecated property
FGIMG_PRESSED, // Note: Deprecated property
ALPHA,
NUM_PROPERTIES,
NONE
};
enum State
{
STATE_DEFAULT = 0,
STATE_HOVERED = 1 << 0,
STATE_PRESSED = 1 << 1,
NUM_STATES = 1 << 2,
STATE_INVALID = 1 << 3,
};
private:
std::array<bool, NUM_PROPERTIES> property_set{};
std::array<std::string, NUM_PROPERTIES> properties;
State state_map = STATE_DEFAULT;
public:
static Property GetPropertyByName(const std::string &name)
@ -99,6 +109,49 @@ public:
property_set[prop] = true;
}
//! Parses a name and returns the corresponding state enum
static State getStateByName(const std::string &name)
{
if (name == "default") {
return STATE_DEFAULT;
} else if (name == "hovered") {
return STATE_HOVERED;
} else if (name == "pressed") {
return STATE_PRESSED;
} else {
return STATE_INVALID;
}
}
//! Gets the state that this style is intended for
State getState() const
{
return state_map;
}
//! Set the given state on this style
void addState(State state)
{
FATAL_ERROR_IF(state >= NUM_STATES, "Out-of-bounds state received");
state_map = static_cast<State>(state_map | state);
}
//! Using a list of styles mapped to state values, calculate the final
// combined style for a state by propagating values in its component states
static StyleSpec getStyleFromStatePropagation(const std::array<StyleSpec, NUM_STATES> &styles, State state)
{
StyleSpec temp = styles[StyleSpec::STATE_DEFAULT];
temp.state_map = state;
for (int i = StyleSpec::STATE_DEFAULT + 1; i <= state; i++) {
if ((state & i) != 0) {
temp = temp | styles[i];
}
}
return temp;
}
video::SColor getColor(Property prop, video::SColor def) const
{
const auto &val = properties[prop];

@ -14,6 +14,7 @@
#include "irrlicht_changes/static_text.h"
#include "porting.h"
#include "StyleSpec.h"
#include "util/numeric.h"
using namespace irr;
using namespace gui;
@ -26,14 +27,15 @@ using namespace gui;
//! constructor
GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool noclip)
s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc,
bool noclip)
: IGUIButton(environment, parent, id, rectangle),
SpriteBank(0), OverrideFont(0),
OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)),
ClickTime(0), HoverTime(0), FocusTime(0),
ClickShiftState(false), ClickControlState(false),
IsPushButton(false), Pressed(false),
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false), TSrc(tsrc)
{
setNotClipped(noclip);
@ -44,14 +46,6 @@ GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent,
// PATCH
for (size_t i = 0; i < 4; i++) {
Colors[i] = Environment->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);
HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(),
core::clamp<u32>(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255));
PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(),
core::clamp<u32>(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255));
}
StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id);
StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
@ -262,6 +256,13 @@ void GUIButton::draw()
return;
// PATCH
// Track hovered state, if it has changed then we need to update the style.
bool hovered = isHovered();
if (hovered != WasHovered) {
WasHovered = hovered;
setFromState();
}
GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());
video::IVideoDriver* driver = Environment->getVideoDriver();
// END PATCH
@ -271,21 +272,24 @@ void GUIButton::draw()
if (!Pressed)
{
// PATCH
skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect,
isHovered() ? HoveredColors : Colors);
skin->drawColored3DButtonPaneStandard(this, AbsoluteRect,
&AbsoluteClippingRect, Colors);
// END PATCH
}
else
{
// PATCH
skin->drawColored3DButtonPanePressed(this,
AbsoluteRect, &AbsoluteClippingRect, PressedColors);
skin->drawColored3DButtonPanePressed(this, AbsoluteRect,
&AbsoluteClippingRect, Colors);
// END PATCH
}
}
const core::position2di buttonCenter(AbsoluteRect.getCenter());
EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed);
// PATCH
// The image changes based on the state, so we use the default every time.
EGUI_BUTTON_IMAGE_STATE imageState = EGBIS_IMAGE_UP;
// END PATCH
if ( ButtonImages[(u32)imageState].Texture )
{
core::position2d<s32> pos(buttonCenter);
@ -548,18 +552,6 @@ void GUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& p
setImage(gui::EGBIS_IMAGE_DOWN, image, pos);
}
void GUIButton::setHoveredImage(video::ITexture* image)
{
setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image);
setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image);
}
void GUIButton::setHoveredImage(video::ITexture* image, const core::rect<s32>& pos)
{
setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos);
setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos);
}
//! Sets the text displayed by the button
void GUIButton::setText(const wchar_t* text)
{
@ -618,6 +610,8 @@ void GUIButton::setPressed(bool pressed)
skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));
}
}
setFromState();
}
}
@ -729,10 +723,12 @@ void GUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri
}
// PATCH
GUIButton* GUIButton::addButton(IGUIEnvironment *environment, const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)
GUIButton* GUIButton::addButton(IGUIEnvironment *environment,
const core::rect<s32>& rectangle, ISimpleTextureSource *tsrc,
IGUIElement* parent, s32 id, const wchar_t* text,
const wchar_t *tooltiptext)
{
GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle);
GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle, tsrc);
if (text)
button->setText(text);
@ -749,76 +745,87 @@ void GUIButton::setColor(video::SColor color)
for (size_t i = 0; i < 4; i++) {
video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
Colors[i] = base.getInterpolated(color, d);
HoveredColors[i] = irr::video::SColor(Colors[i].getAlpha(),
core::clamp<u32>(Colors[i].getRed() * COLOR_HOVERED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getGreen() * COLOR_HOVERED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getBlue() * COLOR_HOVERED_MOD, 0, 255));
PressedColors[i] = irr::video::SColor(Colors[i].getAlpha(),
core::clamp<u32>(Colors[i].getRed() * COLOR_PRESSED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255),
core::clamp<u32>(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255));
}
}
void GUIButton::setHoveredColor(video::SColor color)
{
float d = 0.65f;
for (size_t i = 0; i < 4; i++) {
video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
HoveredColors[i] = base.getInterpolated(color, d);
}
}
void GUIButton::setPressedColor(video::SColor color)
{
float d = 0.65f;
for (size_t i = 0; i < 4; i++) {
video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
PressedColors[i] = base.getInterpolated(color, d);
}
}
//! Set element properties from a StyleSpec
void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc)
//! Set element properties from a StyleSpec corresponding to the button state
void GUIButton::setFromState()
{
StyleSpec::State state = StyleSpec::STATE_DEFAULT;
if (isPressed())
state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_PRESSED);
if (isHovered())
state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_HOVERED);
setFromStyle(StyleSpec::getStyleFromStatePropagation(Styles, state));
}
//! Set element properties from a StyleSpec
void GUIButton::setFromStyle(const StyleSpec& style)
{
bool hovered = (style.getState() & StyleSpec::STATE_HOVERED) != 0;
bool pressed = (style.getState() & StyleSpec::STATE_PRESSED) != 0;
if (style.isNotDefault(StyleSpec::BGCOLOR)) {
setColor(style.getColor(StyleSpec::BGCOLOR));
}
if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) {
setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED));
}
if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) {
setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED));
// If we have a propagated hover/press color, we need to automatically
// lighten/darken it
if (!Styles[style.getState()].isNotDefault(StyleSpec::BGCOLOR)) {
for (size_t i = 0; i < 4; i++) {
if (pressed) {
Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD);
} else if (hovered) {
Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD);
}
}
}
} else {
for (size_t i = 0; i < 4; i++) {
video::SColor base =
Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
if (pressed) {
Colors[i] = multiplyColorValue(base, COLOR_PRESSED_MOD);
} else if (hovered) {
Colors[i] = multiplyColorValue(base, COLOR_HOVERED_MOD);
} else {
Colors[i] = base;
}
}
}
if (style.isNotDefault(StyleSpec::TEXTCOLOR)) {
setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));
} else {
setOverrideColor(video::SColor(255,255,255,255));
OverrideColorEnabled = false;
}
setNotClipped(style.getBool(StyleSpec::NOCLIP, isNotClipped()));
setDrawBorder(style.getBool(StyleSpec::BORDER, DrawBorder));
setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
setDrawBorder(style.getBool(StyleSpec::BORDER, true));
setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));
const core::position2di buttonCenter(AbsoluteRect.getCenter());
core::position2d<s32> geom(buttonCenter);
if (style.isNotDefault(StyleSpec::BGIMG)) {
video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, tsrc);
video::ITexture *texture = style.getTexture(StyleSpec::BGIMG,
getTextureSource());
setImage(guiScalingImageButton(
Environment->getVideoDriver(), texture, geom.X, geom.Y));
setScaleImage(true);
}
if (style.isNotDefault(StyleSpec::BGIMG_HOVERED)) {
video::ITexture *hovered_texture = style.getTexture(StyleSpec::BGIMG_HOVERED, tsrc);
setHoveredImage(guiScalingImageButton(
Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y));
setScaleImage(true);
}
if (style.isNotDefault(StyleSpec::BGIMG_PRESSED)) {
video::ITexture *pressed_texture = style.getTexture(StyleSpec::BGIMG_PRESSED, tsrc);
setPressedImage(guiScalingImageButton(
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
Environment->getVideoDriver(), texture, geom.X, geom.Y));
setScaleImage(true);
} else {
setImage(nullptr);
}
BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle);
}
//! Set the styles used for each state
void GUIButton::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles)
{
Styles = styles;
setFromState();
}
// END PATCH

@ -13,6 +13,7 @@
#include "ITexture.h"
#include "SColor.h"
#include "guiSkin.h"
#include "StyleSpec.h"
using namespace irr;
@ -67,7 +68,6 @@ using namespace irr;
#endif
class ISimpleTextureSource;
class StyleSpec;
class GUIButton : public gui::IGUIButton
{
@ -75,7 +75,8 @@ public:
//! constructor
GUIButton(gui::IGUIEnvironment* environment, gui::IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool noclip=false);
s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc,
bool noclip=false);
//! destructor
virtual ~GUIButton();
@ -125,16 +126,10 @@ public:
//! Sets an image which should be displayed on the button when it is in pressed state.
virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos) override;
//! Sets an image which should be displayed on the button when it is in hovered state.
virtual void setHoveredImage(video::ITexture* image=nullptr);
//! Sets the text displayed by the button
virtual void setText(const wchar_t* text) override;
// END PATCH
//! Sets an image which should be displayed on the button when it is in hovered state.
virtual void setHoveredImage(video::ITexture* image, const core::rect<s32>& pos);
//! Sets the sprite bank used by the button
virtual void setSpriteBank(gui::IGUISpriteBank* bank=0) override;
@ -225,22 +220,29 @@ public:
void setColor(video::SColor color);
// PATCH
void setHoveredColor(video::SColor color);
void setPressedColor(video::SColor color);
//! Set element properties from a StyleSpec corresponding to the button state
void setFromState();
//! Set element properties from a StyleSpec
virtual void setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc);
virtual void setFromStyle(const StyleSpec& style);
//! Set the styles used for each state
void setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles);
// END PATCH
//! Do not drop returned handle
static GUIButton* addButton(gui::IGUIEnvironment *environment, const core::rect<s32>& rectangle,
IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext=L"");
static GUIButton* addButton(gui::IGUIEnvironment *environment,
const core::rect<s32>& rectangle, ISimpleTextureSource *tsrc,
IGUIElement* parent, s32 id, const wchar_t* text,
const wchar_t *tooltiptext=L"");
protected:
void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center);
gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const;
ISimpleTextureSource *getTextureSource() { return TSrc; }
struct ButtonImage
{
ButtonImage() : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))
@ -308,6 +310,8 @@ private:
ButtonImage ButtonImages[gui::EGBIS_COUNT];
std::array<StyleSpec, StyleSpec::NUM_STATES> Styles;
gui::IGUIFont* OverrideFont;
bool OverrideColorEnabled;
@ -326,8 +330,8 @@ private:
video::SColor Colors[4];
// PATCH
video::SColor HoveredColors[4];
video::SColor PressedColors[4];
bool WasHovered = false;
ISimpleTextureSource *TSrc;
gui::IGUIStaticText *StaticText;

@ -30,8 +30,9 @@ using namespace irr;
using namespace gui;
GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment,
gui::IGUIElement *parent, s32 id, core::rect<s32> rectangle, bool noclip)
: GUIButton (environment, parent, id, rectangle, noclip)
gui::IGUIElement *parent, s32 id, core::rect<s32> rectangle,
ISimpleTextureSource *tsrc, bool noclip)
: GUIButton (environment, parent, id, rectangle, tsrc, noclip)
{
m_image = Environment->addImage(
core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), this);
@ -39,100 +40,38 @@ GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment,
sendToBack(m_image);
}
bool GUIButtonImage::OnEvent(const SEvent& event)
{
bool result = GUIButton::OnEvent(event);
EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images);
video::ITexture *texture = m_foreground_images[(u32)imageState].Texture;
if (texture != nullptr)
{
m_image->setImage(texture);
}
m_image->setVisible(texture != nullptr);
return result;
}
void GUIButtonImage::setForegroundImage(EGUI_BUTTON_IMAGE_STATE state,
video::ITexture *image, const core::rect<s32> &sourceRect)
{
if (state >= EGBIS_COUNT)
return;
if (image)
image->grab();
u32 stateIdx = (u32)state;
if (m_foreground_images[stateIdx].Texture)
m_foreground_images[stateIdx].Texture->drop();
m_foreground_images[stateIdx].Texture = image;
m_foreground_images[stateIdx].SourceRect = sourceRect;
EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images);
if (imageState == stateIdx)
m_image->setImage(image);
}
void GUIButtonImage::setForegroundImage(video::ITexture *image)
{
setForegroundImage(gui::EGBIS_IMAGE_UP, image);
if (image == m_foreground_image)
return;
if (image != nullptr)
image->grab();
if (m_foreground_image != nullptr)
m_foreground_image->drop();
m_foreground_image = image;
m_image->setImage(image);
}
void GUIButtonImage::setForegroundImage(video::ITexture *image, const core::rect<s32> &pos)
//! Set element properties from a StyleSpec
void GUIButtonImage::setFromStyle(const StyleSpec& style)
{
setForegroundImage(gui::EGBIS_IMAGE_UP, image, pos);
}
void GUIButtonImage::setPressedForegroundImage(video::ITexture *image)
{
setForegroundImage(gui::EGBIS_IMAGE_DOWN, image);
}
void GUIButtonImage::setPressedForegroundImage(video::ITexture *image, const core::rect<s32> &pos)
{
setForegroundImage(gui::EGBIS_IMAGE_DOWN, image, pos);
}
void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image)
{
setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image);
setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image);
}
void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image, const core::rect<s32> &pos)
{
setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos);
setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos);
}
void GUIButtonImage::setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc)
{
GUIButton::setFromStyle(style, tsrc);
GUIButton::setFromStyle(style);
video::IVideoDriver *driver = Environment->getVideoDriver();
const core::position2di buttonCenter(AbsoluteRect.getCenter());
core::position2d<s32> geom(buttonCenter);
if (style.isNotDefault(StyleSpec::FGIMG)) {
video::ITexture *texture = style.getTexture(StyleSpec::FGIMG, tsrc);
video::ITexture *texture = style.getTexture(StyleSpec::FGIMG,
getTextureSource());
setForegroundImage(guiScalingImageButton(driver, texture, geom.X, geom.Y));
setScaleImage(true);
}
if (style.isNotDefault(StyleSpec::FGIMG_HOVERED)) {
video::ITexture *hovered_texture = style.getTexture(StyleSpec::FGIMG_HOVERED, tsrc);
setHoveredForegroundImage(guiScalingImageButton(driver, hovered_texture, geom.X, geom.Y));
setScaleImage(true);
}
if (style.isNotDefault(StyleSpec::FGIMG_PRESSED)) {
video::ITexture *pressed_texture = style.getTexture(StyleSpec::FGIMG_PRESSED, tsrc);
setPressedForegroundImage(guiScalingImageButton(driver, pressed_texture, geom.X, geom.Y));
setScaleImage(true);
} else {
setForegroundImage(nullptr);
}
}
@ -143,11 +82,12 @@ void GUIButtonImage::setScaleImage(bool scaleImage)
}
GUIButtonImage *GUIButtonImage::addButton(IGUIEnvironment *environment,
const core::rect<s32> &rectangle, IGUIElement *parent, s32 id,
const wchar_t *text, const wchar_t *tooltiptext)
const core::rect<s32> &rectangle, ISimpleTextureSource *tsrc,
IGUIElement *parent, s32 id, const wchar_t *text,
const wchar_t *tooltiptext)
{
GUIButtonImage *button = new GUIButtonImage(environment,
parent ? parent : environment->getRootGUIElement(), id, rectangle);
parent ? parent : environment->getRootGUIElement(), id, rectangle, tsrc);
if (text)
button->setText(text);

@ -27,33 +27,23 @@ class GUIButtonImage : public GUIButton
public:
//! constructor
GUIButtonImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent,
s32 id, core::rect<s32> rectangle, bool noclip = false);
virtual bool OnEvent(const SEvent& event) override;
void setForegroundImage(gui::EGUI_BUTTON_IMAGE_STATE state,
video::ITexture *image = nullptr,
const core::rect<s32> &sourceRect = core::rect<s32>(0, 0, 0, 0));
s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc,
bool noclip = false);
void setForegroundImage(video::ITexture *image = nullptr);
void setForegroundImage(video::ITexture *image, const core::rect<s32> &pos);
void setPressedForegroundImage(video::ITexture *image = nullptr);
void setPressedForegroundImage(video::ITexture *image, const core::rect<s32> &pos);
void setHoveredForegroundImage(video::ITexture *image = nullptr);
void setHoveredForegroundImage(video::ITexture *image, const core::rect<s32> &pos);
virtual void setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc) override;
//! Set element properties from a StyleSpec
virtual void setFromStyle(const StyleSpec& style) override;
virtual void setScaleImage(bool scaleImage=true) override;
//! Do not drop returned handle
static GUIButtonImage *addButton(gui::IGUIEnvironment *environment,
const core::rect<s32> &rectangle, IGUIElement *parent, s32 id,
const wchar_t *text, const wchar_t *tooltiptext = L"");
const core::rect<s32> &rectangle, ISimpleTextureSource *tsrc,
IGUIElement *parent, s32 id, const wchar_t *text,
const wchar_t *tooltiptext = L"");
private:
ButtonImage m_foreground_images[gui::EGBIS_COUNT];
video::ITexture *m_foreground_image = nullptr;
gui::IGUIImage *m_image;
};

@ -28,9 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
using namespace irr;
using namespace gui;
GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent,
s32 id, core::rect<s32> rectangle, std::string item, Client *client, bool noclip)
: GUIButton (environment, parent, id, rectangle, noclip)
GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment,
gui::IGUIElement *parent, s32 id, core::rect<s32> rectangle,
ISimpleTextureSource *tsrc, std::string item, Client *client,
bool noclip)
: GUIButton (environment, parent, id, rectangle, tsrc, noclip)
{
m_image = new GUIItemImage(environment, this, id,
core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()),
@ -42,12 +44,13 @@ GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::I
}
GUIButtonItemImage *GUIButtonItemImage::addButton(IGUIEnvironment *environment,
const core::rect<s32> &rectangle, IGUIElement *parent, s32 id,
const wchar_t *text, std::string item, Client *client)
const core::rect<s32> &rectangle, ISimpleTextureSource *tsrc,
IGUIElement *parent, s32 id, const wchar_t *text, std::string item,
Client *client)
{
GUIButtonItemImage *button = new GUIButtonItemImage(environment,
parent ? parent : environment->getRootGUIElement(),
id, rectangle, item, client);
id, rectangle, tsrc, item, client);
if (text)
button->setText(text);

@ -30,13 +30,14 @@ class GUIButtonItemImage : public GUIButton
public:
//! constructor
GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent,
s32 id, core::rect<s32> rectangle, std::string item,
Client *client, bool noclip = false);
s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc,
std::string item, Client *client, bool noclip = false);
//! Do not drop returned handle
static GUIButtonItemImage *addButton(gui::IGUIEnvironment *environment,
const core::rect<s32> &rectangle, IGUIElement *parent, s32 id,
const wchar_t *text, std::string item, Client *client);
const core::rect<s32> &rectangle, ISimpleTextureSource *tsrc,
IGUIElement *parent, s32 id, const wchar_t *text, std::string item,
Client *client);
private:
std::string m_item_name;

@ -40,10 +40,10 @@ const int ID_message = 266;
GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env,
gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client,
const std::string &playername, const std::string &password,
bool *aborted) :
bool *aborted, ISimpleTextureSource *tsrc) :
GUIModalMenu(env, parent, id, menumgr),
m_client(client), m_playername(playername), m_password(password),
m_aborted(aborted)
m_aborted(aborted), m_tsrc(tsrc)
{
#ifdef __ANDROID__
m_touchscreen_visible = false;
@ -130,14 +130,14 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize)
core::rect<s32> rect2(0, 0, 230 * s, 35 * s);
rect2 = rect2 + v2s32(size.X / 2 - 220 * s, ypos);
text = wgettext("Register and Join");
GUIButton::addButton(Environment, rect2, this, ID_confirm, text);
GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_confirm, text);
delete[] text;
}
{
core::rect<s32> rect2(0, 0, 120 * s, 35 * s);
rect2 = rect2 + v2s32(size.X / 2 + 70 * s, ypos);
text = wgettext("Cancel");
GUIButton::addButton(Environment, rect2, this, ID_cancel, text);
GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_cancel, text);
delete[] text;
}
{

@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
class Client;
class ISimpleTextureSource;
class GUIConfirmRegistration : public GUIModalMenu
{
@ -32,7 +33,7 @@ public:
GUIConfirmRegistration(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
s32 id, IMenuManager *menumgr, Client *client,
const std::string &playername, const std::string &password,
bool *aborted);
bool *aborted, ISimpleTextureSource *tsrc);
~GUIConfirmRegistration();
void removeChildren();
@ -63,4 +64,5 @@ private:
const std::string &m_password;
bool *m_aborted = nullptr;
std::wstring m_pass_confirm = L"";
ISimpleTextureSource *m_tsrc;
};

@ -553,7 +553,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element
gui::IGUICheckBox *e = Environment->addCheckBox(fselected, rect, this,
spec.fid, spec.flabel.c_str());
auto style = getStyleForElement("checkbox", name);
auto style = getDefaultStyleForElement("checkbox", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
if (spec.fname == data->focused_fieldname) {
@ -613,7 +613,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
GUIScrollBar *e = new GUIScrollBar(Environment, this, spec.fid, rect,
is_horizontal, true);
auto style = getStyleForElement("scrollbar", name);
auto style = getDefaultStyleForElement("scrollbar", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->setArrowsVisible(data->scrollbar_options.arrow_visiblity);
@ -740,7 +740,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
gui::IGUIImage *e = Environment->addImage(rect, this, spec.fid, 0, true);
e->setImage(texture);
e->setScaleImage(true);
auto style = getStyleForElement("image", spec.fname);
auto style = getDefaultStyleForElement("image", spec.fname);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3));
m_fields.push_back(spec);
@ -776,7 +776,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
);
gui::IGUIImage *e = Environment->addImage(texture, pos, true, this,
spec.fid, 0);
auto style = getStyleForElement("image", spec.fname);
auto style = getDefaultStyleForElement("image", spec.fname);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3));
m_fields.push_back(spec);
@ -841,7 +841,7 @@ void GUIFormSpecMenu::parseAnimatedImage(parserData *data, const std::string &el
if (parts.size() >= 7)
e->setFrameIndex(stoi(parts[6]) - 1);
auto style = getStyleForElement("animated_image", spec.fname, "image");
auto style = getDefaultStyleForElement("animated_image", spec.fname, "image");
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->drop();
@ -888,7 +888,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen
GUIItemImage *e = new GUIItemImage(Environment, this, spec.fid,
core::rect<s32>(pos, pos + geom), name, m_font, m_client);
auto style = getStyleForElement("item_image", spec.fname);
auto style = getDefaultStyleForElement("item_image", spec.fname);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
// item images should let events through
@ -949,10 +949,11 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
if(type == "button_exit")
spec.is_exit = true;
GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str());
GUIButton *e = GUIButton::addButton(Environment, rect, m_tsrc, this,
spec.fid, spec.flabel.c_str());
auto style = getStyleForElement(type, name, (type != "button") ? "button" : "");
e->setFromStyle(style, m_tsrc);
e->setStyles(style);
if (spec.fname == data->focused_fieldname) {
Environment->setFocus(e);
@ -1155,7 +1156,7 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
if (!str_initial_selection.empty() && str_initial_selection != "0")
e->setSelected(stoi(str_initial_selection));
auto style = getStyleForElement("table", name);
auto style = getDefaultStyleForElement("table", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
m_tables.emplace_back(spec, e);
@ -1231,7 +1232,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
if (!str_initial_selection.empty() && str_initial_selection != "0")
e->setSelected(stoi(str_initial_selection));
auto style = getStyleForElement("textlist", name);
auto style = getDefaultStyleForElement("textlist", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
m_tables.emplace_back(spec, e);
@ -1306,7 +1307,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element
if (!str_initial_selection.empty())
e->setSelected(stoi(str_initial_selection)-1);
auto style = getStyleForElement("dropdown", name);
auto style = getDefaultStyleForElement("dropdown", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
m_fields.push_back(spec);
@ -1394,7 +1395,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
e->setPasswordBox(true,L'*');
auto style = getStyleForElement("pwdfield", name, "field");
auto style = getDefaultStyleForElement("pwdfield", name, "field");
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
@ -1454,7 +1455,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,
}
}
auto style = getStyleForElement(is_multiline ? "textarea" : "field", spec.fname);
auto style = getDefaultStyleForElement(is_multiline ? "textarea" : "field", spec.fname);
if (e) {
if (is_editable && spec.fname == data->focused_fieldname)
@ -1752,7 +1753,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
spec.flabel.c_str(), rect, false, false, this, spec.fid);
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
auto style = getStyleForElement("label", spec.fname);
auto style = getDefaultStyleForElement("label", spec.fname);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
@ -1832,7 +1833,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen
rect, false, false, this, spec.fid);
e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
auto style = getStyleForElement("vertlabel", spec.fname, "label");
auto style = getDefaultStyleForElement("vertlabel", spec.fname, "label");
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
@ -1863,17 +1864,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
MY_CHECKPOS("imagebutton",0);
MY_CHECKGEOM("imagebutton",1);
bool noclip = false;
bool drawborder = true;
std::string pressed_image_name;
if (parts.size() >= 7) {
if (parts[5] == "true")
noclip = true;
if (parts[6] == "false")
drawborder = false;
}
if (parts.size() >= 8) {
pressed_image_name = parts[7];
}
@ -1911,35 +1903,30 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
if (type == "image_button_exit")
spec.is_exit = true;
GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str());
GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, m_tsrc,
this, spec.fid, spec.flabel.c_str());
if (spec.fname == data->focused_fieldname) {
Environment->setFocus(e);
}
auto style = getStyleForElement("image_button", spec.fname);
e->setFromStyle(style, m_tsrc);
// We explicitly handle these arguments *after* the style properties in
// order to override them if they are provided
// Override style properties with values specified directly in the element
if (!image_name.empty())
{
video::ITexture *texture = m_tsrc->getTexture(image_name);
e->setForegroundImage(guiScalingImageButton(
Environment->getVideoDriver(), texture, geom.X, geom.Y));
}
if (!pressed_image_name.empty()) {
video::ITexture *pressed_texture = m_tsrc->getTexture(pressed_image_name);
e->setPressedForegroundImage(guiScalingImageButton(
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
}
e->setScaleImage(true);
style[StyleSpec::STATE_DEFAULT].set(StyleSpec::FGIMG, image_name);
if (!pressed_image_name.empty())
style[StyleSpec::STATE_PRESSED].set(StyleSpec::FGIMG, pressed_image_name);
if (parts.size() >= 7) {
e->setNotClipped(noclip);
e->setDrawBorder(drawborder);
style[StyleSpec::STATE_DEFAULT].set(StyleSpec::NOCLIP, parts[5]);
style[StyleSpec::STATE_DEFAULT].set(StyleSpec::BORDER, parts[6]);
}
e->setStyles(style);
e->setScaleImage(true);
m_fields.push_back(spec);
return;
}
@ -2033,7 +2020,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
Environment->setFocus(e);
}
auto style = getStyleForElement("tabheader", name);
auto style = getDefaultStyleForElement("tabheader", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, true));
for (const std::string &button : buttons) {
@ -2118,10 +2105,12 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
2
);
GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment, rect, this, spec_btn.fid, spec_btn.flabel.c_str(), item_name, m_client);
GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment,
rect, m_tsrc, this, spec_btn.fid, spec_btn.flabel.c_str(),
item_name, m_client);
auto style = getStyleForElement("item_image_button", spec_btn.fname, "image_button");
e_btn->setFromStyle(style, m_tsrc);
e_btn->setStyles(style);
if (spec_btn.fname == data->focused_fieldname) {
Environment->setFocus(e_btn);
@ -2177,7 +2166,7 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element)
GUIBox *e = new GUIBox(Environment, this, spec.fid, rect, tmp_color);
auto style = getStyleForElement("box", spec.fname);
auto style = getDefaultStyleForElement("box", spec.fname);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3));
e->drop();
@ -2469,6 +2458,7 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
StyleSpec spec;
// Parse properties
for (size_t i = 1; i < parts.size(); i++) {
size_t equal_pos = parts[i].find('=');
if (equal_pos == std::string::npos) {
@ -2500,16 +2490,92 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
for (size_t sel = 0; sel < selectors.size(); sel++) {
std::string selector = trim(selectors[sel]);
if (selector.empty()) {
errorstream << "Invalid style element (Empty selector): '" << element
<< "'" << std::endl;
// Copy the style properties to a new StyleSpec
// This allows a separate state mask per-selector
StyleSpec selector_spec = spec;
// Parse state information, if it exists
bool state_valid = true;
size_t state_pos = selector.find(':');
if (state_pos != std::string::npos) {
std::string state_str = selector.substr(state_pos + 1);
selector = selector.substr(0, state_pos);
if (state_str.empty()) {
errorstream << "Invalid style element (Invalid state): '" << element
<< "'" << std::endl;
state_valid = false;
} else {
std::vector<std::string> states = split(state_str, '+');
for (std::string &state : states) {
StyleSpec::State converted = StyleSpec::getStateByName(state);
if (converted == StyleSpec::STATE_INVALID) {
infostream << "Unknown style state " << state <<
" in element '" << element << "'" << std::endl;
state_valid = false;
break;
}
selector_spec.addState(converted);
}
}
}
if(!state_valid) {
// Skip this selector
continue;
}
if (style_type) {
theme_by_type[selector] |= spec;
theme_by_type[selector].push_back(selector_spec);
} else {
theme_by_name[selector] |= spec;
theme_by_name[selector].push_back(selector_spec);
}
// Backwards-compatibility for existing _hovered/_pressed properties
if (selector_spec.hasProperty(StyleSpec::BGCOLOR_HOVERED)
|| selector_spec.hasProperty(StyleSpec::BGIMG_HOVERED)
|| selector_spec.hasProperty(StyleSpec::FGIMG_HOVERED)) {
StyleSpec hover_spec;
hover_spec.addState(StyleSpec::STATE_HOVERED);
if (selector_spec.hasProperty(StyleSpec::BGCOLOR_HOVERED)) {
hover_spec.set(StyleSpec::BGCOLOR, selector_spec.get(StyleSpec::BGCOLOR_HOVERED, ""));
}
if (selector_spec.hasProperty(StyleSpec::BGIMG_HOVERED)) {
hover_spec.set(StyleSpec::BGIMG, selector_spec.get(StyleSpec::BGIMG_HOVERED, ""));
}
if (selector_spec.hasProperty(StyleSpec::FGIMG_HOVERED)) {
hover_spec.set(StyleSpec::FGIMG, selector_spec.get(StyleSpec::FGIMG_HOVERED, ""));
}
if (style_type) {
theme_by_type[selector].push_back(hover_spec);
} else {
theme_by_name[selector].push_back(hover_spec);
}
}
if (selector_spec.hasProperty(StyleSpec::BGCOLOR_PRESSED)
|| selector_spec.hasProperty(StyleSpec::BGIMG_PRESSED)
|| selector_spec.hasProperty(StyleSpec::FGIMG_PRESSED)) {
StyleSpec press_spec;
press_spec.addState(StyleSpec::STATE_PRESSED);
if (selector_spec.hasProperty(StyleSpec::BGCOLOR_PRESSED)) {
press_spec.set(StyleSpec::BGCOLOR, selector_spec.get(StyleSpec::BGCOLOR_PRESSED, ""));
}
if (selector_spec.hasProperty(StyleSpec::BGIMG_PRESSED)) {
press_spec.set(StyleSpec::BGIMG, selector_spec.get(StyleSpec::BGIMG_PRESSED, ""));
}
if (selector_spec.hasProperty(StyleSpec::FGIMG_PRESSED)) {
press_spec.set(StyleSpec::FGIMG, selector_spec.get(StyleSpec::FGIMG_PRESSED, ""));
}
if (style_type) {
theme_by_type[selector].push_back(press_spec);
} else {
theme_by_name[selector].push_back(press_spec);
}
}
}
@ -3080,7 +3146,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
size.X / 2 - 70 + 140, pos.Y + m_btn_height * 2
);
const wchar_t *text = wgettext("Proceed");
GUIButton::addButton(Environment, mydata.rect, this, 257, text);
GUIButton::addButton(Environment, mydata.rect, m_tsrc, this, 257, text);
delete[] text;
}
}
@ -4432,25 +4498,34 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id)
return L"";
}
StyleSpec GUIFormSpecMenu::getStyleForElement(const std::string &type,
StyleSpec GUIFormSpecMenu::getDefaultStyleForElement(const std::string &type,
const std::string &name, const std::string &parent_type) {
StyleSpec ret;
return getStyleForElement(type, name, parent_type)[StyleSpec::STATE_DEFAULT];
}
std::array<StyleSpec, StyleSpec::NUM_STATES> GUIFormSpecMenu::getStyleForElement(const std::string &type,
const std::string &name, const std::string &parent_type)
{
std::array<StyleSpec, StyleSpec::NUM_STATES> ret;
if (!parent_type.empty()) {
auto it = theme_by_type.find(parent_type);
if (it != theme_by_type.end()) {
ret |= it->second;
for (const StyleSpec &spec : it->second)
ret[(u32)spec.getState()] |= spec;
}
}
auto it = theme_by_type.find(type);
if (it != theme_by_type.end()) {
ret |= it->second;
for (const StyleSpec &spec : it->second)
ret[(u32)spec.getState()] |= spec;
}
it = theme_by_name.find(name);
if (it != theme_by_name.end()) {
ret |= it->second;
for (const StyleSpec &spec : it->second)
ret[(u32)spec.getState()] |= spec;
}
return ret;

@ -274,11 +274,13 @@ protected:
v2s32 getRealCoordinateBasePos(const std::vector<std::string> &v_pos);
v2s32 getRealCoordinateGeometry(const std::vector<std::string> &v_geom);
std::unordered_map<std::string, StyleSpec> theme_by_type;
std::unordered_map<std::string, StyleSpec> theme_by_name;
std::unordered_map<std::string, std::vector<StyleSpec>> theme_by_type;
std::unordered_map<std::string, std::vector<StyleSpec>> theme_by_name;
std::unordered_set<std::string> property_warned;
StyleSpec getStyleForElement(const std::string &type,
StyleSpec getDefaultStyleForElement(const std::string &type,
const std::string &name="", const std::string &parent_type="");
std::array<StyleSpec, StyleSpec::NUM_STATES> getStyleForElement(const std::string &type,
const std::string &name="", const std::string &parent_type="");
v2s32 padding;

@ -82,8 +82,10 @@ enum
};
GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
GUIModalMenu(env, parent, id, menumgr)
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
ISimpleTextureSource *tsrc) :
GUIModalMenu(env, parent, id, menumgr),
m_tsrc(tsrc)
{
init_keys();
}
@ -157,7 +159,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 100 * s, 30 * s);
rect += topleft + v2s32(offset.X + 150 * s, offset.Y - 5 * s);
const wchar_t *text = wgettext(k->key.name());
k->button = GUIButton::addButton(Environment, rect, this, k->id, text);
k->button = GUIButton::addButton(Environment, rect, m_tsrc, this, k->id, text);
delete[] text;
}
if ((i + 1) % KMaxButtonPerColumns == 0) {
@ -217,14 +219,14 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 100 * s, 30 * s);
rect += topleft + v2s32(size.X / 2 - 105 * s, size.Y - 40 * s);
const wchar_t *text = wgettext("Save");
GUIButton::addButton(Environment, rect, this, GUI_ID_BACK_BUTTON, text);
GUIButton::addButton(Environment, rect, m_tsrc, this, GUI_ID_BACK_BUTTON, text);
delete[] text;
}
{
core::rect<s32> rect(0, 0, 100 * s, 30 * s);
rect += topleft + v2s32(size.X / 2 + 5 * s, size.Y - 40 * s);
const wchar_t *text = wgettext("Cancel");
GUIButton::addButton(Environment, rect, this, GUI_ID_ABORT_BUTTON, text);
GUIButton::addButton(Environment, rect, m_tsrc, this, GUI_ID_ABORT_BUTTON, text);
delete[] text;
}
}

@ -28,6 +28,8 @@
#include <string>
#include <vector>
class ISimpleTextureSource;
struct key_setting
{
int id;
@ -41,7 +43,7 @@ class GUIKeyChangeMenu : public GUIModalMenu
{
public:
GUIKeyChangeMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
IMenuManager *menumgr);
IMenuManager *menumgr, ISimpleTextureSource *tsrc);
~GUIKeyChangeMenu();
void removeChildren();
@ -74,4 +76,5 @@ private:
key_setting *active_key = nullptr;
gui::IGUIStaticText *key_used_text = nullptr;
std::vector<key_setting *> key_settings;
ISimpleTextureSource *m_tsrc;
};

@ -38,10 +38,12 @@ const int ID_cancel = 261;
GUIPasswordChange::GUIPasswordChange(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
Client* client
Client* client,
ISimpleTextureSource *tsrc
):
GUIModalMenu(env, parent, id, menumgr),
m_client(client)
m_client(client),
m_tsrc(tsrc)
{
}
@ -146,14 +148,14 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 100 * s, 30 * s);
rect = rect + v2s32(size.X / 4 + 56 * s, ypos);
text = wgettext("Change");
GUIButton::addButton(Environment, rect, this, ID_change, text);
GUIButton::addButton(Environment, rect, m_tsrc, this, ID_change, text);
delete[] text;
}
{
core::rect<s32> rect(0, 0, 100 * s, 30 * s);
rect = rect + v2s32(size.X / 4 + 185 * s, ypos);
text = wgettext("Cancel");
GUIButton::addButton(Environment, rect, this, ID_cancel, text);
GUIButton::addButton(Environment, rect, m_tsrc, this, ID_cancel, text);
delete[] text;
}

@ -23,12 +23,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <string>
class Client;
class ISimpleTextureSource;
class GUIPasswordChange : public GUIModalMenu
{
public:
GUIPasswordChange(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
IMenuManager *menumgr, Client *client);
IMenuManager *menumgr, Client *client,
ISimpleTextureSource *tsrc);
~GUIPasswordChange();
void removeChildren();
@ -57,4 +59,5 @@ private:
std::wstring m_oldpass = L"";
std::wstring m_newpass = L"";
std::wstring m_newpass_confirm = L"";
ISimpleTextureSource *m_tsrc;
};

@ -38,9 +38,10 @@ const int ID_soundMuteButton = 266;
GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr
IMenuManager *menumgr, ISimpleTextureSource *tsrc
):
GUIModalMenu(env, parent, id, menumgr)
GUIModalMenu(env, parent, id, menumgr),
m_tsrc(tsrc)
{
}
@ -104,7 +105,7 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 80 * s, 30 * s);
rect = rect + v2s32(size.X / 2 - 80 * s / 2, size.Y / 2 + 55 * s);
const wchar_t *text = wgettext("Exit");
GUIButton::addButton(Environment, rect, this, ID_soundExitButton, text);
GUIButton::addButton(Environment, rect, m_tsrc, this, ID_soundExitButton, text);
delete[] text;
}
{

@ -23,12 +23,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "modalMenu.h"
#include <string>
class ISimpleTextureSource;
class GUIVolumeChange : public GUIModalMenu
{
public:
GUIVolumeChange(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr);
IMenuManager *menumgr, ISimpleTextureSource *tsrc);
~GUIVolumeChange();
void removeChildren();
@ -46,4 +48,7 @@ public:
protected:
std::wstring getLabelByID(s32 id) { return L""; }
std::string getNameByID(s32 id) { return ""; }
private:
ISimpleTextureSource *m_tsrc;
};

@ -571,9 +571,10 @@ int ModApiMainMenu::l_show_keys_menu(lua_State *L)
sanity_check(engine != NULL);
GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(RenderingEngine::get_gui_env(),
engine->m_parent,
-1,
engine->m_menumanager);
engine->m_parent,
-1,
engine->m_menumanager,
engine->m_texture_source);
kmenu->drop();
return 0;
}
@ -904,12 +905,12 @@ int ModApiMainMenu::l_show_path_select_dialog(lua_State *L)
GUIFileSelectMenu* fileOpenMenu =
new GUIFileSelectMenu(RenderingEngine::get_gui_env(),
engine->m_parent,
-1,
engine->m_menumanager,
title,
formname,
is_file_select);
engine->m_parent,
-1,
engine->m_menumanager,
title,
formname,
is_file_select);
fileOpenMenu->setTextDest(engine->m_buttonhandler);
fileOpenMenu->drop();
return 0;

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irr_v2d.h"
#include "irr_v3d.h"
#include "irr_aabb3d.h"
#include "SColor.h"
#include <matrix4.h>
#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d) > (max) ? (max) : (d)))
@ -432,3 +433,12 @@ inline v3f getPitchYawRoll(const core::matrix4 &m)
{
return getPitchYawRollRad(m) * core::RADTODEG64;
}
// Muliply the RGB value of a color linearly, and clamp to black/white
inline irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod)
{
return irr::video::SColor(color.getAlpha(),
core::clamp<u32>(color.getRed() * mod, 0, 255),
core::clamp<u32>(color.getGreen() * mod, 0, 255),
core::clamp<u32>(color.getBlue() * mod, 0, 255));
}