You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
551 lines
16 KiB
C++
551 lines
16 KiB
C++
#include "widgets.hpp"
|
|
#include "window_manager.hpp"
|
|
#include "components/esm_store/store.hpp"
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#undef min
|
|
#undef max
|
|
|
|
using namespace MWGui;
|
|
using namespace MWGui::Widgets;
|
|
|
|
/* Helper functions */
|
|
|
|
/*
|
|
* Fixes the filename of a texture path to use the correct .dds extension.
|
|
* This is needed on some ESM entries which point to a .tga file instead.
|
|
*/
|
|
void MWGui::Widgets::fixTexturePath(std::string &path)
|
|
{
|
|
int offset = path.rfind(".");
|
|
if (offset < 0)
|
|
return;
|
|
path.replace(offset, path.length() - offset, ".dds");
|
|
}
|
|
|
|
/* MWSkill */
|
|
|
|
MWSkill::MWSkill()
|
|
: manager(nullptr)
|
|
, skillId(ESM::Skill::Length)
|
|
, skillNameWidget(nullptr)
|
|
, skillValueWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
void MWSkill::setSkillId(ESM::Skill::SkillEnum skill)
|
|
{
|
|
skillId = skill;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWSkill::setSkillNumber(int skill)
|
|
{
|
|
if (skill < 0)
|
|
setSkillId(ESM::Skill::Length);
|
|
else if (skill < ESM::Skill::Length)
|
|
setSkillId(static_cast<ESM::Skill::SkillEnum>(skill));
|
|
else
|
|
throw new std::runtime_error("Skill number out of range");
|
|
}
|
|
|
|
void MWSkill::setSkillValue(const SkillValue& value_)
|
|
{
|
|
value = value_;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWSkill::updateWidgets()
|
|
{
|
|
if (skillNameWidget && manager)
|
|
{
|
|
if (skillId == ESM::Skill::Length)
|
|
{
|
|
skillNameWidget->setCaption("");
|
|
}
|
|
else
|
|
{
|
|
const std::string &name = manager->getGameSettingString(ESM::Skill::sSkillNameIds[skillId], "");
|
|
skillNameWidget->setCaption(name);
|
|
}
|
|
}
|
|
if (skillValueWidget)
|
|
{
|
|
SkillValue::Type modified = value.getModified(), base = value.getBase();
|
|
skillValueWidget->setCaption(boost::lexical_cast<std::string>(modified));
|
|
if (modified > base)
|
|
skillValueWidget->setState("increased");
|
|
else if (modified < base)
|
|
skillValueWidget->setState("decreased");
|
|
else
|
|
skillValueWidget->setState("normal");
|
|
}
|
|
}
|
|
|
|
void MWSkill::onClicked(MyGUI::Widget* _sender)
|
|
{
|
|
eventClicked(this);
|
|
}
|
|
|
|
void MWSkill::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
|
{
|
|
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
|
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
MWSkill::~MWSkill()
|
|
{
|
|
shutdownWidgetSkin();
|
|
}
|
|
|
|
void MWSkill::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
shutdownWidgetSkin();
|
|
Base::baseChangeWidgetSkin(_info);
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
void MWSkill::initialiseWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
{
|
|
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
if (name == "StatName")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned");
|
|
skillNameWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "StatValue")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned");
|
|
skillValueWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "StatNameButton")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! skillNameWidget, "widget already assigned");
|
|
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
skillNameWidget = button;
|
|
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWSkill::onClicked);
|
|
}
|
|
else if (name == "StatValueButton")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! skillValueWidget, "widget already assigned");
|
|
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
skillNameWidget = button;
|
|
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWSkill::onClicked);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MWSkill::shutdownWidgetSkin()
|
|
{
|
|
}
|
|
|
|
/* MWAttribute */
|
|
|
|
MWAttribute::MWAttribute()
|
|
: manager(nullptr)
|
|
, id(-1)
|
|
, attributeNameWidget(nullptr)
|
|
, attributeValueWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
void MWAttribute::setAttributeId(int attributeId)
|
|
{
|
|
id = attributeId;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWAttribute::setAttributeValue(const AttributeValue& value_)
|
|
{
|
|
value = value_;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWAttribute::onClicked(MyGUI::Widget* _sender)
|
|
{
|
|
eventClicked(this);
|
|
}
|
|
|
|
void MWAttribute::updateWidgets()
|
|
{
|
|
if (attributeNameWidget && manager)
|
|
{
|
|
if (id < 0 || id >= 8)
|
|
{
|
|
attributeNameWidget->setCaption("");
|
|
}
|
|
else
|
|
{
|
|
static const char *attributes[8] = {
|
|
"sAttributeStrength",
|
|
"sAttributeIntelligence",
|
|
"sAttributeWillpower",
|
|
"sAttributeAgility",
|
|
"sAttributeSpeed",
|
|
"sAttributeEndurance",
|
|
"sAttributePersonality",
|
|
"sAttributeLuck"
|
|
};
|
|
const std::string &name = manager->getGameSettingString(attributes[id], "");
|
|
attributeNameWidget->setCaption(name);
|
|
}
|
|
}
|
|
if (attributeValueWidget)
|
|
{
|
|
AttributeValue::Type modified = value.getModified(), base = value.getBase();
|
|
attributeValueWidget->setCaption(boost::lexical_cast<std::string>(modified));
|
|
if (modified > base)
|
|
attributeValueWidget->setState("increased");
|
|
else if (modified < base)
|
|
attributeValueWidget->setState("decreased");
|
|
else
|
|
attributeValueWidget->setState("normal");
|
|
}
|
|
}
|
|
|
|
void MWAttribute::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
|
{
|
|
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
|
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
MWAttribute::~MWAttribute()
|
|
{
|
|
shutdownWidgetSkin();
|
|
}
|
|
|
|
void MWAttribute::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
shutdownWidgetSkin();
|
|
Base::baseChangeWidgetSkin(_info);
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
void MWAttribute::initialiseWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
{
|
|
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
if (name == "StatName")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! attributeNameWidget, "widget already assigned");
|
|
attributeNameWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "StatValue")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! attributeValueWidget, "widget already assigned");
|
|
attributeValueWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "StatNameButton")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! attributeNameWidget, "widget already assigned");
|
|
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
attributeNameWidget = button;
|
|
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
|
}
|
|
else if (name == "StatValue")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! attributeValueWidget, "widget already assigned");
|
|
MyGUI::ButtonPtr button = (*iter)->castType<Button>();
|
|
attributeNameWidget = button;
|
|
button->eventMouseButtonClick = MyGUI::newDelegate(this, &MWAttribute::onClicked);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MWAttribute::shutdownWidgetSkin()
|
|
{
|
|
}
|
|
|
|
/* MWSpell */
|
|
|
|
MWSpell::MWSpell()
|
|
: mWindowManager(nullptr)
|
|
, spellNameWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
void MWSpell::setSpellId(const std::string &spellId)
|
|
{
|
|
id = spellId;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord)
|
|
{
|
|
const ESMS::ESMStore &store = mWindowManager->getStore();
|
|
const ESM::Spell *spell = store.spells.search(id);
|
|
MYGUI_ASSERT(spell, "spell with id '" << id << "' not found");
|
|
|
|
MWSpellEffectPtr effect = nullptr;
|
|
std::vector<ESM::ENAMstruct>::const_iterator end = spell->effects.list.end();
|
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->effects.list.begin(); it != end; ++it)
|
|
{
|
|
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
|
|
effect->setWindowManager(mWindowManager);
|
|
effect->setSpellEffect(*it);
|
|
effects.push_back(effect);
|
|
coord.top += effect->getHeight();
|
|
}
|
|
}
|
|
|
|
void MWSpell::updateWidgets()
|
|
{
|
|
if (spellNameWidget && mWindowManager)
|
|
{
|
|
const ESMS::ESMStore &store = mWindowManager->getStore();
|
|
const ESM::Spell *spell = store.spells.search(id);
|
|
if (spell)
|
|
spellNameWidget->setCaption(spell->name);
|
|
else
|
|
spellNameWidget->setCaption("");
|
|
}
|
|
}
|
|
|
|
void MWSpell::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
|
{
|
|
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
|
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
MWSpell::~MWSpell()
|
|
{
|
|
shutdownWidgetSkin();
|
|
}
|
|
|
|
void MWSpell::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
shutdownWidgetSkin();
|
|
Base::baseChangeWidgetSkin(_info);
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
void MWSpell::initialiseWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
{
|
|
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
if (name == "StatName")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! spellNameWidget, "widget already assigned");
|
|
spellNameWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MWSpell::shutdownWidgetSkin()
|
|
{
|
|
}
|
|
|
|
/* MWSpellEffect */
|
|
|
|
MWSpellEffect::MWSpellEffect()
|
|
: mWindowManager(nullptr)
|
|
, imageWidget(nullptr)
|
|
, textWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
void MWSpellEffect::setSpellEffect(SpellEffectValue value)
|
|
{
|
|
effect = value;
|
|
updateWidgets();
|
|
}
|
|
|
|
void MWSpellEffect::updateWidgets()
|
|
{
|
|
if (!mWindowManager)
|
|
return;
|
|
|
|
const ESMS::ESMStore &store = mWindowManager->getStore();
|
|
const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID);
|
|
if (textWidget)
|
|
{
|
|
if (magicEffect)
|
|
{
|
|
// TODO: Get name of effect from GMST
|
|
std::string spellLine = "";
|
|
if (effect.skill >= 0 && effect.skill < ESM::Skill::Length)
|
|
{
|
|
spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], "");
|
|
}
|
|
if (effect.attribute >= 0 && effect.attribute < 8)
|
|
{
|
|
static const char *attributes[8] = {
|
|
"sAttributeStrength",
|
|
"sAttributeIntelligence",
|
|
"sAttributeWillpower",
|
|
"sAttributeAgility",
|
|
"sAttributeSpeed",
|
|
"sAttributeEndurance",
|
|
"sAttributePersonality",
|
|
"sAttributeLuck"
|
|
};
|
|
spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], "");
|
|
}
|
|
if (effect.magnMin >= 0 || effect.magnMax >= 0)
|
|
{
|
|
if (effect.magnMin == effect.magnMax)
|
|
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " pts";
|
|
else
|
|
{
|
|
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " to " + boost::lexical_cast<std::string>(effect.magnMin) + " pts";
|
|
}
|
|
}
|
|
if (effect.duration >= 0)
|
|
{
|
|
spellLine += " for " + boost::lexical_cast<std::string>(effect.duration) + " secs";
|
|
}
|
|
if (effect.range == ESM::RT_Self)
|
|
spellLine += " on Self";
|
|
else if (effect.range == ESM::RT_Touch)
|
|
spellLine += " on Touch";
|
|
else if (effect.range == ESM::RT_Target)
|
|
spellLine += " on Target";
|
|
textWidget->setCaption(spellLine);
|
|
}
|
|
else
|
|
textWidget->setCaption("");
|
|
}
|
|
if (imageWidget)
|
|
{
|
|
std::string path = std::string("icons\\") + magicEffect->icon;
|
|
fixTexturePath(path);
|
|
imageWidget->setImageTexture(path);
|
|
}
|
|
}
|
|
|
|
void MWSpellEffect::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
|
{
|
|
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
|
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
MWSpellEffect::~MWSpellEffect()
|
|
{
|
|
shutdownWidgetSkin();
|
|
}
|
|
|
|
void MWSpellEffect::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
shutdownWidgetSkin();
|
|
Base::baseChangeWidgetSkin(_info);
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
void MWSpellEffect::initialiseWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
{
|
|
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
if (name == "Text")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! textWidget, "widget already assigned");
|
|
textWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "Image")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! imageWidget, "widget already assigned");
|
|
imageWidget = (*iter)->castType<StaticImage>();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MWSpellEffect::shutdownWidgetSkin()
|
|
{
|
|
}
|
|
|
|
/* MWDynamicStat */
|
|
|
|
MWDynamicStat::MWDynamicStat()
|
|
: value(0)
|
|
, max(1)
|
|
, textWidget(nullptr)
|
|
, barWidget(nullptr)
|
|
, barTextWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
void MWDynamicStat::setValue(int cur, int max_)
|
|
{
|
|
value = cur;
|
|
max = max_;
|
|
|
|
if (barWidget)
|
|
{
|
|
barWidget->setProgressRange(max);
|
|
barWidget->setProgressPosition(value);
|
|
}
|
|
|
|
|
|
if (barTextWidget)
|
|
{
|
|
if (value >= 0 && max > 0)
|
|
{
|
|
std::stringstream out;
|
|
out << value << "/" << max;
|
|
barTextWidget->setCaption(out.str().c_str());
|
|
}
|
|
else
|
|
barTextWidget->setCaption("");
|
|
}
|
|
}
|
|
void MWDynamicStat::setTitle(const std::string text)
|
|
{
|
|
if (textWidget)
|
|
textWidget->setCaption(text);
|
|
}
|
|
|
|
void MWDynamicStat::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
|
|
{
|
|
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
|
|
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
MWDynamicStat::~MWDynamicStat()
|
|
{
|
|
shutdownWidgetSkin();
|
|
}
|
|
|
|
void MWDynamicStat::baseChangeWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
shutdownWidgetSkin();
|
|
Base::baseChangeWidgetSkin(_info);
|
|
initialiseWidgetSkin(_info);
|
|
}
|
|
|
|
void MWDynamicStat::initialiseWidgetSkin(ResourceSkin* _info)
|
|
{
|
|
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
|
|
{
|
|
const std::string &name = *(*iter)->_getInternalData<std::string>();
|
|
if (name == "Text")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! textWidget, "widget already assigned");
|
|
textWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
else if (name == "Bar")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! barWidget, "widget already assigned");
|
|
barWidget = (*iter)->castType<Progress>();
|
|
}
|
|
else if (name == "BarText")
|
|
{
|
|
MYGUI_DEBUG_ASSERT( ! barTextWidget, "widget already assigned");
|
|
barTextWidget = (*iter)->castType<StaticText>();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MWDynamicStat::shutdownWidgetSkin()
|
|
{
|
|
}
|