2012-04-14 17:47:44 +02:00
|
|
|
#include "tooltips.hpp"
|
2012-04-15 21:14:14 +02:00
|
|
|
|
2014-02-19 18:40:29 +01:00
|
|
|
#include <iomanip>
|
|
|
|
|
2015-01-10 02:50:43 +01:00
|
|
|
#include <MyGUI_Gui.h>
|
|
|
|
#include <MyGUI_ImageBox.h>
|
|
|
|
#include <MyGUI_InputManager.h>
|
|
|
|
#include <MyGUI_RenderManager.h>
|
|
|
|
|
2022-09-05 19:35:15 +02:00
|
|
|
#include <components/esm/records.hpp>
|
2023-01-22 14:22:06 +04:00
|
|
|
#include <components/l10n/manager.hpp>
|
2022-06-29 00:32:11 +02:00
|
|
|
#include <components/misc/resourcehelpers.hpp>
|
2015-01-31 23:27:34 +01:00
|
|
|
#include <components/settings/settings.hpp>
|
2018-06-18 13:43:39 +04:00
|
|
|
#include <components/widgets/box.hpp>
|
2014-08-12 12:18:38 +02:00
|
|
|
|
2012-07-03 12:30:50 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
2015-02-04 21:18:43 +01:00
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
2012-08-12 18:11:09 +02:00
|
|
|
#include "../mwbase/windowmanager.hpp"
|
2012-07-03 12:30:50 +02:00
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
2020-04-26 20:46:51 +03:00
|
|
|
#include "../mwmechanics/spellutil.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "../mwworld/class.hpp"
|
2014-12-19 11:26:54 +01:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
|
2012-09-14 14:34:18 +02:00
|
|
|
#include "inventorywindow.hpp"
|
2013-04-10 00:32:05 -04:00
|
|
|
#include "mapwindow.hpp"
|
2012-07-03 12:30:50 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "itemmodel.hpp"
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
namespace MWGui
|
2012-04-14 17:47:44 +02:00
|
|
|
{
|
2014-08-24 20:51:41 +02:00
|
|
|
std::string ToolTips::sSchoolNames[] = { "#{sSchoolAlteration}", "#{sSchoolConjuration}", "#{sSchoolDestruction}",
|
|
|
|
"#{sSchoolIllusion}", "#{sSchoolMysticism}", "#{sSchoolRestoration}" };
|
2012-04-14 17:47:44 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
ToolTips::ToolTips()
|
|
|
|
: Layout("openmw_tooltips.layout")
|
|
|
|
, mFocusToolTipX(0.0)
|
|
|
|
, mFocusToolTipY(0.0)
|
2015-04-30 19:24:27 -05:00
|
|
|
, mHorizontalScrollIndex(0)
|
2013-04-17 18:56:48 -04:00
|
|
|
, mDelay(0.0)
|
|
|
|
, mRemainingDelay(0.0)
|
|
|
|
, mLastMouseX(0)
|
|
|
|
, mLastMouseY(0)
|
2015-04-30 19:24:27 -05:00
|
|
|
, mEnabled(true)
|
|
|
|
, mFullHelp(false)
|
2015-07-18 17:13:20 +02:00
|
|
|
, mShowOwned(0)
|
2017-07-20 20:59:36 +02:00
|
|
|
, mFrameDuration(0.f)
|
2013-03-13 19:44:34 +01:00
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
|
2012-04-14 17:47:44 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
mDynamicToolTipBox->setVisible(false);
|
2012-05-13 11:25:35 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// turn off mouse focus so that getMouseFocusWidget returns the correct widget,
|
|
|
|
// even if the mouse is over the tooltip
|
|
|
|
mDynamicToolTipBox->setNeedMouseFocus(false);
|
|
|
|
mMainWidget->setNeedMouseFocus(false);
|
2012-12-02 14:08:22 +01:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
mDelay = Settings::Manager::getFloat("tooltip delay", "GUI");
|
|
|
|
mRemainingDelay = mDelay;
|
2012-04-16 00:16:35 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
for (unsigned int i = 0; i < mMainWidget->getChildCount(); ++i)
|
|
|
|
{
|
|
|
|
mMainWidget->getChildAt(i)->setVisible(false);
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2015-07-18 17:13:20 +02:00
|
|
|
mShowOwned = Settings::Manager::getInt("show owned", "Game");
|
2012-05-20 22:06:54 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::setEnabled(bool enabled)
|
2012-05-13 11:25:35 +02:00
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
mEnabled = enabled;
|
2012-05-13 11:25:35 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::onFrame(float frameDuration)
|
2017-07-20 20:59:36 +02:00
|
|
|
{
|
|
|
|
mFrameDuration = frameDuration;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ToolTips::update(float frameDuration)
|
2012-04-15 17:10:08 +02:00
|
|
|
{
|
2012-05-29 12:35:03 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
while (mDynamicToolTipBox->getChildCount())
|
2012-05-28 09:46:05 +02:00
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
|
|
|
|
}
|
2012-10-18 22:21:39 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// start by hiding everything
|
|
|
|
for (unsigned int i = 0; i < mMainWidget->getChildCount(); ++i)
|
|
|
|
{
|
|
|
|
mMainWidget->getChildAt(i)->setVisible(false);
|
|
|
|
}
|
2012-06-02 12:25:24 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
2013-03-19 21:55:37 +01:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
if (!mEnabled)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2012-06-02 12:25:24 +02:00
|
|
|
|
2019-05-16 10:28:56 +04:00
|
|
|
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
|
|
|
bool guiMode = winMgr->isGuiMode();
|
2013-06-16 20:26:27 +02:00
|
|
|
|
2015-11-26 18:22:01 +01:00
|
|
|
if (guiMode)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2019-05-16 10:28:56 +04:00
|
|
|
if (!winMgr->getCursorVisible())
|
2017-09-28 19:42:16 +02:00
|
|
|
return;
|
2013-04-17 18:56:48 -04:00
|
|
|
const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition();
|
2012-06-02 12:25:24 +02:00
|
|
|
|
2019-05-16 10:28:56 +04:00
|
|
|
if (winMgr->getWorldMouseOver()
|
|
|
|
&& (winMgr->isConsoleMode() || (winMgr->getMode() == GM_Container)
|
|
|
|
|| (winMgr->getMode() == GM_Inventory)))
|
2012-06-02 12:25:24 +02:00
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
if (mFocusObject.isEmpty())
|
|
|
|
return;
|
2012-06-02 12:25:24 +02:00
|
|
|
|
2014-05-22 20:37:22 +02:00
|
|
|
const MWWorld::Class& objectclass = mFocusObject.getClass();
|
2012-05-28 09:46:05 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntSize tooltipSize;
|
2019-05-16 10:28:56 +04:00
|
|
|
if (!objectclass.hasToolTip(mFocusObject) && winMgr->isConsoleMode())
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
setCoord(0, 0, 300, 300);
|
|
|
|
mDynamicToolTipBox->setVisible(true);
|
|
|
|
ToolTipInfo info;
|
2014-09-17 13:02:29 +02:00
|
|
|
info.caption = mFocusObject.getClass().getName(mFocusObject);
|
|
|
|
if (info.caption.empty())
|
2023-02-20 23:11:18 +01:00
|
|
|
info.caption = mFocusObject.getCellRef().getRefId().toDebugString();
|
2022-05-04 22:33:39 +02:00
|
|
|
info.icon.clear();
|
2017-10-03 09:59:31 +04:00
|
|
|
tooltipSize = createToolTip(info, checkOwned());
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
|
|
|
else
|
2015-12-19 16:29:07 +01:00
|
|
|
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), true);
|
2012-05-28 09:46:05 +02:00
|
|
|
|
2013-07-10 03:25:09 +02:00
|
|
|
MyGUI::IntPoint tooltipPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
|
|
|
position(tooltipPosition, tooltipSize, viewSize);
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
|
2012-06-02 12:25:24 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
|
2012-06-02 12:25:24 +02:00
|
|
|
else
|
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY)
|
|
|
|
{
|
|
|
|
mRemainingDelay -= frameDuration;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mHorizontalScrollIndex = 0;
|
|
|
|
mRemainingDelay = mDelay;
|
|
|
|
}
|
|
|
|
mLastMouseX = mousePos.left;
|
|
|
|
mLastMouseY = mousePos.top;
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
if (mRemainingDelay > 0)
|
2012-06-02 12:25:24 +02:00
|
|
|
return;
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getMouseFocusWidget();
|
2020-11-13 11:39:47 +04:00
|
|
|
if (focus == nullptr)
|
2013-04-17 18:56:48 -04:00
|
|
|
return;
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntSize tooltipSize;
|
2013-04-10 00:32:05 -04:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// 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
|
|
|
|
while (!focus->isUserString("ToolTipType"))
|
|
|
|
{
|
|
|
|
focus = focus->getParent();
|
|
|
|
if (!focus)
|
|
|
|
return;
|
|
|
|
}
|
2013-04-10 00:32:05 -04:00
|
|
|
|
2023-05-21 16:39:32 +02:00
|
|
|
std::string_view type = focus->getUserString("ToolTipType");
|
2012-08-28 17:30:34 +02:00
|
|
|
|
2023-05-21 16:39:32 +02:00
|
|
|
if (type.empty())
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2012-08-28 17:30:34 +02:00
|
|
|
return;
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-08-28 17:30:34 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// special handling for markers on the local map: the tooltip should only be visible
|
|
|
|
// if the marker is not hidden due to the fog of war.
|
2015-01-31 17:50:19 +01:00
|
|
|
if (type == "MapMarker")
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2015-01-31 17:50:19 +01:00
|
|
|
LocalMapBase::MarkerUserData data = *focus->getUserData<LocalMapBase::MarkerUserData>();
|
2013-04-17 18:56:48 -04:00
|
|
|
|
2015-05-26 16:40:44 +02:00
|
|
|
if (!data.isPositionExplored())
|
2013-04-17 18:56:48 -04:00
|
|
|
return;
|
|
|
|
|
2015-01-31 17:50:19 +01:00
|
|
|
ToolTipInfo info;
|
|
|
|
info.text = data.caption;
|
|
|
|
info.notes = data.notes;
|
2017-10-03 09:59:31 +04:00
|
|
|
tooltipSize = createToolTip(info);
|
2015-01-31 17:50:19 +01:00
|
|
|
}
|
|
|
|
else if (type == "ItemPtr")
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2015-12-19 22:52:35 +01:00
|
|
|
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
|
2023-01-17 01:21:37 +01:00
|
|
|
if (mFocusObject.isEmpty())
|
2018-06-26 13:41:53 +10:00
|
|
|
return;
|
|
|
|
|
2017-10-06 11:38:27 +04:00
|
|
|
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), false, checkOwned());
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2013-05-11 18:38:27 +02:00
|
|
|
else if (type == "ItemModelIndex")
|
|
|
|
{
|
|
|
|
std::pair<ItemModel::ModelIndex, ItemModel*> pair
|
|
|
|
= *focus->getUserData<std::pair<ItemModel::ModelIndex, ItemModel*>>();
|
|
|
|
mFocusObject = pair.second->getItem(pair.first).mBase;
|
2017-10-03 09:59:31 +04:00
|
|
|
bool isAllowedToUse = pair.second->allowedToUseItems();
|
|
|
|
tooltipSize = getToolTipViaPtr(pair.second->getItem(pair.first).mCount, false, !isAllowedToUse);
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
else if (type == "ToolTipInfo")
|
2012-06-02 12:25:24 +02:00
|
|
|
{
|
2017-10-03 09:59:31 +04:00
|
|
|
tooltipSize = createToolTip(*focus->getUserData<MWGui::ToolTipInfo>());
|
2012-06-02 12:25:24 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
else if (type == "AvatarItemSelection")
|
|
|
|
{
|
2014-02-03 22:32:50 +01:00
|
|
|
MyGUI::IntCoord avatarPos = focus->getAbsoluteCoord();
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntPoint relMousePos = MyGUI::InputManager::getInstance().getMousePosition()
|
|
|
|
- MyGUI::IntPoint(avatarPos.left, avatarPos.top);
|
2019-05-16 10:28:56 +04:00
|
|
|
MWWorld::Ptr item
|
|
|
|
= winMgr->getInventoryWindow()->getAvatarSelectedItem(relMousePos.left, relMousePos.top);
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
mFocusObject = item;
|
|
|
|
if (!mFocusObject.isEmpty())
|
2015-12-19 16:29:07 +01:00
|
|
|
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), false);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
|
|
|
else if (type == "Spell")
|
|
|
|
{
|
|
|
|
ToolTipInfo info;
|
|
|
|
|
2023-04-20 21:07:53 +02:00
|
|
|
const ESM::Spell* spell = MWBase::Environment::get().getESMStore()->get<ESM::Spell>().find(
|
2023-03-24 01:32:27 +01:00
|
|
|
ESM::RefId::deserialize(focus->getUserString("Spell")));
|
2013-04-17 18:56:48 -04:00
|
|
|
info.caption = spell->mName;
|
|
|
|
Widgets::SpellEffectList effects;
|
2019-03-02 13:27:59 +04:00
|
|
|
for (const ESM::ENAMstruct& spellEffect : spell->mEffects.mList)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
Widgets::SpellEffectParams params;
|
2019-03-02 13:27:59 +04:00
|
|
|
params.mEffectID = spellEffect.mEffectID;
|
|
|
|
params.mSkill = spellEffect.mSkill;
|
|
|
|
params.mAttribute = spellEffect.mAttribute;
|
|
|
|
params.mDuration = spellEffect.mDuration;
|
|
|
|
params.mMagnMin = spellEffect.mMagnMin;
|
|
|
|
params.mMagnMax = spellEffect.mMagnMax;
|
|
|
|
params.mRange = spellEffect.mRange;
|
|
|
|
params.mArea = spellEffect.mArea;
|
2013-04-17 18:56:48 -04:00
|
|
|
params.mIsConstant = (spell->mData.mType == ESM::Spell::ST_Ability);
|
|
|
|
params.mNoTarget = false;
|
|
|
|
effects.push_back(params);
|
|
|
|
}
|
2014-08-24 20:51:41 +02:00
|
|
|
if (MWMechanics::spellIncreasesSkill(
|
|
|
|
spell)) // display school of spells that contribute to skill progress
|
|
|
|
{
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
2014-08-24 20:51:41 +02:00
|
|
|
int school = MWMechanics::getSpellSchool(spell, player);
|
|
|
|
info.text = "#{sSchool}: " + sSchoolNames[school];
|
|
|
|
}
|
2023-05-21 16:39:32 +02:00
|
|
|
const std::string& cost = focus->getUserString("SpellCost");
|
|
|
|
if (!cost.empty() && cost != "0")
|
2021-04-02 19:47:21 +02:00
|
|
|
info.text
|
|
|
|
+= MWGui::ToolTips::getValueString(MWMechanics::calcSpellCost(*spell), "#{sCastCost}");
|
2013-04-17 18:56:48 -04:00
|
|
|
info.effects = effects;
|
2017-10-03 09:59:31 +04:00
|
|
|
tooltipSize = createToolTip(info);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
|
|
|
else if (type == "Layout")
|
|
|
|
{
|
|
|
|
// tooltip defined in the layout
|
|
|
|
MyGUI::Widget* tooltip;
|
|
|
|
getWidget(tooltip, focus->getUserString("ToolTipLayout"));
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
tooltip->setVisible(true);
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2023-05-21 16:39:32 +02:00
|
|
|
const auto& userStrings = focus->getUserStrings();
|
2019-03-02 13:27:59 +04:00
|
|
|
for (auto& userStringPair : userStrings)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2021-05-10 22:44:07 -05:00
|
|
|
size_t underscorePos = userStringPair.first.find('_');
|
2014-06-17 18:33:53 +02:00
|
|
|
if (underscorePos == std::string::npos)
|
|
|
|
continue;
|
2019-03-02 13:27:59 +04:00
|
|
|
std::string key = userStringPair.first.substr(0, underscorePos);
|
2023-05-23 20:03:12 +02:00
|
|
|
std::string_view first = userStringPair.first;
|
|
|
|
std::string_view widgetName = first.substr(underscorePos + 1);
|
2012-06-02 12:25:24 +02:00
|
|
|
|
2016-10-31 00:23:51 +09:00
|
|
|
type = "Property";
|
2021-04-25 19:57:09 +02:00
|
|
|
size_t caretPos = key.find('^');
|
2014-08-16 13:24:44 +02:00
|
|
|
if (caretPos != std::string::npos)
|
|
|
|
{
|
2023-05-23 20:03:12 +02:00
|
|
|
type = first.substr(0, caretPos);
|
2014-08-16 13:24:44 +02:00
|
|
|
key.erase(key.begin(), key.begin() + caretPos + 1);
|
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::Widget* w;
|
|
|
|
getWidget(w, widgetName);
|
2014-08-16 13:24:44 +02:00
|
|
|
if (type == "Property")
|
2019-03-02 13:27:59 +04:00
|
|
|
w->setProperty(key, userStringPair.second);
|
2014-08-16 13:24:44 +02:00
|
|
|
else if (type == "UserData")
|
2019-03-02 13:27:59 +04:00
|
|
|
w->setUserString(key, userStringPair.second);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
tooltipSize = tooltip->getSize();
|
2013-03-13 19:44:34 +01:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw std::runtime_error("unknown tooltip type");
|
2012-04-14 17:47:44 +02:00
|
|
|
|
2013-07-10 03:25:09 +02:00
|
|
|
MyGUI::IntPoint tooltipPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-07-10 03:25:09 +02:00
|
|
|
position(tooltipPosition, tooltipSize, viewSize);
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
|
2012-06-02 12:25:24 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!mFocusObject.isEmpty())
|
2012-06-02 12:25:24 +02:00
|
|
|
{
|
2017-10-03 09:59:31 +04:00
|
|
|
MyGUI::IntSize tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), true, checkOwned());
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
setCoord(viewSize.width / 2 - tooltipSize.width / 2,
|
|
|
|
std::max(0, int(mFocusToolTipY * viewSize.height - tooltipSize.height)), tooltipSize.width,
|
|
|
|
tooltipSize.height);
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
mDynamicToolTipBox->setVisible(true);
|
|
|
|
}
|
2012-06-02 12:25:24 +02:00
|
|
|
}
|
2012-04-14 17:47:44 +02:00
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-07-10 03:25:09 +02:00
|
|
|
void ToolTips::position(MyGUI::IntPoint& position, MyGUI::IntSize size, MyGUI::IntSize viewportSize)
|
|
|
|
{
|
|
|
|
position += MyGUI::IntPoint(0, 32)
|
2015-03-08 13:07:29 +13:00
|
|
|
- MyGUI::IntPoint(static_cast<int>(MyGUI::InputManager::getInstance().getMousePosition().left
|
|
|
|
/ float(viewportSize.width) * size.width),
|
|
|
|
0);
|
2013-07-10 03:25:09 +02:00
|
|
|
|
|
|
|
if ((position.left + size.width) > viewportSize.width)
|
|
|
|
{
|
|
|
|
position.left = viewportSize.width - size.width;
|
|
|
|
}
|
|
|
|
if ((position.top + size.height) > viewportSize.height)
|
|
|
|
{
|
|
|
|
position.top = MyGUI::InputManager::getInstance().getMousePosition().top - size.height - 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-13 10:00:12 +04:00
|
|
|
void ToolTips::clear()
|
|
|
|
{
|
|
|
|
mFocusObject = MWWorld::Ptr();
|
|
|
|
|
|
|
|
while (mDynamicToolTipBox->getChildCount())
|
|
|
|
{
|
|
|
|
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < mMainWidget->getChildCount(); ++i)
|
|
|
|
{
|
|
|
|
mMainWidget->getChildAt(i)->setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-30 20:22:26 +04:00
|
|
|
void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
mFocusObject = focus;
|
2017-07-20 20:59:36 +02:00
|
|
|
|
|
|
|
update(mFrameDuration);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2017-10-03 09:59:31 +04:00
|
|
|
MyGUI::IntSize ToolTips::getToolTipViaPtr(int count, bool image, bool isOwned)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
// this the maximum width of the tooltip before it starts word-wrapping
|
|
|
|
setCoord(0, 0, 300, 300);
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntSize tooltipSize;
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2014-05-22 20:37:22 +02:00
|
|
|
const MWWorld::Class& object = mFocusObject.getClass();
|
2013-04-17 18:56:48 -04:00
|
|
|
if (!object.hasToolTip(mFocusObject))
|
|
|
|
{
|
|
|
|
mDynamicToolTipBox->setVisible(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mDynamicToolTipBox->setVisible(true);
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2015-12-19 16:29:07 +01:00
|
|
|
ToolTipInfo info = object.getToolTipInfo(mFocusObject, count);
|
2013-04-17 18:56:48 -04:00
|
|
|
if (!image)
|
2022-05-04 22:33:39 +02:00
|
|
|
info.icon.clear();
|
2017-10-03 09:59:31 +04:00
|
|
|
tooltipSize = createToolTip(info, isOwned);
|
2015-07-17 17:29:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return tooltipSize;
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2015-07-17 19:13:45 +02:00
|
|
|
bool ToolTips::checkOwned()
|
2015-07-17 17:29:00 +02:00
|
|
|
{
|
2017-10-03 09:59:31 +04:00
|
|
|
if (mFocusObject.isEmpty())
|
2015-07-17 19:13:45 +02:00
|
|
|
return false;
|
2017-10-03 09:59:31 +04:00
|
|
|
|
|
|
|
MWWorld::Ptr ptr = MWMechanics::getPlayer();
|
|
|
|
MWWorld::Ptr victim;
|
|
|
|
|
|
|
|
MWBase::MechanicsManager* mm = MWBase::Environment::get().getMechanicsManager();
|
|
|
|
return !mm->isAllowedToUse(ptr, mFocusObject, victim);
|
2012-04-15 21:14:14 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
|
2017-10-03 09:59:31 +04:00
|
|
|
MyGUI::IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info, bool isOwned)
|
2012-04-15 21:14:14 +02:00
|
|
|
{
|
2013-04-17 18:56:48 -04:00
|
|
|
mDynamicToolTipBox->setVisible(true);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2017-10-03 09:59:31 +04:00
|
|
|
if ((mShowOwned == 1 || mShowOwned == 3) && isOwned)
|
2017-08-08 22:57:39 +04:00
|
|
|
mDynamicToolTipBox->changeWidgetSkin(MWBase::Environment::get().getWindowManager()->isGuiMode()
|
|
|
|
? "HUD_Box_NoTransp_Owned"
|
|
|
|
: "HUD_Box_Owned");
|
2017-08-08 20:38:15 +04:00
|
|
|
else
|
|
|
|
mDynamicToolTipBox->changeWidgetSkin(
|
|
|
|
MWBase::Environment::get().getWindowManager()->isGuiMode() ? "HUD_Box_NoTransp" : "HUD_Box");
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
const std::string& caption = info.caption;
|
|
|
|
const std::string& image = info.icon;
|
|
|
|
int imageSize = (!image.empty()) ? info.imageSize : 0;
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string text = info.text;
|
2012-05-20 22:06:54 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// remove the first newline (easier this way)
|
|
|
|
if (text.size() > 0 && text[0] == '\n')
|
|
|
|
text.erase(0, 1);
|
2012-04-18 16:53:56 +02:00
|
|
|
|
2020-11-13 11:39:47 +04:00
|
|
|
const ESM::Enchantment* enchant = nullptr;
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2022-08-28 15:06:31 +02:00
|
|
|
if (!info.enchant.empty())
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2016-08-02 11:43:41 +12:00
|
|
|
enchant = store.get<ESM::Enchantment>().search(info.enchant);
|
|
|
|
if (enchant)
|
2016-08-01 13:16:42 +12:00
|
|
|
{
|
|
|
|
if (enchant->mData.mType == ESM::Enchantment::CastOnce)
|
|
|
|
text += "\n#{sItemCastOnce}";
|
|
|
|
else if (enchant->mData.mType == ESM::Enchantment::WhenStrikes)
|
|
|
|
text += "\n#{sItemCastWhenStrikes}";
|
|
|
|
else if (enchant->mData.mType == ESM::Enchantment::WhenUsed)
|
|
|
|
text += "\n#{sItemCastWhenUsed}";
|
|
|
|
else if (enchant->mData.mType == ESM::Enchantment::ConstantEffect)
|
|
|
|
text += "\n#{sItemCastConstant}";
|
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-11-03 16:39:32 +00:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// this the maximum width of the tooltip before it starts word-wrapping
|
|
|
|
setCoord(0, 0, 300, 300);
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const MyGUI::IntPoint padding(8, 8);
|
2012-04-17 16:49:28 +02:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
const int imageCaptionHPadding = !caption.empty() ? 8 : 0;
|
|
|
|
const int imageCaptionVPadding = !caption.empty() ? 4 : 0;
|
2012-04-17 16:49:28 +02:00
|
|
|
|
2017-03-23 14:31:01 +04:00
|
|
|
const int maximumWidth = MyGUI::RenderManager::getInstance().getViewSize().width - imageCaptionHPadding * 2;
|
|
|
|
|
2022-06-29 00:32:11 +02:00
|
|
|
const std::string realImage
|
|
|
|
= Misc::ResourceHelpers::correctIconPath(image, MWBase::Environment::get().getResourceSystem()->getVFS());
|
2012-04-17 16:49:28 +02:00
|
|
|
|
2018-06-18 13:43:39 +04:00
|
|
|
Gui::EditBox* captionWidget = mDynamicToolTipBox->createWidget<Gui::EditBox>(
|
|
|
|
"NormalText", MyGUI::IntCoord(0, 0, 300, 300), MyGUI::Align::Left | MyGUI::Align::Top, "ToolTipCaption");
|
2017-09-26 18:33:32 +02:00
|
|
|
captionWidget->setEditStatic(true);
|
|
|
|
captionWidget->setNeedKeyFocus(false);
|
2013-04-17 18:56:48 -04:00
|
|
|
captionWidget->setCaptionWithReplacing(caption);
|
|
|
|
MyGUI::IntSize captionSize = captionWidget->getTextSize();
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
int captionHeight = std::max(!caption.empty() ? captionSize.height : 0, imageSize);
|
2012-04-17 16:49:28 +02:00
|
|
|
|
2018-06-18 13:43:39 +04:00
|
|
|
Gui::EditBox* textWidget = mDynamicToolTipBox->createWidget<Gui::EditBox>("SandText",
|
|
|
|
MyGUI::IntCoord(0, captionHeight + imageCaptionVPadding, 300, 300 - captionHeight - imageCaptionVPadding),
|
|
|
|
MyGUI::Align::Stretch, "ToolTipText");
|
2017-09-26 18:33:32 +02:00
|
|
|
textWidget->setEditStatic(true);
|
|
|
|
textWidget->setEditMultiLine(true);
|
|
|
|
textWidget->setEditWordWrap(info.wordWrap);
|
2013-04-17 18:56:48 -04:00
|
|
|
textWidget->setCaptionWithReplacing(text);
|
|
|
|
textWidget->setTextAlign(MyGUI::Align::HCenter | MyGUI::Align::Top);
|
2017-09-26 18:33:32 +02:00
|
|
|
textWidget->setNeedKeyFocus(false);
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntSize textSize = textWidget->getTextSize();
|
2012-04-17 16:49:28 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
captionSize += MyGUI::IntSize(imageSize, 0); // adjust for image
|
2022-08-28 15:06:31 +02:00
|
|
|
MyGUI::IntSize totalSize = MyGUI::IntSize(
|
|
|
|
std::min(std::max(textSize.width, captionSize.width + ((!image.empty()) ? imageCaptionHPadding : 0)),
|
|
|
|
maximumWidth),
|
|
|
|
(!text.empty() ? textSize.height + imageCaptionVPadding : 0) + captionHeight);
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2019-03-02 13:27:59 +04:00
|
|
|
for (const std::string& note : info.notes)
|
2015-01-31 17:50:19 +01:00
|
|
|
{
|
|
|
|
MyGUI::ImageBox* icon = mDynamicToolTipBox->createWidget<MyGUI::ImageBox>("MarkerButton",
|
|
|
|
MyGUI::IntCoord(padding.left, totalSize.height + padding.top, 8, 8), MyGUI::Align::Default);
|
2015-03-08 13:07:29 +13:00
|
|
|
icon->setColour(MyGUI::Colour(1.0f, 0.3f, 0.3f));
|
2018-06-18 13:43:39 +04:00
|
|
|
Gui::EditBox* edit = mDynamicToolTipBox->createWidget<Gui::EditBox>("SandText",
|
2015-01-31 17:50:19 +01:00
|
|
|
MyGUI::IntCoord(padding.left + 8 + 4, totalSize.height + padding.top, 300 - padding.left - 8 - 4,
|
|
|
|
300 - totalSize.height),
|
|
|
|
MyGUI::Align::Default);
|
|
|
|
edit->setEditMultiLine(true);
|
|
|
|
edit->setEditWordWrap(true);
|
2019-03-02 13:27:59 +04:00
|
|
|
edit->setCaption(note);
|
2015-01-31 17:50:19 +01:00
|
|
|
edit->setSize(edit->getWidth(), edit->getTextSize().height);
|
|
|
|
icon->setPosition(icon->getLeft(), (edit->getTop() + edit->getBottom()) / 2 - icon->getHeight() / 2);
|
|
|
|
totalSize.height += std::max(edit->getHeight(), icon->getHeight());
|
|
|
|
totalSize.width = std::max(totalSize.width, edit->getWidth() + 8 + 4);
|
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
if (!info.effects.empty())
|
|
|
|
{
|
2023-05-21 16:39:32 +02:00
|
|
|
MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>({},
|
2014-06-05 17:43:12 +02:00
|
|
|
MyGUI::IntCoord(padding.left, totalSize.height, 300 - padding.left, 300 - totalSize.height),
|
2015-01-31 17:50:19 +01:00
|
|
|
MyGUI::Align::Stretch);
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
|
|
|
|
|
|
|
|
Widgets::MWEffectListPtr effectsWidget
|
|
|
|
= effectArea->createWidget<Widgets::MWEffectList>("MW_StatName", coord, MyGUI::Align::Default);
|
|
|
|
effectsWidget->setEffectList(info.effects);
|
|
|
|
|
|
|
|
std::vector<MyGUI::Widget*> effectItems;
|
2019-05-06 23:48:13 +00:00
|
|
|
int flag = info.isPotion ? Widgets::MWEffectList::EF_NoTarget : 0;
|
|
|
|
flag |= info.isIngredient ? Widgets::MWEffectList::EF_NoMagnitude : 0;
|
2021-12-26 19:50:19 +00:00
|
|
|
flag |= info.isIngredient ? Widgets::MWEffectList::EF_Constant : 0;
|
2022-08-01 11:00:14 +03:00
|
|
|
effectsWidget->createEffectWidgets(
|
|
|
|
effectItems, effectArea, coord, info.isPotion || info.isIngredient, flag);
|
2013-04-17 18:56:48 -04:00
|
|
|
totalSize.height += coord.top - 6;
|
|
|
|
totalSize.width = std::max(totalSize.width, coord.width);
|
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2016-08-01 13:16:42 +12:00
|
|
|
if (enchant)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2023-05-21 16:39:32 +02:00
|
|
|
MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>({},
|
2014-06-05 17:43:12 +02:00
|
|
|
MyGUI::IntCoord(padding.left, totalSize.height, 300 - padding.left, 300 - totalSize.height),
|
2015-01-31 17:50:19 +01:00
|
|
|
MyGUI::Align::Stretch);
|
2012-04-30 01:53:22 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
Widgets::MWEffectListPtr enchantWidget
|
|
|
|
= enchantArea->createWidget<Widgets::MWEffectList>("MW_StatName", coord, MyGUI::Align::Default);
|
|
|
|
enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects));
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::vector<MyGUI::Widget*> enchantEffectItems;
|
|
|
|
int flag
|
|
|
|
= (enchant->mData.mType == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0;
|
2022-08-01 11:00:14 +03:00
|
|
|
enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, false, flag);
|
2013-04-17 18:56:48 -04:00
|
|
|
totalSize.height += coord.top - 6;
|
|
|
|
totalSize.width = std::max(totalSize.width, coord.width);
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
if (enchant->mData.mType == ESM::Enchantment::WhenStrikes
|
|
|
|
|| enchant->mData.mType == ESM::Enchantment::WhenUsed)
|
|
|
|
{
|
|
|
|
int maxCharge = enchant->mData.mCharge;
|
|
|
|
int charge = (info.remainingEnchantCharge == -1) ? maxCharge : info.remainingEnchantCharge;
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const int chargeWidth = 204;
|
|
|
|
|
|
|
|
MyGUI::TextBox* chargeText = enchantArea->createWidget<MyGUI::TextBox>(
|
|
|
|
"SandText", MyGUI::IntCoord(0, 0, 10, 18), MyGUI::Align::Default, "ToolTipEnchantChargeText");
|
|
|
|
chargeText->setCaptionWithReplacing("#{sCharges}");
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const int chargeTextWidth = chargeText->getTextSize().width + 5;
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const int chargeAndTextWidth = chargeWidth + chargeTextWidth;
|
2012-10-01 00:23:49 +04:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
totalSize.width = std::max(totalSize.width, chargeAndTextWidth);
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
chargeText->setCoord((totalSize.width - chargeAndTextWidth) / 2, coord.top + 6, chargeTextWidth, 18);
|
2012-05-19 16:28:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
MyGUI::IntCoord chargeCoord;
|
|
|
|
if (totalSize.width < chargeWidth)
|
|
|
|
{
|
|
|
|
totalSize.width = chargeWidth;
|
|
|
|
chargeCoord = MyGUI::IntCoord(0, coord.top + 6, chargeWidth, 18);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
chargeCoord = MyGUI::IntCoord(
|
|
|
|
(totalSize.width - chargeAndTextWidth) / 2 + chargeTextWidth, coord.top + 6, chargeWidth, 18);
|
|
|
|
}
|
|
|
|
Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget<Widgets::MWDynamicStat>(
|
2015-01-31 17:50:19 +01:00
|
|
|
"MW_ChargeBar", chargeCoord, MyGUI::Align::Default);
|
2013-11-09 07:51:46 +01:00
|
|
|
chargeWidget->setValue(charge, maxCharge);
|
2013-04-17 18:56:48 -04:00
|
|
|
totalSize.height += 24;
|
|
|
|
}
|
|
|
|
}
|
2012-05-19 16:28:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
captionWidget->setCoord((totalSize.width - captionSize.width) / 2 + imageSize,
|
|
|
|
(captionHeight - captionSize.height) / 2, captionSize.width - imageSize, captionSize.height);
|
2012-04-30 00:57:41 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
// if its too long we do hscroll with the caption
|
|
|
|
if (captionSize.width > maximumWidth)
|
|
|
|
{
|
|
|
|
mHorizontalScrollIndex = mHorizontalScrollIndex + 2;
|
|
|
|
if (mHorizontalScrollIndex > captionSize.width)
|
|
|
|
{
|
|
|
|
mHorizontalScrollIndex = -totalSize.width;
|
2012-04-30 00:57:41 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
int horizontal_scroll = mHorizontalScrollIndex;
|
|
|
|
if (horizontal_scroll < 40)
|
|
|
|
{
|
|
|
|
horizontal_scroll = 40;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
horizontal_scroll = 80 - mHorizontalScrollIndex;
|
2012-04-30 00:57:41 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
captionWidget->setPosition(
|
|
|
|
MyGUI::IntPoint(horizontal_scroll, captionWidget->getPosition().top + padding.top));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
captionWidget->setPosition(captionWidget->getPosition() + padding);
|
2012-04-30 00:57:41 +02:00
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
textWidget->setPosition(textWidget->getPosition()
|
|
|
|
+ MyGUI::IntPoint(0,
|
|
|
|
padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter
|
2013-04-10 00:32:05 -04:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
if (!image.empty())
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
MyGUI::ImageBox* imageWidget = mDynamicToolTipBox->createWidget<MyGUI::ImageBox>("ImageBox",
|
|
|
|
MyGUI::IntCoord(
|
|
|
|
(totalSize.width - captionSize.width - imageCaptionHPadding) / 2, 0, imageSize, imageSize),
|
2015-01-31 17:50:19 +01:00
|
|
|
MyGUI::Align::Left | MyGUI::Align::Top);
|
2013-04-17 18:56:48 -04:00
|
|
|
imageWidget->setImageTexture(realImage);
|
|
|
|
imageWidget->setPosition(imageWidget->getPosition() + padding);
|
2013-03-13 19:44:34 +01:00
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
totalSize += MyGUI::IntSize(padding.left * 2, padding.top * 2);
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
return totalSize;
|
2012-04-30 00:57:41 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string ToolTips::toString(const float value)
|
|
|
|
{
|
|
|
|
std::ostringstream stream;
|
2014-06-05 18:15:48 +02:00
|
|
|
|
|
|
|
if (value != int(value))
|
|
|
|
stream << std::setprecision(3);
|
|
|
|
|
|
|
|
stream << value;
|
2013-04-17 18:56:48 -04:00
|
|
|
return stream.str();
|
|
|
|
}
|
2012-04-14 17:47:44 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string ToolTips::toString(const int value)
|
|
|
|
{
|
2019-01-07 17:47:39 +04:00
|
|
|
return std::to_string(value);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-04-15 17:10:08 +02:00
|
|
|
|
2016-08-14 19:37:22 +09:00
|
|
|
std::string ToolTips::getWeightString(const float weight, const std::string& prefix)
|
|
|
|
{
|
|
|
|
if (weight == 0)
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2016-08-14 19:37:22 +09:00
|
|
|
else
|
|
|
|
return "\n" + prefix + ": " + toString(weight);
|
|
|
|
}
|
|
|
|
|
2017-03-18 19:23:19 +04:00
|
|
|
std::string ToolTips::getPercentString(const float value, const std::string& prefix)
|
|
|
|
{
|
|
|
|
if (value == 0)
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2017-03-18 19:23:19 +04:00
|
|
|
else
|
|
|
|
return "\n" + prefix + ": " + toString(value * 100) + "%";
|
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string ToolTips::getValueString(const int value, const std::string& prefix)
|
|
|
|
{
|
|
|
|
if (value == 0)
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2013-04-17 18:56:48 -04:00
|
|
|
else
|
|
|
|
return "\n" + prefix + ": " + toString(value);
|
|
|
|
}
|
2012-04-16 22:58:16 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string ToolTips::getMiscString(const std::string& text, const std::string& prefix)
|
|
|
|
{
|
2022-08-28 15:06:31 +02:00
|
|
|
if (text.empty())
|
|
|
|
return {};
|
2013-04-17 18:56:48 -04:00
|
|
|
else
|
|
|
|
return "\n" + prefix + ": " + text;
|
|
|
|
}
|
2012-04-16 15:00:44 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string ToolTips::getCountString(const int value)
|
|
|
|
{
|
|
|
|
if (value == 1)
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2013-04-17 18:56:48 -04:00
|
|
|
else
|
2015-01-10 03:01:01 +01:00
|
|
|
return " (" + MyGUI::utility::toString(value) + ")";
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-12 13:46:03 +02:00
|
|
|
|
2020-04-10 23:14:00 +03:00
|
|
|
std::string ToolTips::getSoulString(const MWWorld::CellRef& cellref)
|
|
|
|
{
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
const ESM::RefId& soul = cellref.getSoul();
|
2020-04-10 23:14:00 +03:00
|
|
|
if (soul.empty())
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2020-04-10 23:14:00 +03:00
|
|
|
const ESM::Creature* creature = store.get<ESM::Creature>().search(soul);
|
|
|
|
if (!creature)
|
2022-08-28 15:06:31 +02:00
|
|
|
return {};
|
2020-04-10 23:14:00 +03:00
|
|
|
if (creature->mName.empty())
|
2023-02-20 23:11:18 +01:00
|
|
|
return " (" + creature->mId.toDebugString() + ")";
|
2020-04-10 23:14:00 +03:00
|
|
|
return " (" + creature->mName + ")";
|
|
|
|
}
|
|
|
|
|
2014-07-22 20:03:35 +02:00
|
|
|
std::string ToolTips::getCellRefString(const MWWorld::CellRef& cellref)
|
|
|
|
{
|
|
|
|
std::string ret;
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
ret += getMiscString(cellref.getOwner().getRefIdString(), "Owner");
|
|
|
|
const ESM::RefId& factionId = cellref.getFaction();
|
2019-10-05 16:59:04 +04:00
|
|
|
if (!factionId.empty())
|
2019-09-16 14:20:43 +04:00
|
|
|
{
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2019-09-16 14:20:43 +04:00
|
|
|
const ESM::Faction* fact = store.get<ESM::Faction>().search(factionId);
|
|
|
|
if (fact != nullptr)
|
|
|
|
{
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
ret += getMiscString(fact->mName.empty() ? factionId.getRefIdString() : fact->mName, "Owner Faction");
|
2019-10-05 16:59:04 +04:00
|
|
|
if (cellref.getFactionRank() >= 0)
|
|
|
|
{
|
|
|
|
int rank = cellref.getFactionRank();
|
2022-08-28 15:06:31 +02:00
|
|
|
const std::string& rankName = fact->mRanks[rank];
|
2019-10-05 16:59:04 +04:00
|
|
|
if (rankName.empty())
|
|
|
|
ret += getValueString(cellref.getFactionRank(), "Rank");
|
|
|
|
else
|
|
|
|
ret += getMiscString(rankName, "Rank");
|
|
|
|
}
|
2019-09-16 14:20:43 +04:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 21:18:43 +01:00
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
std::vector<std::pair<ESM::RefId, int>> itemOwners
|
2015-02-04 21:18:43 +01:00
|
|
|
= MWBase::Environment::get().getMechanicsManager()->getStolenItemOwners(cellref.getRefId());
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
for (std::pair<ESM::RefId, int>& owner : itemOwners)
|
2015-02-04 21:18:43 +01:00
|
|
|
{
|
2019-03-02 13:27:59 +04:00
|
|
|
if (owner.second == std::numeric_limits<int>::max())
|
2023-02-20 23:11:18 +01:00
|
|
|
ret += std::string("\nStolen from ") + owner.first.toDebugString(); // for legacy (ESS) savegames
|
2015-03-22 17:25:23 +01:00
|
|
|
else
|
2022-10-18 09:26:55 +02:00
|
|
|
ret += std::string("\nStolen ") + MyGUI::utility::toString(owner.second) + " from "
|
2023-02-20 23:11:18 +01:00
|
|
|
+ owner.first.toDebugString();
|
2015-02-04 21:18:43 +01:00
|
|
|
}
|
|
|
|
|
2014-07-22 20:03:35 +02:00
|
|
|
ret += getMiscString(cellref.getGlobalVariable(), "Global");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-07-31 15:41:32 +03:00
|
|
|
std::string ToolTips::getDurationString(float duration, const std::string& prefix)
|
|
|
|
{
|
2023-01-22 14:22:06 +04:00
|
|
|
auto l10n = MWBase::Environment::get().getL10nManager()->getContext("Interface");
|
|
|
|
|
2019-07-31 15:41:32 +03:00
|
|
|
std::string ret;
|
|
|
|
ret = prefix + ": ";
|
|
|
|
|
|
|
|
if (duration < 1.f)
|
|
|
|
{
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationSecond", { "seconds" }, { 0 });
|
2019-07-31 15:41:32 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-08-09 19:56:21 +03:00
|
|
|
constexpr int secondsPerMinute = 60; // 60 seconds
|
|
|
|
constexpr int secondsPerHour = secondsPerMinute * 60; // 60 minutes
|
|
|
|
constexpr int secondsPerDay = secondsPerHour * 24; // 24 hours
|
|
|
|
constexpr int secondsPerMonth = secondsPerDay * 30; // 30 days
|
|
|
|
constexpr int secondsPerYear = secondsPerDay * 365;
|
|
|
|
int fullDuration = static_cast<int>(duration);
|
2019-07-31 15:41:32 +03:00
|
|
|
int units = 0;
|
2019-08-09 19:56:21 +03:00
|
|
|
int years = fullDuration / secondsPerYear;
|
|
|
|
int months = fullDuration % secondsPerYear / secondsPerMonth;
|
|
|
|
int days = fullDuration % secondsPerYear % secondsPerMonth
|
|
|
|
/ secondsPerDay; // Because a year is not exactly 12 "months"
|
|
|
|
int hours = fullDuration % secondsPerDay / secondsPerHour;
|
|
|
|
int minutes = fullDuration % secondsPerHour / secondsPerMinute;
|
|
|
|
int seconds = fullDuration % secondsPerMinute;
|
|
|
|
if (years)
|
2019-07-31 15:41:32 +03:00
|
|
|
{
|
|
|
|
units++;
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationYear", { "years" }, { years });
|
2019-07-31 15:41:32 +03:00
|
|
|
}
|
2019-08-09 19:56:21 +03:00
|
|
|
if (months)
|
2019-07-31 15:41:32 +03:00
|
|
|
{
|
|
|
|
units++;
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationMonth", { "months" }, { months });
|
2019-07-31 15:41:32 +03:00
|
|
|
}
|
2019-08-09 19:56:21 +03:00
|
|
|
if (units < 2 && days)
|
2019-07-31 15:41:32 +03:00
|
|
|
{
|
|
|
|
units++;
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationDay", { "days" }, { days });
|
2019-07-31 15:41:32 +03:00
|
|
|
}
|
2019-08-09 19:56:21 +03:00
|
|
|
if (units < 2 && hours)
|
2019-07-31 15:41:32 +03:00
|
|
|
{
|
|
|
|
units++;
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationHour", { "hours" }, { hours });
|
2019-07-31 15:41:32 +03:00
|
|
|
}
|
2019-08-09 19:56:21 +03:00
|
|
|
if (units >= 2)
|
|
|
|
return ret;
|
|
|
|
if (minutes)
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationMinute", { "minutes" }, { minutes });
|
2019-08-09 19:56:21 +03:00
|
|
|
if (seconds)
|
2023-01-22 14:22:06 +04:00
|
|
|
ret += l10n->formatMessage("DurationSecond", { "seconds" }, { seconds });
|
2019-07-31 15:41:32 +03:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-05-16 09:21:08 +02:00
|
|
|
bool ToolTips::toggleFullHelp()
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
mFullHelp = !mFullHelp;
|
2014-05-16 09:21:08 +02:00
|
|
|
return mFullHelp;
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-04-16 22:58:16 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
bool ToolTips::getFullHelp() const
|
|
|
|
{
|
|
|
|
return mFullHelp;
|
|
|
|
}
|
2012-05-14 21:37:43 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
|
|
|
|
{
|
|
|
|
mFocusToolTipX = (min_x + max_x) / 2;
|
|
|
|
mFocusToolTipY = min_y;
|
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId)
|
|
|
|
{
|
|
|
|
if (skillId == -1)
|
|
|
|
return;
|
|
|
|
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
const std::string& skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
|
|
|
const ESM::Skill* skill = store.get<ESM::Skill>().find(skillId);
|
|
|
|
assert(skill);
|
|
|
|
|
|
|
|
const ESM::Attribute* attr = store.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
|
|
|
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->mDescription);
|
|
|
|
widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->mName + "}");
|
|
|
|
widget->setUserString("ImageTexture_SkillNoProgressImage", icon);
|
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId)
|
|
|
|
{
|
2023-05-28 15:10:53 +02:00
|
|
|
const ESM::Attribute* attribute
|
|
|
|
= MWBase::Environment::get().getESMStore()->get<ESM::Attribute>().search(attributeId);
|
|
|
|
if (!attribute)
|
2013-04-17 18:56:48 -04:00
|
|
|
return;
|
|
|
|
|
2023-05-28 15:10:53 +02:00
|
|
|
const std::string& icon = attribute->mIcon;
|
|
|
|
const std::string& name = attribute->mName;
|
|
|
|
const std::string& desc = attribute->mDescription;
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
|
|
|
widget->setUserString("ToolTipLayout", "AttributeToolTip");
|
|
|
|
widget->setUserString("Caption_AttributeName", "#{" + name + "}");
|
|
|
|
widget->setUserString("Caption_AttributeDescription", "#{" + desc + "}");
|
|
|
|
widget->setUserString("ImageTexture_AttributeImage", icon);
|
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId)
|
2012-05-27 06:39:10 +02:00
|
|
|
{
|
2017-04-30 19:45:36 +04:00
|
|
|
widget->setUserString("Caption_Caption", name);
|
2013-04-17 18:56:48 -04:00
|
|
|
std::string specText;
|
|
|
|
// get all skills of this specialisation
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::Store<ESM::Skill>& skills = MWBase::Environment::get().getESMStore()->get<ESM::Skill>();
|
2013-04-17 18:56:48 -04:00
|
|
|
|
2017-04-30 19:45:36 +04:00
|
|
|
bool isFirst = true;
|
2019-03-02 13:27:59 +04:00
|
|
|
for (auto& skillPair : skills)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2019-03-02 13:27:59 +04:00
|
|
|
if (skillPair.second.mData.mSpecialization == specId)
|
2017-04-30 19:45:36 +04:00
|
|
|
{
|
|
|
|
if (isFirst)
|
|
|
|
isFirst = false;
|
|
|
|
else
|
|
|
|
specText += "\n";
|
|
|
|
|
2019-03-02 13:27:59 +04:00
|
|
|
specText += std::string("#{") + ESM::Skill::sSkillNameIds[skillPair.first] + "}";
|
2017-04-30 19:45:36 +04:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2017-04-30 19:45:36 +04:00
|
|
|
widget->setUserString("Caption_ColumnText", specText);
|
|
|
|
widget->setUserString("ToolTipLayout", "SpecializationToolTip");
|
2013-04-17 18:56:48 -04:00
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
2012-05-27 06:39:10 +02:00
|
|
|
}
|
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const ESM::RefId& birthsignId)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2012-11-06 11:29:18 +04:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
const ESM::BirthSign* sign = store.get<ESM::BirthSign>().find(birthsignId);
|
2022-06-29 00:32:11 +02:00
|
|
|
const VFS::Manager* const vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
|
|
|
widget->setUserString("ToolTipLayout", "BirthSignToolTip");
|
2022-06-29 00:32:11 +02:00
|
|
|
widget->setUserString(
|
|
|
|
"ImageTexture_BirthSignImage", Misc::ResourceHelpers::correctTexturePath(sign->mTexture, vfs));
|
2022-08-28 15:06:31 +02:00
|
|
|
std::string text = sign->mName + "\n#{fontcolourhtml=normal}" + sign->mDescription;
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
std::vector<const ESM::Spell*> abilities, powers, spells;
|
2012-05-27 06:39:10 +02:00
|
|
|
|
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type
The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID
Slowly going through all the changes to make, still hundreds of errors
a lot of functions/structures use std::string or stringview to designate an ID. So it takes time
Continues slowly replacing ids. There are technically more and more compilation errors
I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type
Continue moving forward, changes to the stores
slowly moving along
Starting to see the fruit of those changes.
still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type.
More replacements. Things are starting to get easier
I can see more and more often the issue is that the function is awaiting a RefId, but is given a string
there is less need to go down functions and to fix a long list of them.
Still moving forward, and for the first time error count is going down!
Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably
Cells are back to using string for the name, haven't fixed everything yet. Many other changes
Under the bar of 400 compilation errors.
more good progress <100 compile errors!
More progress
Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string
some more progress on other fronts
Mostly game settings clean
one error opened a lot of other errors. Down to 18, but more will prbably appear
only link errors left??
Fixed link errors
OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
|
|
|
for (const ESM::RefId& spellId : sign->mPowers.mList)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
|
|
|
const ESM::Spell* spell = store.get<ESM::Spell>().search(spellId);
|
|
|
|
if (!spell)
|
|
|
|
continue; // Skip spells which cannot be found
|
|
|
|
ESM::Spell::SpellType type = static_cast<ESM::Spell::SpellType>(spell->mData.mType);
|
|
|
|
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)
|
2022-08-28 15:06:31 +02:00
|
|
|
abilities.push_back(spell);
|
2013-04-17 18:56:48 -04:00
|
|
|
else if (type == ESM::Spell::ST_Power)
|
2022-08-28 15:06:31 +02:00
|
|
|
powers.push_back(spell);
|
2013-04-17 18:56:48 -04:00
|
|
|
else if (type == ESM::Spell::ST_Spell)
|
2022-08-28 15:06:31 +02:00
|
|
|
spells.push_back(spell);
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2022-08-28 15:06:31 +02:00
|
|
|
using Category = std::pair<const std::vector<const ESM::Spell*>&, std::string_view>;
|
|
|
|
for (const auto& [category, label] : std::initializer_list<Category>{
|
|
|
|
{ abilities, "sBirthsignmenu1" }, { powers, "sPowers" }, { spells, "sBirthsignmenu2" } })
|
2012-05-27 06:39:10 +02:00
|
|
|
{
|
2019-03-02 13:27:59 +04:00
|
|
|
bool addHeader = true;
|
2022-08-28 15:06:31 +02:00
|
|
|
for (const ESM::Spell* spell : category)
|
2012-05-27 06:39:10 +02:00
|
|
|
{
|
2019-03-02 13:27:59 +04:00
|
|
|
if (addHeader)
|
2013-04-17 18:56:48 -04:00
|
|
|
{
|
2022-08-28 15:06:31 +02:00
|
|
|
text += "\n\n#{fontcolourhtml=header}#{";
|
|
|
|
text += label;
|
|
|
|
text += '}';
|
2019-03-02 13:27:59 +04:00
|
|
|
addHeader = false;
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2014-09-20 09:07:47 +02:00
|
|
|
text += "\n#{fontcolourhtml=normal}" + spell->mName;
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
}
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
widget->setUserString("Caption_BirthSignText", text);
|
2012-05-27 06:39:10 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace)
|
|
|
|
{
|
|
|
|
widget->setUserString("Caption_CenteredCaption", playerRace->mName);
|
|
|
|
widget->setUserString("Caption_CenteredCaptionText", playerRace->mDescription);
|
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
2017-04-30 19:45:36 +04:00
|
|
|
widget->setUserString("ToolTipLayout", "RaceToolTip");
|
2013-04-17 18:56:48 -04:00
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass)
|
|
|
|
{
|
2023-05-21 16:39:32 +02:00
|
|
|
if (playerClass.mName.empty())
|
2013-04-17 18:56:48 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
int spec = playerClass.mData.mSpecialization;
|
2023-05-26 12:16:47 +02:00
|
|
|
std::string specStr = "#{";
|
|
|
|
specStr += ESM::Class::sGmstSpecializationIds[spec];
|
|
|
|
specStr += '}';
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
widget->setUserString("Caption_ClassName", playerClass.mName);
|
|
|
|
widget->setUserString("Caption_ClassDescription", playerClass.mDescription);
|
|
|
|
widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
|
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
|
|
|
widget->setUserString("ToolTipLayout", "ClassToolTip");
|
|
|
|
}
|
2012-05-27 06:39:10 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
|
|
|
|
{
|
2023-04-20 21:07:53 +02:00
|
|
|
const ESM::MagicEffect* effect = MWBase::Environment::get().getESMStore()->get<ESM::MagicEffect>().find(id);
|
2023-05-23 19:06:08 +02:00
|
|
|
const std::string& name = ESM::MagicEffect::indexToGmstString(id);
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
std::string icon = effect->mIcon;
|
2014-08-12 12:18:38 +02:00
|
|
|
int slashPos = icon.rfind('\\');
|
2013-04-17 18:56:48 -04:00
|
|
|
icon.insert(slashPos + 1, "b_");
|
2022-06-29 00:32:11 +02:00
|
|
|
icon = Misc::ResourceHelpers::correctIconPath(icon, MWBase::Environment::get().getResourceSystem()->getVFS());
|
2013-04-17 18:56:48 -04:00
|
|
|
|
|
|
|
widget->setUserString("ToolTipType", "Layout");
|
|
|
|
widget->setUserString("ToolTipLayout", "MagicEffectToolTip");
|
|
|
|
widget->setUserString("Caption_MagicEffectName", "#{" + name + "}");
|
|
|
|
widget->setUserString("Caption_MagicEffectDescription", effect->mDescription);
|
2014-08-24 20:51:41 +02:00
|
|
|
widget->setUserString("Caption_MagicEffectSchool", "#{sSchool}: " + sSchoolNames[effect->mData.mSchool]);
|
2013-04-17 18:56:48 -04:00
|
|
|
widget->setUserString("ImageTexture_MagicEffectImage", icon);
|
|
|
|
}
|
2012-05-28 09:46:05 +02:00
|
|
|
|
2013-04-17 18:56:48 -04:00
|
|
|
void ToolTips::setDelay(float delay)
|
|
|
|
{
|
|
|
|
mDelay = delay;
|
|
|
|
mRemainingDelay = mDelay;
|
|
|
|
}
|
2012-09-23 00:36:20 +02:00
|
|
|
|
2012-05-28 09:46:05 +02:00
|
|
|
}
|