Skip to content

Commit b6f633e

Browse files
committed
Merge branch 'reorderofreorderedeffects' into 'master'
Rework spell icon update (#8946) Closes #8946 See merge request OpenMW/openmw!5138
2 parents cafc2c7 + 1241bf2 commit b6f633e

File tree

2 files changed

+108
-178
lines changed

2 files changed

+108
-178
lines changed

apps/openmw/mwgui/spellicons.cpp

Lines changed: 106 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "spellicons.hpp"
22

3-
#include <format>
43
#include <iomanip>
54
#include <sstream>
65

@@ -24,184 +23,139 @@
2423

2524
namespace MWGui
2625
{
27-
void SpellIcons::updateWidgets(MyGUI::Widget* parent, bool adjustSize)
26+
namespace
2827
{
29-
MWWorld::Ptr player = MWMechanics::getPlayer();
30-
const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
28+
MyGUI::ImageBox* createIcon(MyGUI::Widget& parent, std::string_view name, std::string_view icon, int size)
29+
{
30+
const VFS::Manager& vfs = *MWBase::Environment::get().getResourceSystem()->getVFS();
3131

32-
std::map<ESM::RefId, std::vector<MagicEffectInfo>> effects;
33-
for (const auto& params : stats.getActiveSpells())
32+
const MyGUI::IntCoord coord(0, 0, size, size);
33+
MyGUI::ImageBox* widget = parent.createWidget<MyGUI::ImageBox>("ImageBox", coord, MyGUI::Align::Default);
34+
widget->setImageTexture(Misc::ResourceHelpers::correctIconPath(VFS::Path::toNormalized(icon), vfs));
35+
36+
ToolTipInfo tooltipInfo;
37+
tooltipInfo.caption = name;
38+
tooltipInfo.icon = icon;
39+
tooltipInfo.imageSize = size;
40+
tooltipInfo.wordWrap = false;
41+
42+
widget->setUserData(tooltipInfo);
43+
widget->setUserString("ToolTipType", "ToolTipInfo");
44+
widget->setVisible(false);
45+
46+
return widget;
47+
}
48+
49+
std::string printEffectMagnitude(float srcMagnitude, ESM::MagicEffect::MagnitudeDisplayType displayType)
3450
{
35-
for (const auto& effect : params.getEffects())
51+
std::string result;
52+
if (displayType == ESM::MagicEffect::MDT_None)
53+
return result;
54+
55+
const int magnitude = static_cast<int>(srcMagnitude);
56+
if (displayType == ESM::MagicEffect::MDT_TimesInt)
3657
{
37-
if (!(effect.mFlags & ESM::ActiveEffect::Flag_Applied))
38-
continue;
39-
MagicEffectInfo newEffectSource;
40-
newEffectSource.mKey = MWMechanics::EffectKey(effect.mEffectId, effect.getSkillOrAttribute());
41-
newEffectSource.mMagnitude = static_cast<int>(effect.mMagnitude);
42-
newEffectSource.mPermanent = effect.mDuration == -1.f;
43-
newEffectSource.mRemainingTime = effect.mTimeLeft;
44-
newEffectSource.mSource = params.getDisplayName();
45-
newEffectSource.mTotalTime = effect.mDuration;
46-
effects[effect.mEffectId].push_back(std::move(newEffectSource));
58+
std::stringstream formatter;
59+
formatter << std::fixed << std::setprecision(1) << " " << (magnitude / 10.0f);
60+
result += formatter.str();
61+
}
62+
else
63+
{
64+
result += ": " + MyGUI::utility::toString(magnitude);
65+
if (displayType != ESM::MagicEffect::MDT_Percentage)
66+
result += ' ';
4767
}
68+
69+
std::string_view unit;
70+
if (displayType == ESM::MagicEffect::MDT_TimesInt)
71+
unit = "sXTimesINT";
72+
else if (displayType == ESM::MagicEffect::MDT_Percentage)
73+
unit = "sPercent";
74+
else if (displayType == ESM::MagicEffect::MDT_Feet)
75+
unit = "sFeet";
76+
else if (displayType == ESM::MagicEffect::MDT_Level)
77+
unit = magnitude > 1 ? "sLevels" : "sLevel";
78+
else if (displayType == ESM::MagicEffect::MDT_Points)
79+
unit = magnitude > 1 ? "sPoints" : "sPoint";
80+
81+
result += MWBase::Environment::get().getWindowManager()->getGameSettingString(unit, {});
82+
83+
return result;
4884
}
85+
}
4986

50-
int w = 2;
51-
const auto& store = MWBase::Environment::get().getESMStore();
52-
for (const auto& [effectId, effectInfos] : effects)
87+
void SpellIcons::updateWidgets(MyGUI::Widget* parent, bool adjustSize)
88+
{
89+
for (auto& [effectId, widget] : mWidgetMap)
5390
{
54-
const ESM::MagicEffect* effect = store->get<ESM::MagicEffect>().find(effectId);
55-
56-
float remainingDuration = 0;
57-
float totalDuration = 0;
91+
widget->setVisible(false);
92+
widget->setAlpha(1.f);
93+
widget->getUserData<ToolTipInfo>()->text.clear();
94+
}
5895

59-
std::string sourcesDescription;
96+
int horizontalOffset = 2;
97+
constexpr int verticalOffset = 2;
98+
constexpr int size = 16;
6099

61-
static const float fadeTime
62-
= store->get<ESM::GameSetting>().find("fMagicStartIconBlink")->mValue.getFloat();
100+
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
101+
static const float fadeTime = store.get<ESM::GameSetting>().find("fMagicStartIconBlink")->mValue.getFloat();
63102

64-
bool addNewLine = false;
65-
for (const MagicEffectInfo& effectInfo : effectInfos)
103+
const MWWorld::Ptr player = MWMechanics::getPlayer();
104+
const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
105+
for (const auto& params : stats.getActiveSpells())
106+
{
107+
for (const auto& source : params.getEffects())
66108
{
67-
if (addNewLine)
68-
sourcesDescription += '\n';
109+
if (!(source.mFlags & ESM::ActiveEffect::Flag_Applied))
110+
continue;
111+
if (source.mDuration != -1.f && source.mTimeLeft <= 0.f)
112+
continue;
69113

70-
// if at least one of the effect sources is permanent, the effect will never wear off
71-
if (effectInfo.mPermanent)
72-
{
73-
remainingDuration = fadeTime;
74-
totalDuration = fadeTime;
75-
}
76-
else
77-
{
78-
remainingDuration = std::max(remainingDuration, effectInfo.mRemainingTime);
79-
totalDuration = std::max(totalDuration, effectInfo.mTotalTime);
80-
}
114+
const ESM::RefId effectId = source.mEffectId;
115+
const ESM::MagicEffect& effect = *store.get<ESM::MagicEffect>().find(effectId);
116+
const ESM::RefId arg = source.getSkillOrAttribute();
81117

82-
sourcesDescription += effectInfo.mSource;
118+
if (mWidgetMap.find(effectId) == mWidgetMap.end())
119+
mWidgetMap[effectId] = createIcon(*parent, effect.mName, effect.mIcon, size);
83120

84-
if (effect->mData.mFlags & ESM::MagicEffect::TargetSkill)
121+
MyGUI::ImageBox& widget = *mWidgetMap[effectId];
122+
if (!widget.getVisible())
85123
{
86-
const ESM::Skill* skill = store->get<ESM::Skill>().find(effectInfo.mKey.mArg);
87-
sourcesDescription += " (" + skill->mName + ')';
124+
widget.setPosition(horizontalOffset, verticalOffset);
125+
widget.setVisible(true);
126+
if (source.mDuration >= fadeTime && fadeTime > 0.f)
127+
widget.setAlpha(std::min(source.mTimeLeft / fadeTime, 1.f));
128+
horizontalOffset += size;
88129
}
89-
if (effect->mData.mFlags & ESM::MagicEffect::TargetAttribute)
90-
{
91-
const ESM::Attribute* attribute = store->get<ESM::Attribute>().find(effectInfo.mKey.mArg);
92-
sourcesDescription += " (" + attribute->mName + ')';
93-
}
94-
ESM::MagicEffect::MagnitudeDisplayType displayType = effect->getMagnitudeDisplayType();
95-
if (displayType == ESM::MagicEffect::MDT_TimesInt)
96-
{
97-
std::string_view timesInt
98-
= MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", {});
99-
std::stringstream formatter;
100-
formatter << std::fixed << std::setprecision(1) << " " << (effectInfo.mMagnitude / 10.0f)
101-
<< timesInt;
102-
sourcesDescription += formatter.str();
103-
}
104-
else if (displayType != ESM::MagicEffect::MDT_None)
105-
{
106-
sourcesDescription += ": " + MyGUI::utility::toString(effectInfo.mMagnitude);
107-
108-
if (displayType == ESM::MagicEffect::MDT_Percentage)
109-
sourcesDescription
110-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", {});
111-
else if (displayType == ESM::MagicEffect::MDT_Feet)
112-
{
113-
sourcesDescription += ' ';
114-
sourcesDescription
115-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", {});
116-
}
117-
else if (displayType == ESM::MagicEffect::MDT_Level)
118-
{
119-
sourcesDescription += ' ';
120-
if (effectInfo.mMagnitude > 1)
121-
sourcesDescription
122-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", {});
123-
else
124-
sourcesDescription
125-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", {});
126-
}
127-
else // ESM::MagicEffect::MDT_Points
128-
{
129-
sourcesDescription += ' ';
130-
if (effectInfo.mMagnitude > 1)
131-
sourcesDescription
132-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", {});
133-
else
134-
sourcesDescription
135-
+= MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", {});
136-
}
137-
}
138-
if (effectInfo.mRemainingTime > -1 && Settings::game().mShowEffectDuration)
139-
sourcesDescription
140-
+= MWGui::ToolTips::getDurationString(effectInfo.mRemainingTime, " #{sDuration}");
141130

142-
addNewLine = true;
143-
}
131+
std::string& desc = widget.getUserData<ToolTipInfo>()->text;
132+
if (!desc.empty())
133+
desc += '\n';
144134

145-
if (remainingDuration > 0.f)
146-
{
147-
MyGUI::ImageBox* image;
148-
if (mWidgetMap.find(effectId) == mWidgetMap.end())
135+
desc += params.getDisplayName();
136+
137+
if (effect.mData.mFlags & ESM::MagicEffect::TargetSkill)
149138
{
150-
image = parent->createWidget<MyGUI::ImageBox>(
151-
"ImageBox", MyGUI::IntCoord(w, 2, 16, 16), MyGUI::Align::Default);
152-
mWidgetMap[effectId] = image;
153-
154-
image->setImageTexture(
155-
Misc::ResourceHelpers::correctIconPath(VFS::Path::toNormalized(effect->mIcon),
156-
*MWBase::Environment::get().getResourceSystem()->getVFS()));
157-
158-
ToolTipInfo tooltipInfo;
159-
tooltipInfo.caption = effect->mName;
160-
tooltipInfo.icon = effect->mIcon;
161-
tooltipInfo.imageSize = 16;
162-
tooltipInfo.wordWrap = false;
163-
164-
image->setUserData(tooltipInfo);
165-
image->setUserString("ToolTipType", "ToolTipInfo");
139+
const ESM::Skill& skill = *store.get<ESM::Skill>().find(arg);
140+
desc += " (" + skill.mName + ')';
166141
}
167-
else
168-
image = mWidgetMap[effectId];
169-
170-
image->setPosition(w, 2);
171-
image->setVisible(true);
172-
w += 16;
173-
174-
ToolTipInfo* tooltipInfo = image->getUserData<ToolTipInfo>();
175-
tooltipInfo->text = std::move(sourcesDescription);
176-
177-
// Fade out
178-
if (totalDuration >= fadeTime && fadeTime > 0.f)
179-
image->setAlpha(std::min(remainingDuration / fadeTime, 1.f));
180-
}
181-
else if (mWidgetMap.find(effectId) != mWidgetMap.end())
182-
{
183-
MyGUI::ImageBox* image = mWidgetMap[effectId];
184-
image->setVisible(false);
185-
image->setAlpha(1.f);
142+
if (effect.mData.mFlags & ESM::MagicEffect::TargetAttribute)
143+
{
144+
const ESM::Attribute& attribute = *store.get<ESM::Attribute>().find(arg);
145+
desc += " (" + attribute.mName + ')';
146+
}
147+
desc += printEffectMagnitude(source.mMagnitude, effect.getMagnitudeDisplayType());
148+
if (source.mTimeLeft > -1 && Settings::game().mShowEffectDuration)
149+
desc += MWGui::ToolTips::getDurationString(source.mTimeLeft, " #{sDuration}");
186150
}
187151
}
188152

189153
if (adjustSize)
190154
{
191-
int s = w + 2;
192-
if (effects.empty())
193-
s = 0;
194-
int diff = parent->getWidth() - s;
195-
parent->setSize(s, parent->getHeight());
155+
const int newWidth = horizontalOffset > 2 ? horizontalOffset + 2 : 0;
156+
const int diff = parent->getWidth() - newWidth;
157+
parent->setSize(newWidth, parent->getHeight());
196158
parent->setPosition(parent->getLeft() + diff, parent->getTop());
197159
}
198-
199-
// hide inactive effects
200-
for (auto& widgetPair : mWidgetMap)
201-
{
202-
if (effects.find(widgetPair.first) == effects.end())
203-
widgetPair.second->setVisible(false);
204-
}
205160
}
206-
207161
}

apps/openmw/mwgui/spellicons.hpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,19 @@
11
#ifndef MWGUI_SPELLICONS_H
22
#define MWGUI_SPELLICONS_H
33

4-
#include <string>
5-
#include <vector>
4+
#include <map>
65

7-
#include "../mwmechanics/magiceffects.hpp"
6+
#include <components/esm/refid.hpp>
87

98
namespace MyGUI
109
{
1110
class Widget;
1211
class ImageBox;
1312
}
14-
namespace ESM
15-
{
16-
struct ENAMstruct;
17-
struct EffectList;
18-
}
1913

2014
namespace MWGui
2115
{
2216

23-
// information about a single magic effect source as required for display in the tooltip
24-
struct MagicEffectInfo
25-
{
26-
MagicEffectInfo()
27-
: mMagnitude(0)
28-
, mRemainingTime(0.f)
29-
, mTotalTime(0.f)
30-
, mPermanent(false)
31-
{
32-
}
33-
std::string mSource; // display name for effect source (e.g. potion name)
34-
MWMechanics::EffectKey mKey;
35-
int mMagnitude;
36-
float mRemainingTime;
37-
float mTotalTime;
38-
bool mPermanent; // the effect is permanent
39-
};
40-
4117
class SpellIcons
4218
{
4319
public:

0 commit comments

Comments
 (0)