163 changes: 85 additions & 78 deletions src/gui/guiButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -618,6 +610,8 @@ void GUIButton::setPressed(bool pressed)
skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));
}
}

setFromState();
}
}

Expand Down Expand Up @@ -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);

Expand All @@ -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)

//! Set element properties from a StyleSpec corresponding to the button state
void GUIButton::setFromState()
{
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);
}
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, ISimpleTextureSource *tsrc)
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
34 changes: 19 additions & 15 deletions src/gui/guiButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ITexture.h"
#include "SColor.h"
#include "guiSkin.h"
#include "StyleSpec.h"

using namespace irr;

Expand Down Expand Up @@ -67,15 +68,15 @@ using namespace irr;
#endif

class ISimpleTextureSource;
class StyleSpec;

class GUIButton : public gui::IGUIButton
{
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();
Expand Down Expand Up @@ -125,16 +126,10 @@ class GUIButton : public gui::IGUIButton
//! 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;

Expand Down Expand Up @@ -225,22 +220,29 @@ class GUIButton : public gui::IGUIButton

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))
Expand Down Expand Up @@ -308,6 +310,8 @@ class GUIButton : public gui::IGUIButton

ButtonImage ButtonImages[gui::EGBIS_COUNT];

std::array<StyleSpec, StyleSpec::NUM_STATES> Styles;

gui::IGUIFont* OverrideFont;

bool OverrideColorEnabled;
Expand All @@ -326,8 +330,8 @@ class GUIButton : public gui::IGUIButton

video::SColor Colors[4];
// PATCH
video::SColor HoveredColors[4];
video::SColor PressedColors[4];
bool WasHovered = false;
ISimpleTextureSource *TSrc;

gui::IGUIStaticText *StaticText;

Expand Down
102 changes: 21 additions & 81 deletions src/gui/guiButtonImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,109 +30,48 @@ 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);
m_image->setScaleImage(isScalingImage());
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)
void GUIButtonImage::setForegroundImage(video::ITexture *image)
{
if (state >= EGBIS_COUNT)
if (image == m_foreground_image)
return;

if (image)
if (image != nullptr)
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);
}

void GUIButtonImage::setForegroundImage(video::ITexture *image, const core::rect<s32> &pos)
{
setForegroundImage(gui::EGBIS_IMAGE_UP, image, pos);
}

void GUIButtonImage::setPressedForegroundImage(video::ITexture *image)
{
setForegroundImage(gui::EGBIS_IMAGE_DOWN, image);
}
if (m_foreground_image != nullptr)
m_foreground_image->drop();

void GUIButtonImage::setPressedForegroundImage(video::ITexture *image, const core::rect<s32> &pos)
{
setForegroundImage(gui::EGBIS_IMAGE_DOWN, image, pos);
m_foreground_image = image;
m_image->setImage(image);
}

void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image)
//! Set element properties from a StyleSpec
void GUIButtonImage::setFromStyle(const StyleSpec& style)
{
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);
}
}

Expand All @@ -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);
Expand Down
26 changes: 8 additions & 18 deletions src/gui/guiButtonImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
15 changes: 9 additions & 6 deletions src/gui/guiButtonItemImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand All @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions src/gui/guiButtonItemImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/gui/guiConfirmRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
{
Expand Down
4 changes: 3 additions & 1 deletion src/gui/guiConfirmRegistration.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>

class Client;
class ISimpleTextureSource;

class GUIConfirmRegistration : public GUIModalMenu
{
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();
Expand Down Expand Up @@ -63,4 +64,5 @@ class GUIConfirmRegistration : public GUIModalMenu
const std::string &m_password;
bool *m_aborted = nullptr;
std::wstring m_pass_confirm = L"";
ISimpleTextureSource *m_tsrc;
};
187 changes: 131 additions & 56 deletions src/gui/guiFormSpecMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)));
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)));

Expand Down Expand Up @@ -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)));

Expand Down Expand Up @@ -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];
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions src/gui/guiFormSpecMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,13 @@ class GUIFormSpecMenu : public GUIModalMenu
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;
Expand Down
12 changes: 7 additions & 5 deletions src/gui/guiKeyChangeMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/gui/guiKeyChangeMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <string>
#include <vector>

class ISimpleTextureSource;

struct key_setting
{
int id;
Expand All @@ -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();
Expand Down Expand Up @@ -74,4 +76,5 @@ class GUIKeyChangeMenu : public GUIModalMenu
key_setting *active_key = nullptr;
gui::IGUIStaticText *key_used_text = nullptr;
std::vector<key_setting *> key_settings;
ISimpleTextureSource *m_tsrc;
};
10 changes: 6 additions & 4 deletions src/gui/guiPasswordChange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}

Expand Down Expand Up @@ -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;
}

Expand Down
5 changes: 4 additions & 1 deletion src/gui/guiPasswordChange.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -57,4 +59,5 @@ class GUIPasswordChange : public GUIModalMenu
std::wstring m_oldpass = L"";
std::wstring m_newpass = L"";
std::wstring m_newpass_confirm = L"";
ISimpleTextureSource *m_tsrc;
};
7 changes: 4 additions & 3 deletions src/gui/guiVolumeChange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}

Expand Down Expand Up @@ -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;
}
{
Expand Down
7 changes: 6 additions & 1 deletion src/gui/guiVolumeChange.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -46,4 +48,7 @@ class GUIVolumeChange : public GUIModalMenu
protected:
std::wstring getLabelByID(s32 id) { return L""; }
std::string getNameByID(s32 id) { return ""; }

private:
ISimpleTextureSource *m_tsrc;
};
19 changes: 10 additions & 9 deletions src/script/lua_api/l_mainmenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions src/util/numeric.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down Expand Up @@ -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));
}