diff options
Diffstat (limited to 'src/gui/StyleSpec.h')
-rw-r--r-- | src/gui/StyleSpec.h | 168 |
1 files changed, 162 insertions, 6 deletions
diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 999c1d237..67caf4f7b 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -18,8 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "client/tile.h" // ITextureSource +#include "client/fontengine.h" +#include "debug.h" #include "irrlichttypes_extrabloated.h" #include "util/string.h" +#include <algorithm> #include <array> #pragma once @@ -31,25 +34,38 @@ 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, + CONTENT_OFFSET, + PADDING, + FONT, + FONT_SIZE, 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) @@ -82,6 +98,14 @@ public: return FGIMG_PRESSED; } else if (name == "alpha") { return ALPHA; + } else if (name == "content_offset") { + return CONTENT_OFFSET; + } else if (name == "padding") { + return PADDING; + } else if (name == "font") { + return FONT; + } else if (name == "font_size") { + return FONT_SIZE; } else { return NONE; } @@ -99,6 +123,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]; @@ -143,6 +210,70 @@ public: return rect; } + irr::core::vector2d<s32> getVector2i(Property prop, irr::core::vector2d<s32> def) const + { + const auto &val = properties[prop]; + if (val.empty()) + return def; + + irr::core::vector2d<s32> vec; + if (!parseVector2i(val, &vec)) + return def; + + return vec; + } + + irr::core::vector2d<s32> getVector2i(Property prop) const + { + const auto &val = properties[prop]; + FATAL_ERROR_IF(val.empty(), "Unexpected missing property"); + + irr::core::vector2d<s32> vec; + parseVector2i(val, &vec); + return vec; + } + + gui::IGUIFont *getFont() const + { + FontSpec spec(FONT_SIZE_UNSPECIFIED, FM_Standard, false, false); + + const std::string &font = properties[FONT]; + const std::string &size = properties[FONT_SIZE]; + + if (font.empty() && size.empty()) + return nullptr; + + std::vector<std::string> modes = split(font, ','); + + for (size_t i = 0; i < modes.size(); i++) { + if (modes[i] == "normal") + spec.mode = FM_Standard; + else if (modes[i] == "mono") + spec.mode = FM_Mono; + else if (modes[i] == "bold") + spec.bold = true; + else if (modes[i] == "italic") + spec.italic = true; + } + + if (!size.empty()) { + int calc_size = 1; + + if (size[0] == '*') { + std::string new_size = size.substr(1); // Remove '*' (invalid for stof) + calc_size = stof(new_size) * g_fontengine->getFontSize(spec.mode); + } else if (size[0] == '+' || size[0] == '-') { + calc_size = stoi(size) + g_fontengine->getFontSize(spec.mode); + } else { + calc_size = stoi(size); + } + + spec.size = (unsigned)std::min(std::max(calc_size, 1), 999); + } + + return g_fontengine->getFont(spec); + } + video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc, video::ITexture *def) const { @@ -233,4 +364,29 @@ private: return true; } + + bool parseVector2i(const std::string &value, irr::core::vector2d<s32> *parsed_vec) const + { + irr::core::vector2d<s32> vec; + std::vector<std::string> v_vector = split(value, ','); + + if (v_vector.size() == 1) { + s32 x = stoi(v_vector[0]); + vec.X = x; + vec.Y = x; + } else if (v_vector.size() == 2) { + s32 x = stoi(v_vector[0]); + s32 y = stoi(v_vector[1]); + vec.X = x; + vec.Y = y; + } else { + warningstream << "Invalid vector2d string format: \"" << value + << "\"" << std::endl; + return false; + } + + *parsed_vec = vec; + + return true; + } }; |