/* * Gui Skinning * Copyright (C) 2008 The Legend of Mazzeroth Development Team * Copyright (C) 2009 Aethyra Development Team * Copyright (C) 2009 The Mana World Development Team * Copyright (C) 2009-2012 The Mana Developers * * This file is part of The Mana Client. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include "graphics.h" #include "eventlistener.h" #include "gui/palette.h" #include "resources/image.h" #include "utils/xml.h" #include #include #include #include #include namespace gcn { class Widget; } class DyePalette; class Image; class ImageSet; class ProgressBar; class ThemeInfo { public: ThemeInfo() = default; explicit ThemeInfo(const std::string &path); bool isValid() const { return !name.empty(); } const std::string &getName() const { return name; } const std::string &getPath() const { return path; } std::string getFullPath() const; const XML::Document &getDocument() const { return *doc; } private: std::string name; std::string path; std::unique_ptr doc; }; enum class SkinType { Window, ToolWindow, Popup, SpeechBubble, Button, ButtonUp, ButtonDown, ButtonLeft, ButtonRight, ButtonClose, ButtonSticky, CheckBox, RadioButton, TextField, Tab, ScrollArea, ScrollAreaHBar, ScrollAreaHMarker, ScrollAreaVBar, ScrollAreaVMarker, DropDownFrame, DropDownButton, ProgressBar, Slider, SliderHandle, ResizeGrip, ShortcutBox, EquipmentBox, ItemSlot, EmoteSlot, }; enum StateFlags : uint8_t { STATE_HOVERED = 0x01, STATE_SELECTED = 0x02, STATE_DISABLED = 0x04, STATE_FOCUSED = 0x08, }; struct ColoredRectangle { gcn::Color color; bool filled = true; }; struct SkinPart { int offsetX = 0; int offsetY = 0; std::variant data; }; struct TextFormat { bool bold = false; gcn::Color color; std::optional outlineColor; std::optional shadowColor; }; struct SkinState { uint8_t stateFlags = 0; uint8_t setFlags = 0; TextFormat textFormat; std::vector parts; }; struct WidgetState { WidgetState() = default; explicit WidgetState(const gcn::Widget *widget); explicit WidgetState(const gcn::Rectangle &dim, uint8_t flags = 0); int x = 0; int y = 0; int width = 0; int height = 0; uint8_t flags = 0; }; class Skin { public: Skin() = default; ~Skin(); void addState(SkinState state); void draw(Graphics *graphics, const WidgetState &state) const; const SkinState *getState(uint8_t flags) const; /** * Returns the minimum width which can be used with this skin. */ int getMinWidth() const; /** * Returns the minimum height which can be used with this skin. */ int getMinHeight() const; /** * Updates the alpha value of the skin */ void updateAlpha(float alpha); int width = 0; int height = 0; int frameSize = 0; int padding = 0; int spacing = 0; int titleBarHeight = 0; int titleOffsetX = 0; int titleOffsetY = 0; int palette = 0; bool showButtons = true; private: std::vector mStates; }; class Theme : public EventListener { public: static std::string prepareThemePath(); static std::vector getAvailableThemes(); Theme(const ThemeInfo &themeInfo); ~Theme() override; const std::string &getThemePath() const { return mThemePath; } /** * Returns the patch to the given GUI resource relative to the theme * or, if it isn't in the theme, relative to 'graphics/gui'. */ std::string resolvePath(const std::string &path) const; static ResourceRef getImageFromTheme(const std::string &path); enum ThemePalette { TEXT, BLACK, // Color 0 RED, // Color 1 GREEN, // Color 2 BLUE, // Color 3 ORANGE, // Color 4 YELLOW, // Color 5 PINK, // Color 6 PURPLE, // Color 7 GRAY, // Color 8 BROWN, // Color 9 CARET, SHADOW, OUTLINE, PARTY_TAB, WHISPER_TAB, BACKGROUND, HIGHLIGHT, TAB_FLASH, SHOP_WARNING, ITEM_EQUIPPED, CHAT, OLDCHAT, AWAYCHAT, BUBBLE_TEXT, GM, GLOBAL, PLAYER, WHISPER, IS, PARTY, GUILD, SERVER, LOGGER, HYPERLINK, UNKNOWN_ITEM, GENERIC, HEAD, USABLE, TORSO, ONEHAND, LEGS, FEET, TWOHAND, SHIELD, RING, NECKLACE, ARMS, AMMO, SERVER_VERSION_NOT_SUPPORTED, THEME_COLORS_END }; enum ProgressPalette { PROG_DEFAULT, PROG_HP, PROG_MP, PROG_NO_MP, PROG_EXP, PROG_INVY_SLOTS, PROG_WEIGHT, PROG_JOB, THEME_PROG_END }; /** * Gets the color associated with the type in the default palette (0). * * @param type the color type requested * @return the requested color */ static const gcn::Color &getThemeColor(int type); static gcn::Color getProgressColor(int type, float progress); const Palette &getPalette(size_t index) const; /** * Returns a color from the default palette (0). */ const gcn::Color &getColor(int type) const; /** * Returns the color ID associated with a character, if it exists. * Returns no value if the character is not found. * * @param c character requested * @return the requested color or none */ static std::optional getColorIdForChar(char c); void drawSkin(Graphics *graphics, SkinType type, const WidgetState &state) const; void drawProgressBar(Graphics *graphics, const gcn::Rectangle &area, const gcn::Color &color, float progress, const std::string &text = std::string()) const; const Skin &getSkin(SkinType skinType) const; const Image *getIcon(const std::string &name) const; /** * Get the current GUI alpha value. */ int getGuiAlpha() const { return static_cast(mAlpha * 255.0f); } /** * Get the minimum opacity allowed to skins. */ float getMinimumOpacity() const { return mMinimumOpacity; } /** * Set the minimum opacity allowed to skins. * Set a negative value to free the minimum allowed. */ void setMinimumOpacity(float minimumOpacity); void event(Event::Channel channel, const Event &event) override; private: /** * Updates the alpha values of all of the skins and images. */ void updateAlpha(); ResourceRef getImage(const std::string &path) const; bool readTheme(const ThemeInfo &themeInfo); void readSkinNode(XML::Node node); void readSkinStateNode(XML::Node node, Skin &skin) const; void readSkinStateImgNode(XML::Node node, SkinState &state) const; void readIconNode(XML::Node node); void readPaletteNode(XML::Node node); void readProgressBarNode(XML::Node node); std::string mThemePath; std::map mSkins; std::map mIcons; /** * Tells if the current skins opacity * should not get less than the given value */ float mMinimumOpacity = 0.0f; float mAlpha = 1.0; std::vector mPalettes; std::vector> mProgressColors; };