diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/renderingengine.cpp | 16 | ||||
-rw-r--r-- | src/gui/StyleSpec.h | 93 | ||||
-rw-r--r-- | src/gui/guiFormSpecMenu.cpp | 158 | ||||
-rw-r--r-- | src/gui/guiFormSpecMenu.h | 6 |
4 files changed, 203 insertions, 70 deletions
diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index e56367afe..631616c06 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -55,17 +55,17 @@ with this program; if not, write to the Free Software Foundation, Inc., RenderingEngine *RenderingEngine::s_singleton = nullptr; -static gui::GUISkin* createSkin(gui::IGUIEnvironment *environment, - gui::EGUI_SKIN_TYPE type, video::IVideoDriver *driver) +static gui::GUISkin *createSkin(gui::IGUIEnvironment *environment, + gui::EGUI_SKIN_TYPE type, video::IVideoDriver *driver) { - gui::GUISkin* skin = new gui::GUISkin(type, driver); + gui::GUISkin *skin = new gui::GUISkin(type, driver); - gui::IGUIFont* builtinfont = environment->getBuiltInFont(); - gui::IGUIFontBitmap* bitfont = 0; + gui::IGUIFont *builtinfont = environment->getBuiltInFont(); + gui::IGUIFontBitmap *bitfont = nullptr; if (builtinfont && builtinfont->getType() == gui::EGFT_BITMAP) bitfont = (gui::IGUIFontBitmap*)builtinfont; - gui::IGUISpriteBank* bank = 0; + gui::IGUISpriteBank *bank = 0; skin->setFont(builtinfont); if (bitfont) @@ -102,7 +102,7 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) u32 i; for (i = 0; i != drivers.size(); i++) { if (!strcasecmp(driverstring.c_str(), - RenderingEngine::getVideoDriverName(drivers[i]))) { + RenderingEngine::getVideoDriverName(drivers[i]))) { driverType = drivers[i]; break; } @@ -139,7 +139,7 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) s_singleton = this; auto skin = createSkin(m_device->getGUIEnvironment(), - gui::EGST_WINDOWS_METALLIC, driver); + gui::EGST_WINDOWS_METALLIC, driver); m_device->getGUIEnvironment()->setSkin(skin); skin->drop(); } diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index f81727e93..29aae0836 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -18,85 +18,118 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "irrlichttypes_extrabloated.h" +#include <array> #pragma once - class StyleSpec { public: - enum Property { - NONE = 0, + enum Property + { TEXTCOLOR, BGCOLOR, - NUM_PROPERTIES + NOCLIP, + BORDER, + BGIMG, + BGIMG_PRESSED, + ALPHA, + NUM_PROPERTIES, + NONE }; private: - std::unordered_map<Property, std::string> properties; + std::array<bool, NUM_PROPERTIES> property_set; + std::array<std::string, NUM_PROPERTIES> properties; public: - static Property GetPropertyByName(const std::string &name) { + static Property GetPropertyByName(const std::string &name) + { if (name == "textcolor") { return TEXTCOLOR; } else if (name == "bgcolor") { return BGCOLOR; + } else if (name == "noclip") { + return NOCLIP; + } else if (name == "border") { + return BORDER; + } else if (name == "bgimg") { + return BGIMG; + } else if (name == "bgimg_pressed") { + return BGIMG_PRESSED; + } else if (name == "alpha") { + return ALPHA; } else { return NONE; } } - std::string get(Property prop, std::string def) const { - auto it = properties.find(prop); - if (it == properties.end()) { - return def; - } - - return it->second; + std::string get(Property prop, std::string def) const + { + const auto &val = properties[prop]; + return val.empty() ? def : val; } - void set(Property prop, std::string value) { - properties[prop] = std::move(value); + void set(Property prop, const std::string &value) + { + properties[prop] = value; + property_set[prop] = true; } - video::SColor getColor(Property prop, video::SColor def) const { - auto it = properties.find(prop); - if (it == properties.end()) { + video::SColor getColor(Property prop, video::SColor def) const + { + const auto &val = properties[prop]; + if (val.empty()) { return def; } - parseColorString(it->second, def, false, 0xFF); + parseColorString(val, def, false, 0xFF); return def; } - video::SColor getColor(Property prop) const { - auto it = properties.find(prop); - FATAL_ERROR_IF(it == properties.end(), "Unexpected missing property"); + video::SColor getColor(Property prop) const + { + const auto &val = properties[prop]; + FATAL_ERROR_IF(val.empty(), "Unexpected missing property"); video::SColor color; - parseColorString(it->second, color, false, 0xFF); + parseColorString(val, color, false, 0xFF); return color; } - bool hasProperty(Property prop) const { - return properties.find(prop) != properties.end(); + bool getBool(Property prop, bool def) const + { + const auto &val = properties[prop]; + if (val.empty()) { + return def; + } + + return is_yes(val); + } + + inline bool isNotDefault(Property prop) const + { + return !properties[prop].empty(); } - StyleSpec &operator|=(const StyleSpec &other) { - for (size_t i = 1; i < NUM_PROPERTIES; i++) { + inline bool hasProperty(Property prop) const { return property_set[prop]; } + + StyleSpec &operator|=(const StyleSpec &other) + { + for (size_t i = 0; i < NUM_PROPERTIES; i++) { auto prop = (Property)i; if (other.hasProperty(prop)) { - properties[prop] = other.get(prop, ""); + set(prop, other.get(prop, "")); } } return *this; } - StyleSpec operator|(const StyleSpec &other) const { + StyleSpec operator|(const StyleSpec &other) const + { StyleSpec newspec = *this; newspec |= other; return newspec; } }; - diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 3bb654972..c9ae76750 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -500,6 +500,9 @@ 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); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } @@ -556,6 +559,9 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen gui::IGUIScrollBar* e = Environment->addScrollBar(is_horizontal,rect,this,spec.fid); + auto style = getStyleForElement("scrollbar", name); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setMax(1000); e->setMin(0); e->setPos(stoi(parts[4])); @@ -702,15 +708,35 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); - auto style = getThemeForElement(type, name); - if (style.hasProperty(StyleSpec::BGCOLOR)) { + auto style = getStyleForElement(type, name, (type != "button") ? "button" : ""); + if (style.isNotDefault(StyleSpec::BGCOLOR)) { e->setColor(style.getColor(StyleSpec::BGCOLOR)); } - if (style.hasProperty(StyleSpec::TEXTCOLOR)) { + if (style.isNotDefault(StyleSpec::TEXTCOLOR)) { e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR)); } - -// e->setSprite(); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); + + if (style.isNotDefault(StyleSpec::BGIMG)) { + std::string image_name = style.get(StyleSpec::BGIMG, ""); + std::string pressed_image_name = style.get(StyleSpec::BGIMG_PRESSED, ""); + + video::ITexture *texture = 0; + video::ITexture *pressed_texture = 0; + texture = m_tsrc->getTexture(image_name); + if (!pressed_image_name.empty()) + pressed_texture = m_tsrc->getTexture(pressed_image_name); + else + pressed_texture = texture; + + e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); + e->setImage(guiScalingImageButton( + Environment->getVideoDriver(), texture, geom.X, geom.Y)); + e->setPressedImage(guiScalingImageButton( + Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); + e->setScaleImage(true); + } if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -889,6 +915,9 @@ 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); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + m_tables.emplace_back(spec, e); m_fields.push_back(spec); return; @@ -963,6 +992,9 @@ 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); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + m_tables.emplace_back(spec, e); m_fields.push_back(spec); return; @@ -1035,6 +1067,9 @@ 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); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + m_fields.push_back(spec); m_dropdowns.emplace_back(spec, std::vector<std::string>()); @@ -1118,6 +1153,11 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element e->setPasswordBox(true,L'*'); + auto style = getStyleForElement("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))); + irr::SEvent evt; evt.EventType = EET_KEY_INPUT_EVENT; evt.KeyInput.Key = KEY_END; @@ -1194,6 +1234,14 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, evt.KeyInput.PressedDown = true; e->OnEvent(evt); } + + auto style = getStyleForElement(is_multiline ? "textarea" : "field", spec.fname); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); + e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + if (style.get(StyleSpec::BGCOLOR, "") == "transparent") { + e->setDrawBackground(false); + } } if (!spec.flabel.empty()) { @@ -1407,6 +1455,15 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) gui::IGUIStaticText *e = gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, false, this, spec.fid); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); + + auto style = getStyleForElement("label", spec.fname); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, false)); + e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + if (style.isNotDefault(StyleSpec::BGCOLOR)) { + e->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR)); + } + m_fields.push_back(spec); } @@ -1475,9 +1532,18 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen L"", 258+m_fields.size() ); - gui::IGUIStaticText *t = gui::StaticText::add(Environment, spec.flabel.c_str(), + gui::IGUIStaticText *e = gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, false, this, spec.fid); - t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); + e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); + + auto style = getStyleForElement("vertlabel", spec.fname, "label"); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, false)); + e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + if (style.isNotDefault(StyleSpec::BGCOLOR)) { + e->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR)); + } + m_fields.push_back(spec); return; } @@ -1563,14 +1629,21 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem Environment->setFocus(e); } - e->setUseAlphaChannel(true); + auto style = getStyleForElement("image_button", spec.fname); + + e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); e->setImage(guiScalingImageButton( Environment->getVideoDriver(), texture, geom.X, geom.Y)); e->setPressedImage(guiScalingImageButton( Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); e->setScaleImage(true); - e->setNotClipped(noclip); - e->setDrawBorder(drawborder); + if (parts.size() >= 7) { + e->setNotClipped(noclip); + e->setDrawBorder(drawborder); + } else { + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); + } m_fields.push_back(spec); return; @@ -1656,7 +1729,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen pos.Y+geom.Y); gui::IGUITabControl *e = Environment->addTabControl(rect, this, - false, show_border, spec.fid); + show_background, show_border, spec.fid); e->setAlignment(irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_LOWERRIGHT); e->setTabHeight(geom.Y); @@ -1665,16 +1738,13 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen Environment->setFocus(e); } - e->setNotClipped(true); - - auto style = getThemeForElement("tabheader", name); + auto style = getStyleForElement("tabheader", name); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, true)); for (const std::string &button : buttons) { auto tab = e->addTab(unescape_translate(unescape_string( utf8_to_wide(button))).c_str(), -1); - tab->setDrawBackground(false); - tab->setBackgroundColor(video::SColor(0xFFFF0000)); - if (style.hasProperty(StyleSpec::BGCOLOR)) + if (style.isNotDefault(StyleSpec::BGCOLOR)) tab->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR)); tab->setTextColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); @@ -1753,6 +1823,10 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, L""); + auto style = getStyleForElement("item_image_button", spec.fname, "image_button"); + e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); + e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); + if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } @@ -2043,30 +2117,46 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b { std::vector<std::string> parts = split(element, ';'); - if (parts.size() != 3) { + if (parts.size() < 2) { errorstream << "Invalid style element (" << parts.size() << "): '" << element << "'" << std::endl; return false; } std::string selector = trim(parts[0]); - std::string propname = trim(parts[1]); - std::string value = trim(parts[2]); - - StyleSpec::Property prop = StyleSpec::GetPropertyByName(propname); - if (prop == StyleSpec::NONE) { - errorstream << "Invalid style element (Unknown property " << prop << "): '" << element + if (selector.empty()) { + errorstream << "Invalid style element (Selector required): '" << element << "'" << std::endl; return false; } StyleSpec spec; - spec.set(prop, value); - if (selector.empty()) { - errorstream << "Invalid style element (Selector required): '" << element - << "'" << std::endl; - return false; + for (size_t i = 1; i < parts.size(); i++) { + size_t equal_pos = parts[i].find('='); + if (equal_pos == std::string::npos) { + errorstream << "Invalid style element (Property missing value): '" << element + << "'" << std::endl; + return false; + } + + std::string propname = trim(parts[i].substr(0, equal_pos)); + std::string value = trim(unescape_string(parts[i].substr(equal_pos + 1))); + + std::transform(propname.begin(), propname.end(), propname.begin(), ::tolower); + + StyleSpec::Property prop = StyleSpec::GetPropertyByName(propname); + if (prop == StyleSpec::NONE) { + if (property_warned.find(propname) != property_warned.end()) { + warningstream << "Invalid style element (Unknown property " << propname << "): '" + << element + << "'" << std::endl; + property_warned.insert(propname); + } + return false; + } + + spec.set(prop, value); } if (style_type) { @@ -4115,9 +4205,17 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id) return L""; } -StyleSpec GUIFormSpecMenu::getThemeForElement(const std::string &type, const std::string &name) { +StyleSpec GUIFormSpecMenu::getStyleForElement(const std::string &type, + const std::string &name, const std::string &parent_type) { StyleSpec ret; + if (!parent_type.empty()) { + auto it = theme_by_type.find(parent_type); + if (it != theme_by_type.end()) { + ret |= it->second; + } + } + auto it = theme_by_type.find(type); if (it != theme_by_type.end()) { ret |= it->second; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index b310f8a77..e4dc66151 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <utility> #include <stack> +#include <unordered_set> #include "irrlichttypes_extrabloated.h" #include "inventorymanager.h" @@ -404,8 +405,10 @@ protected: std::unordered_map<std::string, StyleSpec> theme_by_type; std::unordered_map<std::string, StyleSpec> theme_by_name; + std::unordered_set<std::string> property_warned; - StyleSpec getThemeForElement(const std::string &type, const std::string &name); + StyleSpec getStyleForElement(const std::string &type, + const std::string &name="", const std::string &parent_type=""); v2s32 padding; v2f32 spacing; @@ -574,7 +577,6 @@ private: * and the default value for the setting is true. */ bool m_remap_dbl_click; - }; class FormspecFormSource: public IFormSource |