diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 3e41fa6b1..d3d261ab0 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -1,6 +1,4 @@ #include "class.hpp" -#include "window_manager.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -8,6 +6,11 @@ #include #include +#include + +#include "window_manager.hpp" +#include "tooltips.hpp" + #undef min #undef max @@ -79,17 +82,13 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager) // Centre dialog center(); - setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(favoriteAttribute[0], "FavoriteAttribute0"); getWidget(favoriteAttribute[1], "FavoriteAttribute1"); favoriteAttribute[0]->setWindowManager(&mWindowManager); favoriteAttribute[1]->setWindowManager(&mWindowManager); - setText("MajorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu3", "Major Skills:")); - setText("MinorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu4", "Minor Skills:")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -231,15 +230,21 @@ void PickClassDialog::updateStats() "sSpecializationMagic", "sSpecializationStealth" }; - specializationName->setCaption(mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization])); + std::string specName = mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specialization); favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]); favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]); + ToolTips::createAttributeToolTip(favoriteAttribute[0], favoriteAttribute[0]->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute[1], favoriteAttribute[1]->getAttributeId()); for (int i = 0; i < 5; ++i) { majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); + ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][0]); + ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][1]); } classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); @@ -387,7 +392,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); @@ -451,6 +455,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) minorSkill[2]->setSkillId(ESM::Skill::Spear); minorSkill[3]->setSkillId(ESM::Skill::Athletics); minorSkill[4]->setSkillId(ESM::Skill::Enchant); + + setSpecialization(0); + update(); } CreateClassDialog::~CreateClassDialog() @@ -461,6 +468,18 @@ CreateClassDialog::~CreateClassDialog() delete descDialog; } +void CreateClassDialog::update() +{ + for (int i = 0; i < 5; ++i) + { + ToolTips::createSkillToolTip(majorSkill[i], majorSkill[i]->getSkillId()); + ToolTips::createSkillToolTip(minorSkill[i], minorSkill[i]->getSkillId()); + } + + ToolTips::createAttributeToolTip(favoriteAttribute0, favoriteAttribute0->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute1, favoriteAttribute1->getAttributeId()); +} + std::string CreateClassDialog::getName() const { return editName->getOnlyText(); @@ -539,14 +558,25 @@ void CreateClassDialog::open() void CreateClassDialog::onDialogCancel() { if (specDialog) - specDialog->setVisible(false); + { + mWindowManager.removeDialog(specDialog); + specDialog = 0; + } if (attribDialog) - attribDialog->setVisible(false); + { + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + } if (skillDialog) - skillDialog->setVisible(false); + { + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + } if (descDialog) - descDialog->setVisible(false); - // TODO: Delete dialogs here + { + mWindowManager.removeDialog(descDialog); + descDialog = 0; + } } void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) @@ -562,8 +592,23 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) void CreateClassDialog::onSpecializationSelected() { specializationId = specDialog->getSpecializationId(); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); - specDialog->setVisible(false); + setSpecialization(specializationId); + + mWindowManager.removeDialog(specDialog); + specDialog = 0; +} + +void CreateClassDialog::setSpecialization(int id) +{ + specializationId = (ESM::Class::Specialization) id; + static const char *specIds[3] = { + "sSpecializationCombat", + "sSpecializationMagic", + "sSpecializationStealth" + }; + std::string specName = mWindowManager.getGameSettingString(specIds[specializationId], specIds[specializationId]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specializationId); } void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) @@ -592,7 +637,10 @@ void CreateClassDialog::onAttributeSelected() favoriteAttribute0->setAttributeId(favoriteAttribute1->getAttributeId()); } attribute->setAttributeId(id); - attribDialog->setVisible(false); + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + + update(); } void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) @@ -625,7 +673,9 @@ void CreateClassDialog::onSkillSelected() } skill->setSkillId(skillDialog->getSkillId()); - skillDialog->setVisible(false); + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + update(); } void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) @@ -640,6 +690,7 @@ void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) { description = descDialog->getTextInput(); mWindowManager.removeDialog(descDialog); + descDialog = 0; } void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) @@ -665,20 +716,35 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM getWidget(specialization0, "Specialization0"); getWidget(specialization1, "Specialization1"); getWidget(specialization2, "Specialization2"); - specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); + std::string combat = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""); + std::string magic = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], ""); + std::string stealth = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], ""); + + specialization0->setCaption(combat); specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); + specialization1->setCaption(magic); specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); + specialization2->setCaption(stealth); specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specializationId = ESM::Class::Combat; + ToolTips::createSpecializationToolTip(specialization0, combat, ESM::Class::Combat); + ToolTips::createSpecializationToolTip(specialization1, magic, ESM::Class::Magic); + ToolTips::createSpecializationToolTip(specialization2, stealth, ESM::Class::Stealth); + MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSpecializationDialog::~SelectSpecializationDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -721,6 +787,7 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) attribute->setWindowManager(&parWindowManager); attribute->setAttributeId(ESM::Attribute::attributeIds[i]); attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); + ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId()); } MyGUI::ButtonPtr cancelButton; @@ -729,6 +796,13 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectAttributeDialog::~SelectAttributeDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -810,6 +884,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) skills[spec][i].widget->setWindowManager(&mWindowManager); skills[spec][i].widget->setSkillId(skills[spec][i].skillId); skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); + ToolTips::createSkillToolTip(skills[spec][i].widget, skills[spec][i].widget->getSkillId()); } } @@ -819,6 +894,13 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSkillDialog::~SelectSkillDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -853,6 +935,13 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +DescriptionDialog::~DescriptionDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 6f0138aa4..868052800 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -139,6 +139,7 @@ namespace MWGui { public: SelectSpecializationDialog(WindowManager& parWindowManager); + ~SelectSpecializationDialog(); ESM::Class::Specialization getSpecializationId() const { return specializationId; } @@ -169,6 +170,7 @@ namespace MWGui { public: SelectAttributeDialog(WindowManager& parWindowManager); + ~SelectAttributeDialog(); ESM::Attribute::AttributeID getAttributeId() const { return attributeId; } Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; } @@ -201,6 +203,7 @@ namespace MWGui { public: SelectSkillDialog(WindowManager& parWindowManager); + ~SelectSkillDialog(); ESM::Skill::SkillEnum getSkillId() const { return skillId; } Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; } @@ -236,6 +239,7 @@ namespace MWGui { public: DescriptionDialog(WindowManager& parWindowManager); + ~DescriptionDialog(); std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } @@ -285,6 +289,10 @@ namespace MWGui void onDescriptionEntered(WindowBase* parWindow); void onDialogCancel(); + void setSpecialization(int id); + + void update(); + private: MyGUI::EditPtr editName; MyGUI::TextBox* specializationName; diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index f18bdb41f..dea365ac2 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -1,7 +1,4 @@ #include "race.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -10,6 +7,12 @@ #include #include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" + using namespace MWGui; using namespace Widgets; @@ -51,7 +54,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager) prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); - setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair")); + setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu4", "Change Hair")); getWidget(prevButton, "PrevHairButton"); getWidget(nextButton, "NextHairButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); @@ -255,6 +258,8 @@ void RaceDialog::updateSkills() skillWidget->setWindowManager(&mWindowManager); skillWidget->setSkillNumber(skillId); skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus)); + ToolTips::createSkillToolTip(skillWidget, skillId); + skillItems.push_back(skillWidget); @@ -288,6 +293,8 @@ void RaceDialog::updateSpellPowers() spellPowerWidget = spellPowerList->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast(i)); spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setSpellId(spellpower); + spellPowerWidget->setUserString("ToolTipType", "Spell"); + spellPowerWidget->setUserString("Spell", spellpower); spellPowerItems.push_back(spellPowerWidget); diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 5059efb34..be537e854 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -1,12 +1,15 @@ #include "review.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" + +#include #include #include -#include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" #undef min #undef max @@ -74,7 +77,7 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) getWidget(skillAreaWidget, "Skills"); getWidget(skillClientWidget, "SkillClient"); getWidget(skillScrollerWidget, "SkillScroller"); - + skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition); updateScroller(); @@ -137,13 +140,17 @@ void ReviewDialog::setRace(const std::string &raceId_) raceId = raceId_; const ESM::Race *race = mWindowManager.getStore().races.search(raceId); if (race) + { + ToolTips::createRaceToolTip(raceWidget, race); raceWidget->setCaption(race->name); + } } void ReviewDialog::setClass(const ESM::Class& class_) { klass = class_; classWidget->setCaption(klass.name); + ToolTips::createClassToolTip(classWidget, klass); } void ReviewDialog::setBirthSign(const std::string& signId) @@ -151,22 +158,31 @@ void ReviewDialog::setBirthSign(const std::string& signId) birthSignId = signId; const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId); if (sign) + { birthSignWidget->setCaption(sign->name); + ToolTips::createBirthsignToolTip(birthSignWidget, birthSignId); + } } void ReviewDialog::setHealth(const MWMechanics::DynamicStat& value) { health->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + health->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } void ReviewDialog::setMagicka(const MWMechanics::DynamicStat& value) { magicka->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + magicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } void ReviewDialog::setFatigue(const MWMechanics::DynamicStat& value) { fatigue->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + fatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat& value) @@ -219,6 +235,8 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::ImageBox* separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); + separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); + skillWidgets.push_back(separator); coord1.top += separator->getHeight(); @@ -228,6 +246,7 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2 void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* groupWidget = skillClientWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); + groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); groupWidget->setCaption(label); skillWidgets.push_back(groupWidget); @@ -242,10 +261,12 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); + skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -262,6 +283,7 @@ void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGU skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); @@ -297,6 +319,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId else if (modified < base) state = "decreased"; MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + + for (int i=0; i<2; ++i) + { + ToolTips::createSkillToolTip(skillWidgets[skillWidgets.size()-1-i], skillId); + } + skillWidgetMap[skillId] = widget; } } @@ -330,6 +358,8 @@ void ReviewDialog::updateScroller() { skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); + if (clientHeight != 0) + skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() ); } // widget controls @@ -363,3 +393,15 @@ void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender) { eventActivateDialog(BIRTHSIGN_DIALOG); } + +void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (skillScrollerWidget->getScrollPosition() - _rel*0.3 < 0) + skillScrollerWidget->setScrollPosition(0); + else if (skillScrollerWidget->getScrollPosition() - _rel*0.3 > skillScrollerWidget->getScrollRange()-1) + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollRange()-1); + else + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollPosition() - _rel*0.3); + + onScrollChangePosition(skillScrollerWidget, skillScrollerWidget->getScrollPosition()); +} diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 76ca5a2d7..bae4dc459 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -68,6 +68,8 @@ namespace MWGui void onClassClicked(MyGUI::Widget* _sender); void onBirthSignClicked(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 54d9d7d4e..061800bf0 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -12,6 +12,7 @@ #include "../mwbase/environment.hpp" #include "window_manager.hpp" +#include "tooltips.hpp" using namespace MWGui; @@ -442,32 +443,17 @@ void StatsWindow::updateSkillArea() const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); MyGUI::Widget* raceWidget; getWidget(raceWidget, "RaceText"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); getWidget(raceWidget, "Race_str"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); // class tooltip MyGUI::Widget* classWidget; const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); - int spec = playerClass.data.specialization; - std::string specStr; - if (spec == 0) - specStr = "#{sSpecializationCombat}"; - else if (spec == 1) - specStr = "#{sSpecializationMagic}"; - else if (spec == 2) - specStr = "#{sSpecializationStealth}"; - getWidget(classWidget, "ClassText"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); getWidget(classWidget, "Class_str"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); if (!mFactions.empty()) { @@ -534,61 +520,8 @@ void StatsWindow::updateSkillArea() addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); MyGUI::Widget* w = addItem(sign->name, coord1, coord2); - w->setUserString("ToolTipType", "Layout"); - w->setUserString("ToolTipLayout", "BirthSignToolTip"); - std::string image = sign->texture; - image.replace(image.size()-3, 3, "dds"); - w->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); - std::string text; - - text += sign->name; - text += "\n#BF9959" + sign->description; - - std::vector abilities, powers, spells; - - std::vector::const_iterator it = sign->powers.list.begin(); - std::vector::const_iterator end = sign->powers.list.end(); - for (; it != end; ++it) - { - const std::string &spellId = *it; - const ESM::Spell *spell = store.spells.search(spellId); - if (!spell) - continue; // Skip spells which cannot be found - ESM::Spell::SpellType type = static_cast(spell->data.type); - if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) - continue; // We only want spell, ability and powers. - - if (type == ESM::Spell::ST_Ability) - abilities.push_back(spellId); - else if (type == ESM::Spell::ST_Power) - powers.push_back(spellId); - else if (type == ESM::Spell::ST_Spell) - spells.push_back(spellId); - } - - struct{ const std::vector &spells; std::string label; } categories[3] = { - {abilities, "sBirthsignmenu1"}, - {powers, "sPowers"}, - {spells, "sBirthsignmenu2"} - }; - - for (int category = 0; category < 3; ++category) - { - for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) - { - if (it == categories[category].spells.begin()) - { - text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; - } - - const std::string &spellId = *it; - - const ESM::Spell *spell = store.spells.search(spellId); - text += "\n#BF9959" + spell->name; - } - } - w->setUserString("Caption_BirthSignText", text); + ToolTips::createBirthsignToolTip(w, birthSignId); } // Add a line separator if there are items above diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index e21c88646..c6d8e2c8c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -65,6 +65,17 @@ void ToolTips::onFrame(float frameDuration) IntSize tooltipSize; + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) + { + focus = focus->getParent(); + if (!focus) + return; + ++i; + } + std::string type = focus->getUserString("ToolTipType"); std::string text = focus->getUserString("ToolTipText"); @@ -78,6 +89,29 @@ void ToolTips::onFrame(float frameDuration) mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } else if (type == "Layout") { // tooltip defined in the layout @@ -440,3 +474,150 @@ void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, mFocusToolTipX = (min_x + max_x) / 2; mFocusToolTipY = min_y; } + +void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId) +{ + if (skillId == -1) + return; + + const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); + assert(skill); + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->data.attribute); + assert(attr); + std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("Caption_SkillNoProgressName", "#{"+skillNameId+"}"); + widget->setUserString("Caption_SkillNoProgressDescription", skill->description); + widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); + widget->setUserString("ImageTexture_SkillNoProgressImage", icon); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); +} + +void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId) +{ + if (attributeId == -1) + return; + + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(attributeId); + assert(attr); + std::string icon = ESM::Attribute::attributeIcons[attributeId]; + std::string name = ESM::Attribute::gmstAttributeIds[attributeId]; + std::string desc = ESM::Attribute::gmstAttributeDescIds[attributeId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", "#{"+name+"}"); + widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}"); + widget->setUserString("ImageTexture_AttributeImage", icon); +} + +void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId) +{ + widget->setUserString("Caption_CenteredCaption", name); + std::string specText; + // get all skills of this specialisation + std::map skills = MWBase::Environment::get().getWorld()->getStore().skills.list; + for (std::map::const_iterator it = skills.begin(); + it != skills.end(); ++it) + { + if (it->second.data.specialization == specId) + specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->second.index] + "}"; + } + widget->setUserString("Caption_CenteredCaptionText", specText); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); + widget->setUserString("ToolTipType", "Layout"); +} + +void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId) +{ + const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find(birthsignId); + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "BirthSignToolTip"); + std::string image = sign->texture; + image.replace(image.size()-3, 3, "dds"); + widget->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); + std::string text; + + text += sign->name; + text += "\n#BF9959" + sign->description; + + std::vector abilities, powers, spells; + + std::vector::const_iterator it = sign->powers.list.begin(); + std::vector::const_iterator end = sign->powers.list.end(); + for (; it != end; ++it) + { + const std::string &spellId = *it; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + if (!spell) + continue; // Skip spells which cannot be found + ESM::Spell::SpellType type = static_cast(spell->data.type); + if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) + continue; // We only want spell, ability and powers. + + if (type == ESM::Spell::ST_Ability) + abilities.push_back(spellId); + else if (type == ESM::Spell::ST_Power) + powers.push_back(spellId); + else if (type == ESM::Spell::ST_Spell) + spells.push_back(spellId); + } + + struct{ const std::vector &spells; std::string label; } categories[3] = { + {abilities, "sBirthsignmenu1"}, + {powers, "sPowers"}, + {spells, "sBirthsignmenu2"} + }; + + for (int category = 0; category < 3; ++category) + { + for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) + { + if (it == categories[category].spells.begin()) + { + text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; + } + + const std::string &spellId = *it; + + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + text += "\n#BF9959" + spell->name; + } + } + + widget->setUserString("Caption_BirthSignText", text); +} + +void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace) +{ + widget->setUserString("Caption_CenteredCaption", playerRace->name); + widget->setUserString("Caption_CenteredCaptionText", playerRace->description); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); +} + +void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass) +{ + if (playerClass.name == "") + return; + + int spec = playerClass.data.specialization; + std::string specStr; + if (spec == 0) + specStr = "#{sSpecializationCombat}"; + else if (spec == 1) + specStr = "#{sSpecializationMagic}"; + else if (spec == 2) + specStr = "#{sSpecializationStealth}"; + + widget->setUserString("Caption_ClassName", playerClass.name); + widget->setUserString("Caption_ClassDescription", playerClass.description); + widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "ClassToolTip"); +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 6d4a205d1..1925a4f14 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -57,6 +57,15 @@ namespace MWGui static std::string getCountString(const int value); ///< @return blank string if count is 1, or else " (value)" + // these do not create an actual tooltip, but they fill in the data that is required so the tooltip + // system knows what to show in case this widget is hovered + static void createSkillToolTip(MyGUI::Widget* widget, int skillId); + static void createAttributeToolTip(MyGUI::Widget* widget, int attributeId); + static void createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId); + static void createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId); + static void createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace); + static void createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass); + private: MyGUI::Widget* mDynamicToolTipBox; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 2fd40b7c2..b85074805 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -301,8 +301,8 @@ void MWEffectList::createEffectWidgets(std::vector &effects, M { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - it->mIsConstant = (flags & EF_Constant); - it->mNoTarget = (flags & EF_NoTarget); + it->mIsConstant = (flags & EF_Constant) || it->mIsConstant; + it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget; effect->setSpellEffect(*it); effects.push_back(effect); if (effect->getRequestedWidth() > maxwidth) diff --git a/components/esm/attr.cpp b/components/esm/attr.cpp index 8c410e57a..b077ef499 100644 --- a/components/esm/attr.cpp +++ b/components/esm/attr.cpp @@ -34,3 +34,14 @@ const std::string Attribute::gmstAttributeDescIds[Attribute::Length] = { "sPerDesc", "sLucDesc" }; + +const std::string Attribute::attributeIcons[Attribute::Length] = { + "icons\\k\\attribute_strength.dds", + "icons\\k\\attribute_int.dds", + "icons\\k\\attribute_wilpower.dds", + "icons\\k\\attribute_agility.dds", + "icons\\k\\attribute_speed.dds", + "icons\\k\\attribute_endurance.dds", + "icons\\k\\attribute_personality.dds", + "icons\\k\\attribute_luck.dds" +}; diff --git a/components/esm/attr.hpp b/components/esm/attr.hpp index 183fb9e0e..620683dbb 100644 --- a/components/esm/attr.hpp +++ b/components/esm/attr.hpp @@ -30,6 +30,7 @@ struct Attribute static const AttributeID attributeIds[Length]; static const std::string gmstAttributeIds[Length]; static const std::string gmstAttributeDescIds[Length]; + static const std::string attributeIcons[Length]; Attribute(AttributeID id, const std::string &name, const std::string &description) : id(id) diff --git a/files/mygui/openmw_chargen_class_layout.xml b/files/mygui/openmw_chargen_class_layout.xml index 38fa606ab..613143d54 100644 --- a/files/mygui/openmw_chargen_class_layout.xml +++ b/files/mygui/openmw_chargen_class_layout.xml @@ -14,8 +14,11 @@ - + + + + @@ -23,16 +26,19 @@ - + + + + - + @@ -42,7 +48,7 @@ - + @@ -58,7 +64,7 @@ - + diff --git a/files/mygui/openmw_chargen_create_class_layout.xml b/files/mygui/openmw_chargen_create_class_layout.xml index be6a10e0c..dde74a6a2 100644 --- a/files/mygui/openmw_chargen_create_class_layout.xml +++ b/files/mygui/openmw_chargen_create_class_layout.xml @@ -12,17 +12,23 @@ - + + + + - + - + + + + @@ -59,7 +65,7 @@ - + diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml index 9a6ed4f2e..1cef9c9ce 100644 --- a/files/mygui/openmw_chargen_generate_class_result_layout.xml +++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml @@ -9,10 +9,10 @@ - + @@ -24,7 +24,7 @@ - + diff --git a/files/mygui/openmw_chargen_race_layout.xml b/files/mygui/openmw_chargen_race_layout.xml index a9b072f5e..df0d29f78 100644 --- a/files/mygui/openmw_chargen_race_layout.xml +++ b/files/mygui/openmw_chargen_race_layout.xml @@ -17,27 +17,23 @@ - - - - @@ -45,15 +41,13 @@ - - + - diff --git a/files/mygui/openmw_chargen_review_layout.xml b/files/mygui/openmw_chargen_review_layout.xml index 57bb3b124..2071cac88 100644 --- a/files/mygui/openmw_chargen_review_layout.xml +++ b/files/mygui/openmw_chargen_review_layout.xml @@ -26,26 +26,83 @@ + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -59,7 +116,7 @@ - + diff --git a/files/mygui/openmw_chargen_select_specialization_layout.xml b/files/mygui/openmw_chargen_select_specialization_layout.xml index 53980b133..1b5295bc9 100644 --- a/files/mygui/openmw_chargen_select_specialization_layout.xml +++ b/files/mygui/openmw_chargen_select_specialization_layout.xml @@ -11,13 +11,13 @@ - + - + - + diff --git a/files/mygui/openmw_infobox_layout.xml b/files/mygui/openmw_infobox_layout.xml index de1030830..89031a616 100644 --- a/files/mygui/openmw_infobox_layout.xml +++ b/files/mygui/openmw_infobox_layout.xml @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index e96aeb918..f1a8b0dfc 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -139,4 +139,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 6b62f618d..bfa970de5 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -65,27 +65,46 @@ - - - - - - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 262fd2020..148e98064 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -134,6 +134,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + +