diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-02-23 16:58:19 +0100 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-02-25 18:28:11 +0100 |
commit | 228e7a50ce1553b3fe21d16d0c7c642cf025be48 (patch) | |
tree | c4f02f7231d8a288a0c5d2c5b080cd87a90053cb /src | |
parent | 656d74376b1458cd32c97a217d22b8e0e7e6fea7 (diff) | |
download | mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.gz mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.bz2 mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.xz mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.zip |
Added tooltips to status effect icons
Based on the name attributes in the status-effect XML elements.
Also cleanup the code a little. Since the MiniStatusWindow now adjust
its size to respect the status icons, those icons no longer have to be
drawn from the Viewport.
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/ministatuswindow.cpp | 186 | ||||
-rw-r--r-- | src/gui/ministatuswindow.h | 24 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 6 | ||||
-rw-r--r-- | src/resources/statuseffectdb.cpp | 2 | ||||
-rw-r--r-- | src/statuseffect.h | 1 |
5 files changed, 118 insertions, 101 deletions
diff --git a/src/gui/ministatuswindow.cpp b/src/gui/ministatuswindow.cpp index 4c2a7b1d..4e32848c 100644 --- a/src/gui/ministatuswindow.cpp +++ b/src/gui/ministatuswindow.cpp @@ -47,12 +47,15 @@ #include "utils/stringutils.h" #include "utils/time.h" -static constexpr int ICON_SPACING = 4; +#include <algorithm> + +static constexpr int ICON_SPACING = 3; MiniStatusWindow::MiniStatusWindow(): Popup("MiniStatus") { setPadding(3); + setMinHeight(0); listen(Event::AttributesChannel); listen(Event::ActorSpriteChannel); @@ -87,8 +90,7 @@ MiniStatusWindow::MiniStatusWindow(): add(mMpBar); add(mXpBar); - setContentSize(mXpBar->getX() + mXpBar->getWidth(), - mXpBar->getY() + mXpBar->getHeight()); + updateSize(); auto stateIt = config.windows.find(getPopupName()); setVisible(stateIt != config.windows.end() ? stateIt->second.visible.value_or(true) @@ -101,34 +103,21 @@ MiniStatusWindow::MiniStatusWindow(): MiniStatusWindow::~MiniStatusWindow() = default; -void MiniStatusWindow::setIcon(int index, Sprite *sprite) -{ - if (index >= (int) mIcons.size()) - mIcons.resize(index + 1); - - mIcons[index].reset(sprite); -} - -void MiniStatusWindow::eraseIcon(int index) -{ - mIcons.erase(mIcons.begin() + index); -} - void MiniStatusWindow::drawIcons(Graphics *graphics) { const auto game = Game::instance(); const int tileWidth = game->getCurrentTileWidth(); const int tileHeight = game->getCurrentTileHeight(); - int iconX = mXpBar->getX() + mXpBar->getWidth() + 3 + tileWidth / 2; - int iconY = 3 + tileHeight; + int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2; + int iconY = ICON_SPACING + tileHeight; - for (auto &icon : mIcons) + for (auto &icon : mStatusIcons) { - icon->draw(graphics, - iconX - icon->getWidth() / 2, - iconY - icon->getHeight()); - iconX += ICON_SPACING + icon->getWidth(); + icon.sprite->draw(graphics, + iconX - icon.sprite->getWidth() / 2, + iconY - icon.sprite->getHeight()); + iconX += ICON_SPACING + icon.sprite->getWidth(); } } @@ -168,48 +157,25 @@ void MiniStatusWindow::event(Event::Channel channel, const Event &event) const int id = event.getInt("index"); const bool newStatus = event.getBool("newStatus"); - if (auto effect = StatusEffectDB::getStatusEffect(id)) - { - effect->deliverMessage(newStatus); - effect->playSfx(newStatus); - - Sprite *sprite = newStatus ? effect->getIconSprite() : nullptr; - - if (!sprite) - { - // delete sprite, if necessary - for (unsigned int i = 0; i < mStatusEffectIcons.size();) - if (mStatusEffectIcons[i] == id) - { - mStatusEffectIcons.erase(mStatusEffectIcons.begin() - + i); - eraseIcon(i); - } - else - i++; - } - else - { - // replace sprite or append - bool found = false; - - for (unsigned int i = 0; i < mStatusEffectIcons.size(); - i++) - if (mStatusEffectIcons[i] == id) - { - setIcon(i, sprite); - found = true; - break; - } - - if (!found) - { // add new - int offset = mStatusEffectIcons.size(); - setIcon(offset, sprite); - mStatusEffectIcons.push_back(id); - } - } - } + auto effect = StatusEffectDB::getStatusEffect(id); + if (!effect) + return; + + effect->deliverMessage(newStatus); + effect->playSfx(newStatus); + + Sprite *sprite = newStatus ? effect->getIconSprite() : nullptr; + auto it = std::find_if(mStatusIcons.begin(), mStatusIcons.end(), + [id](const StatusIcon &icon) { + return icon.effectId == id; + }); + + if (!sprite && it != mStatusIcons.end()) + mStatusIcons.erase(it); + else if (sprite && it == mStatusIcons.end()) + mStatusIcons.push_back(StatusIcon{id, std::unique_ptr<Sprite>(sprite)}); + + updateSize(); } } } @@ -231,42 +197,84 @@ void MiniStatusWindow::logic() } */ - for (auto &icon : mIcons) - icon->update(Time::deltaTimeMs()); + for (auto &icon : mStatusIcons) + icon.sprite->update(Time::deltaTimeMs()); +} + +void MiniStatusWindow::draw(gcn::Graphics *graphics) +{ + drawChildren(graphics); + + drawIcons(static_cast<Graphics*>(graphics)); } void MiniStatusWindow::mouseMoved(gcn::MouseEvent &event) { Popup::mouseMoved(event); - const int x = event.getX(); - const int y = event.getY(); + std::string tooltip1; + std::string tooltip2; if (event.getSource() == mXpBar) { - mTextPopup->show(x + getX(), y + getY(), - strprintf("%u/%u", PlayerInfo::getAttribute(EXP), - PlayerInfo::getAttribute(EXP_NEEDED)), - strprintf("%s: %u", _("Need"), - PlayerInfo::getAttribute(EXP_NEEDED) - - PlayerInfo::getAttribute(EXP))); + const int xp = PlayerInfo::getAttribute(EXP); + const int xpNeeded = PlayerInfo::getAttribute(EXP_NEEDED); + tooltip1 = strprintf("%u/%u", xp, xpNeeded); + tooltip2 = strprintf("%s: %u", _("Need"), xpNeeded - xp); } else if (event.getSource() == mHpBar) { - mTextPopup->show(x + getX(), y + getY(), - strprintf("%u/%u", PlayerInfo::getAttribute(HP), - PlayerInfo::getAttribute(MAX_HP))); + const int hp = PlayerInfo::getAttribute(HP); + const int maxHp = PlayerInfo::getAttribute(MAX_HP); + tooltip1 = strprintf("%u/%u", hp, maxHp); } else if (event.getSource() == mMpBar) { - mTextPopup->show(x + getX(), y + getY(), - strprintf("%u/%u", PlayerInfo::getAttribute(MP), - PlayerInfo::getAttribute(MAX_MP))); + const int mp = PlayerInfo::getAttribute(MP); + const int maxMp = PlayerInfo::getAttribute(MAX_MP); + tooltip1 = strprintf("%u/%u", mp, maxMp); } else { + // Check if the mouse is over one of the status icons + const auto game = Game::instance(); + const int tileWidth = game->getCurrentTileWidth(); + const int tileHeight = game->getCurrentTileHeight(); + + int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2; + int iconY = ICON_SPACING + tileHeight; + + for (const auto &icon : mStatusIcons) + { + int spriteX = iconX + icon.sprite->getOffsetX() - icon.sprite->getWidth() / 2; + int spriteY = iconY + icon.sprite->getOffsetY() - icon.sprite->getHeight(); + + if (event.getX() >= spriteX && + event.getX() < spriteX + icon.sprite->getWidth() && + event.getY() >= spriteY && + event.getY() < spriteY + icon.sprite->getHeight()) + { + auto effect = StatusEffectDB::getStatusEffect(icon.effectId); + if (effect) + tooltip1 = effect->name; + break; + } + + iconX += ICON_SPACING + icon.sprite->getWidth(); + } + } + + if (tooltip1.empty()) + { mTextPopup->setVisible(false); } + else + { + mTextPopup->show(event.getX() + getX(), + event.getY() + getY(), + tooltip1, + tooltip2); + } } void MiniStatusWindow::mouseExited(gcn::MouseEvent &event) @@ -275,3 +283,19 @@ void MiniStatusWindow::mouseExited(gcn::MouseEvent &event) mTextPopup->setVisible(false); } + +void MiniStatusWindow::updateSize() +{ + int width = mXpBar->getX() + mXpBar->getWidth(); + int height = mXpBar->getY() + mXpBar->getHeight(); + + // Increase width based on the size of the status icons + if (!mStatusIcons.empty()) + { + width += ICON_SPACING; + for (const auto &icon : mStatusIcons) + width += ICON_SPACING + icon.sprite->getWidth(); + } + + setContentSize(width, height); +} diff --git a/src/gui/ministatuswindow.h b/src/gui/ministatuswindow.h index a92ab63a..21c4b76e 100644 --- a/src/gui/ministatuswindow.h +++ b/src/gui/ministatuswindow.h @@ -44,27 +44,18 @@ class MiniStatusWindow : public Popup, public EventListener MiniStatusWindow(); ~MiniStatusWindow() override; - void drawIcons(Graphics *graphics); - void event(Event::Channel channel, const Event &event) override; void logic() override; // Updates icons - void draw(gcn::Graphics *graphics) override - { drawChildren(graphics); } + void draw(gcn::Graphics *graphics) override; void mouseMoved(gcn::MouseEvent &mouseEvent) override; void mouseExited(gcn::MouseEvent &event) override; private: - bool isInBar(ProgressBar *bar, int x, int y) const; - - /** - * Sets one of the icons. - */ - void setIcon(int index, Sprite *sprite); - - void eraseIcon(int index); + void drawIcons(Graphics *graphics); + void updateSize(); /* * Mini Status Bars @@ -74,8 +65,13 @@ class MiniStatusWindow : public Popup, public EventListener ProgressBar *mXpBar; TextPopup *mTextPopup; - std::vector<int> mStatusEffectIcons; - std::vector<std::unique_ptr<Sprite>> mIcons; + struct StatusIcon + { + int effectId; + std::unique_ptr<Sprite> sprite; + }; + + std::vector<StatusIcon> mStatusIcons; }; extern MiniStatusWindow *miniStatusWindow; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index fba08a9a..8f4ee686 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -32,7 +32,6 @@ #include "textmanager.h" #include "gui/gui.h" -#include "gui/ministatuswindow.h" #include "gui/popupmenu.h" #include "gui/beingpopup.h" @@ -237,11 +236,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) } } - // The icons for the MiniStatusWindow are drawn here, otherwise they would - // be clipped by the window. - if (miniStatusWindow) - miniStatusWindow->drawIcons(graphics); - // Draw contained widgets WindowContainer::draw(gcnGraphics); } diff --git a/src/resources/statuseffectdb.cpp b/src/resources/statuseffectdb.cpp index 1bfff5e1..fe179191 100644 --- a/src/resources/statuseffectdb.cpp +++ b/src/resources/statuseffectdb.cpp @@ -62,6 +62,8 @@ void StatusEffectDB::readStatusEffectNode(XML::Node node, const std::string &/* auto &effect = mStatusEffects[id]; + node.attribute("name", effect.name); + node.attribute("start-message", effect.start.message); node.attribute("start-audio", effect.start.sfx); node.attribute("start-particle", effect.start.particleEffect); diff --git a/src/statuseffect.h b/src/statuseffect.h index fce52603..2ab98d4f 100644 --- a/src/statuseffect.h +++ b/src/statuseffect.h @@ -36,6 +36,7 @@ public: std::string particleEffect; }; + std::string name; Event start; Event end; std::string icon; |