2012-04-21 10:51:01 +02:00
|
|
|
#include "inventorywindow.hpp"
|
|
|
|
|
2018-02-24 15:13:14 +03:00
|
|
|
#include <cmath>
|
2017-10-20 01:10:17 +02:00
|
|
|
#include <stdexcept>
|
|
|
|
|
2015-01-10 02:50:43 +01:00
|
|
|
#include <MyGUI_Button.h>
|
2020-02-24 18:14:40 +00:00
|
|
|
#include <MyGUI_EditBox.h>
|
2015-01-10 02:50:43 +01:00
|
|
|
#include <MyGUI_ImageBox.h>
|
|
|
|
#include <MyGUI_InputManager.h>
|
|
|
|
#include <MyGUI_RenderManager.h>
|
|
|
|
#include <MyGUI_Window.h>
|
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
#include <osg/Texture2D>
|
|
|
|
|
2022-08-03 00:00:54 +02:00
|
|
|
#include <components/misc/strings/algorithm.hpp>
|
2015-07-07 19:16:32 +02:00
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
#include <components/myguiplatform/myguitexture.hpp>
|
|
|
|
|
2023-04-12 00:33:36 +02:00
|
|
|
#include <components/settings/values.hpp>
|
2015-01-31 23:27:34 +01:00
|
|
|
|
2012-07-03 12:30:50 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
2014-01-07 19:49:16 +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"
|
|
|
|
|
2018-07-09 19:31:40 +04:00
|
|
|
#include "../mwworld/actionequip.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "../mwworld/class.hpp"
|
2012-07-03 12:30:50 +02:00
|
|
|
#include "../mwworld/inventorystore.hpp"
|
|
|
|
|
2022-06-26 16:42:29 +02:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
2021-07-21 07:46:02 +00:00
|
|
|
#include "../mwmechanics/npcstats.hpp"
|
2015-08-21 21:12:39 +12:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "countdialog.hpp"
|
2015-01-10 01:21:17 +01:00
|
|
|
#include "draganddrop.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "inventoryitemmodel.hpp"
|
|
|
|
#include "itemview.hpp"
|
2023-04-12 00:33:36 +02:00
|
|
|
#include "settings.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "sortfilteritemmodel.hpp"
|
2020-04-10 23:14:00 +03:00
|
|
|
#include "tooltips.hpp"
|
2013-05-11 18:38:27 +02:00
|
|
|
#include "tradeitemmodel.hpp"
|
|
|
|
#include "tradewindow.hpp"
|
2012-05-15 18:05:53 +02:00
|
|
|
|
2014-12-15 15:23:03 +01:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
bool isRightHandWeapon(const MWWorld::Ptr& item)
|
|
|
|
{
|
2021-10-11 11:46:21 +00:00
|
|
|
if (item.getClass().getType() != ESM::Weapon::sRecordId)
|
2014-12-15 15:23:03 +01:00
|
|
|
return false;
|
|
|
|
std::vector<int> equipmentSlots = item.getClass().getEquipmentSlots(item).first;
|
|
|
|
return (!equipmentSlots.empty() && equipmentSlots.front() == MWWorld::InventoryStore::Slot_CarriedRight);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-04-21 10:51:01 +02:00
|
|
|
namespace MWGui
|
|
|
|
{
|
2023-04-12 00:33:36 +02:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
WindowSettingValues getModeSettings(GuiMode mode)
|
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case GM_Container:
|
|
|
|
return makeInventoryContainerWindowSettingValues();
|
|
|
|
case GM_Companion:
|
|
|
|
return makeInventoryCompanionWindowSettingValues();
|
|
|
|
case GM_Barter:
|
|
|
|
return makeInventoryBarterWindowSettingValues();
|
|
|
|
default:
|
|
|
|
return makeInventoryWindowSettingValues();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-04-21 10:51:01 +02:00
|
|
|
|
2016-08-16 22:47:45 +02:00
|
|
|
InventoryWindow::InventoryWindow(
|
|
|
|
DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem)
|
2013-05-11 18:38:27 +02:00
|
|
|
: WindowPinnableBase("openmw_inventory_window.layout")
|
|
|
|
, mDragAndDrop(dragAndDrop)
|
2015-04-30 19:24:27 -05:00
|
|
|
, mSelectedItem(-1)
|
2018-10-09 10:21:12 +04:00
|
|
|
, mSortModel(nullptr)
|
|
|
|
, mTradeModel(nullptr)
|
2013-07-31 21:40:29 +02:00
|
|
|
, mGuiMode(GM_Inventory)
|
2015-04-30 19:24:27 -05:00
|
|
|
, mLastXSize(0)
|
|
|
|
, mLastYSize(0)
|
2022-05-29 13:24:48 +02:00
|
|
|
, mPreview(std::make_unique<MWRender::InventoryPreview>(parent, resourceSystem, MWMechanics::getPlayer()))
|
2015-04-30 19:24:27 -05:00
|
|
|
, mTrading(false)
|
2018-08-27 09:37:08 +04:00
|
|
|
, mUpdateTimer(0.f)
|
2012-04-21 10:51:01 +02:00
|
|
|
{
|
2022-05-29 13:24:48 +02:00
|
|
|
mPreviewTexture
|
|
|
|
= std::make_unique<osgMyGUI::OSGTexture>(mPreview->getTexture(), mPreview->getTextureStateSet());
|
2015-05-20 02:18:20 +02:00
|
|
|
mPreview->rebuild();
|
|
|
|
|
2014-09-13 04:07:40 +02:00
|
|
|
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord
|
|
|
|
+= MyGUI::newDelegate(this, &InventoryWindow::onWindowResize);
|
2012-05-12 21:28:04 +02:00
|
|
|
|
|
|
|
getWidget(mAvatar, "Avatar");
|
2012-09-13 00:54:32 +02:00
|
|
|
getWidget(mAvatarImage, "AvatarImage");
|
2012-05-12 21:28:04 +02:00
|
|
|
getWidget(mEncumbranceBar, "EncumbranceBar");
|
|
|
|
getWidget(mFilterAll, "AllButton");
|
|
|
|
getWidget(mFilterWeapon, "WeaponButton");
|
|
|
|
getWidget(mFilterApparel, "ApparelButton");
|
|
|
|
getWidget(mFilterMagic, "MagicButton");
|
|
|
|
getWidget(mFilterMisc, "MiscButton");
|
2012-05-13 11:25:35 +02:00
|
|
|
getWidget(mLeftPane, "LeftPane");
|
|
|
|
getWidget(mRightPane, "RightPane");
|
2013-03-16 22:53:33 +01:00
|
|
|
getWidget(mArmorRating, "ArmorRating");
|
2020-02-24 18:14:40 +00:00
|
|
|
getWidget(mFilterEdit, "FilterEdit");
|
2012-05-12 21:44:33 +02:00
|
|
|
|
2014-02-03 22:32:50 +01:00
|
|
|
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
2015-05-20 02:18:20 +02:00
|
|
|
mAvatarImage->setRenderItemTexture(mPreviewTexture.get());
|
2016-02-05 20:23:41 +01:00
|
|
|
mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
|
2012-05-15 18:05:53 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
getWidget(mItemView, "ItemView");
|
|
|
|
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
|
|
|
|
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &InventoryWindow::onBackgroundSelected);
|
2012-05-12 22:44:12 +02:00
|
|
|
|
2012-05-12 21:44:33 +02:00
|
|
|
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
|
|
|
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
|
|
|
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
|
|
|
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
|
|
|
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
2020-02-24 18:14:40 +00:00
|
|
|
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &InventoryWindow::onNameFilterChanged);
|
2012-05-12 22:00:15 +02:00
|
|
|
|
|
|
|
mFilterAll->setStateSelected(true);
|
2012-05-13 16:41:00 +02:00
|
|
|
|
2013-12-03 18:42:35 +01:00
|
|
|
setGuiMode(mGuiMode);
|
|
|
|
|
|
|
|
adjustPanes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::adjustPanes()
|
|
|
|
{
|
2014-02-03 22:32:50 +01:00
|
|
|
const float aspect = 0.5; // fixed aspect ratio for the avatar image
|
2015-03-08 13:22:56 +13:00
|
|
|
int leftPaneWidth = static_cast<int>((mMainWidget->getSize().height - 44 - mArmorRating->getHeight()) * aspect);
|
2014-02-03 22:32:50 +01:00
|
|
|
mLeftPane->setSize(leftPaneWidth, mMainWidget->getSize().height - 44);
|
|
|
|
mRightPane->setCoord(mLeftPane->getPosition().left + leftPaneWidth + 4, mRightPane->getPosition().top,
|
|
|
|
mMainWidget->getSize().width - 12 - leftPaneWidth - 15, mMainWidget->getSize().height - 44);
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
2012-09-15 00:57:29 +02:00
|
|
|
|
2013-05-15 17:54:18 +02:00
|
|
|
void InventoryWindow::updatePlayer()
|
|
|
|
{
|
2014-01-08 18:39:44 +01:00
|
|
|
mPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
2022-08-31 18:49:50 +02:00
|
|
|
auto tradeModel = std::make_unique<TradeItemModel>(std::make_unique<InventoryItemModel>(mPtr), MWWorld::Ptr());
|
|
|
|
mTradeModel = tradeModel.get();
|
2015-08-16 17:49:37 +02:00
|
|
|
|
|
|
|
if (mSortModel) // reuse existing SortModel when possible to keep previous category/filter settings
|
2022-08-31 18:49:50 +02:00
|
|
|
mSortModel->setSourceModel(std::move(tradeModel));
|
2015-08-16 17:49:37 +02:00
|
|
|
else
|
2022-08-31 19:03:45 +02:00
|
|
|
{
|
|
|
|
auto sortModel = std::make_unique<SortFilterItemModel>(std::move(tradeModel));
|
|
|
|
mSortModel = sortModel.get();
|
|
|
|
mItemView->setModel(std::move(sortModel));
|
|
|
|
}
|
2015-08-16 17:49:37 +02:00
|
|
|
|
2020-02-25 15:21:06 +03:00
|
|
|
mSortModel->setNameFilter(mFilterEdit->getCaption());
|
|
|
|
|
2018-04-13 09:17:05 +04:00
|
|
|
mFilterAll->setStateSelected(true);
|
|
|
|
mFilterWeapon->setStateSelected(false);
|
|
|
|
mFilterApparel->setStateSelected(false);
|
|
|
|
mFilterMagic->setStateSelected(false);
|
|
|
|
mFilterMisc->setStateSelected(false);
|
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
mPreview->updatePtr(mPtr);
|
|
|
|
mPreview->rebuild();
|
|
|
|
mPreview->update();
|
|
|
|
|
|
|
|
dirtyPreview();
|
|
|
|
|
|
|
|
updatePreviewSize();
|
2017-04-19 18:28:49 +02:00
|
|
|
|
|
|
|
updateEncumbranceBar();
|
|
|
|
mItemView->update();
|
|
|
|
notifyContentChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::clear()
|
|
|
|
{
|
|
|
|
mPtr = MWWorld::Ptr();
|
2018-10-09 10:21:12 +04:00
|
|
|
mTradeModel = nullptr;
|
|
|
|
mSortModel = nullptr;
|
|
|
|
mItemView->setModel(nullptr);
|
2013-05-15 17:54:18 +02:00
|
|
|
}
|
|
|
|
|
2019-04-26 11:37:57 +04:00
|
|
|
void InventoryWindow::toggleMaximized()
|
|
|
|
{
|
2023-04-12 00:33:36 +02:00
|
|
|
const WindowSettingValues settings = getModeSettings(mGuiMode);
|
|
|
|
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mRegular : settings.mMaximized;
|
2019-04-26 11:37:57 +04:00
|
|
|
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
2023-04-12 00:33:36 +02:00
|
|
|
const float x = rect.mX * viewSize.width;
|
|
|
|
const float y = rect.mY * viewSize.height;
|
|
|
|
const float w = rect.mW * viewSize.width;
|
|
|
|
const float h = rect.mH * viewSize.height;
|
2019-04-26 11:37:57 +04:00
|
|
|
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
|
|
|
|
window->setCoord(x, y, w, h);
|
|
|
|
|
2023-04-12 00:33:36 +02:00
|
|
|
settings.mIsMaximized.set(!settings.mIsMaximized);
|
2019-04-26 11:37:57 +04:00
|
|
|
|
|
|
|
adjustPanes();
|
|
|
|
updatePreviewSize();
|
|
|
|
}
|
|
|
|
|
2013-07-31 21:40:29 +02:00
|
|
|
void InventoryWindow::setGuiMode(GuiMode mode)
|
|
|
|
{
|
|
|
|
mGuiMode = mode;
|
2023-04-12 00:33:36 +02:00
|
|
|
const WindowSettingValues settings = getModeSettings(mGuiMode);
|
2019-04-26 11:37:57 +04:00
|
|
|
setPinButtonVisible(mode == GM_Inventory);
|
|
|
|
|
2023-04-12 00:33:36 +02:00
|
|
|
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mMaximized : settings.mRegular;
|
2013-12-03 18:42:35 +01:00
|
|
|
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
2023-04-12 00:33:36 +02:00
|
|
|
MyGUI::IntPoint pos(static_cast<int>(rect.mX * viewSize.width), static_cast<int>(rect.mY * viewSize.height));
|
|
|
|
MyGUI::IntSize size(static_cast<int>(rect.mW * viewSize.width), static_cast<int>(rect.mH * viewSize.height));
|
2013-12-24 00:20:01 +01:00
|
|
|
|
2015-11-30 05:19:14 +01:00
|
|
|
bool needUpdate = (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight());
|
|
|
|
|
2015-10-26 14:25:44 +01:00
|
|
|
mMainWidget->setPosition(pos);
|
|
|
|
mMainWidget->setSize(size);
|
|
|
|
|
2013-12-03 18:42:35 +01:00
|
|
|
adjustPanes();
|
2015-11-30 05:19:14 +01:00
|
|
|
|
|
|
|
if (needUpdate)
|
|
|
|
updatePreviewSize();
|
2013-07-31 21:40:29 +02:00
|
|
|
}
|
|
|
|
|
2014-06-16 00:52:40 +02:00
|
|
|
SortFilterItemModel* InventoryWindow::getSortFilterModel()
|
|
|
|
{
|
|
|
|
return mSortModel;
|
|
|
|
}
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
TradeItemModel* InventoryWindow::getTradeModel()
|
|
|
|
{
|
|
|
|
return mTradeModel;
|
|
|
|
}
|
|
|
|
|
|
|
|
ItemModel* InventoryWindow::getModel()
|
|
|
|
{
|
|
|
|
return mTradeModel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::onBackgroundSelected()
|
|
|
|
{
|
|
|
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
|
|
|
mDragAndDrop->drop(mTradeModel, mItemView);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::onItemSelected(int index)
|
|
|
|
{
|
2017-10-19 17:17:14 +02:00
|
|
|
onItemSelectedFromSourceModel(mSortModel->mapToSource(index));
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
|
2017-10-19 17:17:14 +02:00
|
|
|
void InventoryWindow::onItemSelectedFromSourceModel(int index)
|
2013-05-11 18:38:27 +02:00
|
|
|
{
|
|
|
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
|
|
|
{
|
|
|
|
mDragAndDrop->drop(mTradeModel, mItemView);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ItemStack& item = mTradeModel->getItem(index);
|
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& sound = item.mBase.getClass().getDownSoundId(item.mBase);
|
2013-05-11 18:38:27 +02:00
|
|
|
|
|
|
|
MWWorld::Ptr object = item.mBase;
|
|
|
|
int count = item.mCount;
|
2017-10-20 01:10:17 +02:00
|
|
|
bool shift = MyGUI::InputManager::getInstance().isShiftPressed();
|
2013-11-01 00:20:33 +01:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
if (MyGUI::InputManager::getInstance().isControlPressed())
|
|
|
|
count = 1;
|
|
|
|
|
|
|
|
if (mTrading)
|
|
|
|
{
|
2014-09-13 18:48:41 -04:00
|
|
|
// Can't give conjured items to a merchant
|
|
|
|
if (item.mFlags & ItemStack::Flag_Bound)
|
2014-09-10 21:34:17 -04:00
|
|
|
{
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound(sound);
|
2014-09-10 21:34:17 -04:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog9}");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
// check if merchant accepts item
|
|
|
|
int services = MWBase::Environment::get().getWindowManager()->getTradeWindow()->getMerchantServices();
|
2014-05-22 20:37:22 +02:00
|
|
|
if (!object.getClass().canSell(object, services))
|
2013-05-11 18:38:27 +02:00
|
|
|
{
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound(sound);
|
2013-05-11 18:38:27 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog4}");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-31 13:28:09 +04:00
|
|
|
// If we unequip weapon during attack, it can lead to unexpected behaviour
|
|
|
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPtr))
|
|
|
|
{
|
2021-10-11 11:46:21 +00:00
|
|
|
bool isWeapon = item.mBase.getType() == ESM::Weapon::sRecordId;
|
2017-08-31 13:28:09 +04:00
|
|
|
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
|
|
|
|
|
|
|
if (isWeapon && invStore.isEquipped(item.mBase))
|
|
|
|
{
|
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sCantEquipWeapWarning}");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
if (count > 1 && !shift)
|
|
|
|
{
|
|
|
|
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
|
|
|
std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}";
|
2022-08-16 21:15:03 +02:00
|
|
|
std::string name{ object.getClass().getName(object) };
|
|
|
|
name += MWGui::ToolTips::getSoulString(object.getCellRef());
|
2020-04-10 23:14:00 +03:00
|
|
|
dialog->openCountDialog(name, message, count);
|
2013-05-11 18:38:27 +02:00
|
|
|
dialog->eventOkClicked.clear();
|
|
|
|
if (mTrading)
|
|
|
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem);
|
|
|
|
else
|
|
|
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::dragItem);
|
|
|
|
mSelectedItem = index;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mSelectedItem = index;
|
|
|
|
if (mTrading)
|
2018-10-09 10:21:12 +04:00
|
|
|
sellItem(nullptr, count);
|
2013-05-11 18:38:27 +02:00
|
|
|
else
|
2018-10-09 10:21:12 +04:00
|
|
|
dragItem(nullptr, count);
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-18 20:00:18 -06:00
|
|
|
void InventoryWindow::ensureSelectedItemUnequipped(int count)
|
2014-05-19 08:03:55 +02:00
|
|
|
{
|
|
|
|
const ItemStack& item = mTradeModel->getItem(mSelectedItem);
|
|
|
|
if (item.mType == ItemStack::Type_Equipped)
|
|
|
|
{
|
2014-05-22 20:37:22 +02:00
|
|
|
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
2023-01-16 23:51:04 +01:00
|
|
|
MWWorld::Ptr newStack = *invStore.unequipItemQuantity(item.mBase, count);
|
2014-05-19 08:03:55 +02:00
|
|
|
|
|
|
|
// The unequipped item was re-stacked. We have to update the index
|
|
|
|
// since the item pointed does not exist anymore.
|
|
|
|
if (item.mBase != newStack)
|
|
|
|
{
|
2016-01-18 20:00:18 -06:00
|
|
|
updateItemView(); // Unequipping can produce a new stack, not yet in the window...
|
|
|
|
|
2014-05-19 08:03:55 +02:00
|
|
|
// newIndex will store the index of the ItemStack the item was stacked on
|
|
|
|
int newIndex = -1;
|
|
|
|
for (size_t i = 0; i < mTradeModel->getItemCount(); ++i)
|
|
|
|
{
|
|
|
|
if (mTradeModel->getItem(i).mBase == newStack)
|
|
|
|
{
|
|
|
|
newIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newIndex == -1)
|
|
|
|
throw std::runtime_error("Can't find restacked item");
|
|
|
|
|
|
|
|
mSelectedItem = newIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
void InventoryWindow::dragItem(MyGUI::Widget* sender, int count)
|
|
|
|
{
|
2016-01-18 20:00:18 -06:00
|
|
|
ensureSelectedItemUnequipped(count);
|
2013-05-11 18:38:27 +02:00
|
|
|
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count);
|
2014-08-16 17:18:13 +02:00
|
|
|
notifyContentChanged();
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::sellItem(MyGUI::Widget* sender, int count)
|
|
|
|
{
|
2016-01-18 20:00:18 -06:00
|
|
|
ensureSelectedItemUnequipped(count);
|
2013-05-11 18:38:27 +02:00
|
|
|
const ItemStack& item = mTradeModel->getItem(mSelectedItem);
|
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& sound = item.mBase.getClass().getUpSoundId(item.mBase);
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound(sound);
|
2013-05-11 18:38:27 +02:00
|
|
|
|
|
|
|
if (item.mType == ItemStack::Type_Barter)
|
|
|
|
{
|
|
|
|
// this was an item borrowed to us by the merchant
|
|
|
|
mTradeModel->returnItemBorrowedToUs(mSelectedItem, count);
|
2014-09-22 11:26:16 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count);
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// borrow item to the merchant
|
|
|
|
mTradeModel->borrowItemFromUs(mSelectedItem, count);
|
2014-09-22 11:26:16 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count);
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
mItemView->update();
|
2014-08-16 17:18:13 +02:00
|
|
|
notifyContentChanged();
|
2013-05-11 18:38:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::updateItemView()
|
|
|
|
{
|
2015-03-11 20:04:25 +01:00
|
|
|
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
2014-12-15 20:20:17 +01:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
mItemView->update();
|
2015-05-20 02:18:20 +02:00
|
|
|
|
|
|
|
dirtyPreview();
|
2012-05-17 21:56:16 +02:00
|
|
|
}
|
2012-05-12 21:28:04 +02:00
|
|
|
|
2017-09-22 17:10:53 +02:00
|
|
|
void InventoryWindow::onOpen()
|
2012-05-17 21:56:16 +02:00
|
|
|
{
|
2020-02-24 18:14:40 +00:00
|
|
|
// Reset the filter focus when opening the window
|
|
|
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
|
|
|
if (focus == mFilterEdit)
|
|
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr);
|
|
|
|
|
2017-04-19 18:28:49 +02:00
|
|
|
if (!mPtr.isEmpty())
|
|
|
|
{
|
|
|
|
updateEncumbranceBar();
|
|
|
|
mItemView->update();
|
|
|
|
notifyContentChanged();
|
|
|
|
}
|
2013-12-03 18:42:35 +01:00
|
|
|
adjustPanes();
|
2012-04-21 11:05:30 +02:00
|
|
|
}
|
|
|
|
|
2019-04-26 11:37:57 +04:00
|
|
|
void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
|
|
|
|
{
|
|
|
|
adjustPanes();
|
2023-04-12 00:33:36 +02:00
|
|
|
const WindowSettingValues settings = getModeSettings(mGuiMode);
|
2019-04-26 11:37:57 +04:00
|
|
|
|
2013-12-03 18:42:35 +01:00
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
2023-04-12 00:33:36 +02:00
|
|
|
|
|
|
|
settings.mRegular.mX.set(_sender->getPosition().left / static_cast<float>(viewSize.width));
|
|
|
|
settings.mRegular.mY.set(_sender->getPosition().top / static_cast<float>(viewSize.height));
|
|
|
|
settings.mRegular.mW.set(_sender->getSize().width / static_cast<float>(viewSize.width));
|
|
|
|
settings.mRegular.mH.set(_sender->getSize().height / static_cast<float>(viewSize.height));
|
|
|
|
settings.mIsMaximized.set(false);
|
2013-12-03 18:42:35 +01:00
|
|
|
|
2012-09-14 17:10:10 +02:00
|
|
|
if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize)
|
|
|
|
{
|
|
|
|
mLastXSize = mMainWidget->getSize().width;
|
|
|
|
mLastYSize = mMainWidget->getSize().height;
|
2015-05-20 02:18:20 +02:00
|
|
|
|
|
|
|
updatePreviewSize();
|
|
|
|
updateArmorRating();
|
2012-09-14 17:10:10 +02:00
|
|
|
}
|
2012-05-12 18:24:47 +02:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
void InventoryWindow::updateArmorRating()
|
|
|
|
{
|
|
|
|
mArmorRating->setCaptionWithReplacing(
|
|
|
|
"#{sArmor}: " + MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
|
|
|
|
if (mArmorRating->getTextSize().width > mArmorRating->getSize().width)
|
|
|
|
mArmorRating->setCaptionWithReplacing(
|
|
|
|
MyGUI::utility::toString(static_cast<int>(mPtr.getClass().getArmorRating(mPtr))));
|
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::updatePreviewSize()
|
|
|
|
{
|
2021-07-04 08:36:59 +00:00
|
|
|
const MyGUI::IntSize viewport = getPreviewViewportSize();
|
|
|
|
mPreview->setViewport(viewport.width, viewport.height);
|
2016-02-05 20:23:41 +01:00
|
|
|
mAvatarImage->getSubWidgetMain()->_setUVSet(
|
2021-07-04 08:36:59 +00:00
|
|
|
MyGUI::FloatRect(0.f, 0.f, viewport.width / float(mPreview->getTextureWidth()),
|
|
|
|
viewport.height / float(mPreview->getTextureHeight())));
|
2015-05-20 02:18:20 +02:00
|
|
|
}
|
|
|
|
|
2020-02-24 18:14:40 +00:00
|
|
|
void InventoryWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
|
|
|
|
{
|
|
|
|
mSortModel->setNameFilter(_sender->getCaption());
|
|
|
|
mItemView->update();
|
|
|
|
}
|
|
|
|
|
2012-05-12 21:44:33 +02:00
|
|
|
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
|
|
|
|
{
|
|
|
|
if (_sender == mFilterAll)
|
2013-05-11 18:38:27 +02:00
|
|
|
mSortModel->setCategory(SortFilterItemModel::Category_All);
|
2012-05-12 21:44:33 +02:00
|
|
|
else if (_sender == mFilterWeapon)
|
2013-05-11 18:38:27 +02:00
|
|
|
mSortModel->setCategory(SortFilterItemModel::Category_Weapon);
|
2012-05-12 21:44:33 +02:00
|
|
|
else if (_sender == mFilterApparel)
|
2013-05-11 18:38:27 +02:00
|
|
|
mSortModel->setCategory(SortFilterItemModel::Category_Apparel);
|
2012-05-12 21:44:33 +02:00
|
|
|
else if (_sender == mFilterMagic)
|
2013-05-11 18:38:27 +02:00
|
|
|
mSortModel->setCategory(SortFilterItemModel::Category_Magic);
|
2012-05-12 21:44:33 +02:00
|
|
|
else if (_sender == mFilterMisc)
|
2013-05-11 18:38:27 +02:00
|
|
|
mSortModel->setCategory(SortFilterItemModel::Category_Misc);
|
2012-05-12 22:00:15 +02:00
|
|
|
mFilterAll->setStateSelected(false);
|
|
|
|
mFilterWeapon->setStateSelected(false);
|
|
|
|
mFilterApparel->setStateSelected(false);
|
|
|
|
mFilterMagic->setStateSelected(false);
|
|
|
|
mFilterMisc->setStateSelected(false);
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
mItemView->update();
|
|
|
|
|
2014-09-13 04:07:40 +02:00
|
|
|
_sender->castType<MyGUI::Button>()->setStateSelected(true);
|
2012-05-12 21:44:33 +02:00
|
|
|
}
|
|
|
|
|
2012-05-12 22:44:12 +02:00
|
|
|
void InventoryWindow::onPinToggled()
|
|
|
|
{
|
2023-04-12 00:33:36 +02:00
|
|
|
Settings::windows().mInventoryPin.set(mPinned);
|
2017-04-10 10:18:00 +04:00
|
|
|
|
2013-04-10 00:32:05 -04:00
|
|
|
MWBase::Environment::get().getWindowManager()->setWeaponVisibility(!mPinned);
|
2012-05-12 22:44:12 +02:00
|
|
|
}
|
|
|
|
|
2014-08-04 17:03:47 +02:00
|
|
|
void InventoryWindow::onTitleDoubleClicked()
|
|
|
|
{
|
2019-04-26 11:37:57 +04:00
|
|
|
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
|
|
|
toggleMaximized();
|
|
|
|
else if (!mPinned)
|
2014-08-04 17:03:47 +02:00
|
|
|
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
|
|
|
|
}
|
|
|
|
|
2018-07-09 19:31:40 +04:00
|
|
|
void InventoryWindow::useItem(const MWWorld::Ptr& ptr, bool force)
|
2014-01-13 06:15:22 +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
|
|
|
const ESM::RefId& script = ptr.getClass().getScript(ptr);
|
2020-02-19 22:41:22 +03:00
|
|
|
if (!script.empty())
|
|
|
|
{
|
|
|
|
// Don't try to equip the item if PCSkipEquip is set to 1
|
|
|
|
if (ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 1)
|
|
|
|
{
|
|
|
|
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
|
|
|
|
}
|
2014-01-13 06:15:22 +01:00
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
2015-07-15 18:52:23 +02:00
|
|
|
|
|
|
|
// early-out for items that need to be equipped, but can't be equipped: we don't want to set OnPcEquip in that
|
|
|
|
// case
|
|
|
|
if (!ptr.getClass().getEquipmentSlots(ptr).first.empty())
|
|
|
|
{
|
2018-07-09 19:31:40 +04:00
|
|
|
if (ptr.getClass().hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
2015-07-15 18:52:23 +02:00
|
|
|
{
|
2018-07-09 19:31:40 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}");
|
2015-07-15 18:52:23 +02:00
|
|
|
updateItemView();
|
|
|
|
return;
|
|
|
|
}
|
2018-07-09 19:31:40 +04:00
|
|
|
|
|
|
|
if (!force)
|
|
|
|
{
|
2022-08-23 22:14:27 +02:00
|
|
|
auto canEquip = ptr.getClass().canBeEquipped(ptr, player);
|
2018-07-09 19:31:40 +04:00
|
|
|
|
|
|
|
if (canEquip.first == 0)
|
|
|
|
{
|
2020-02-19 22:41:22 +03:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second);
|
2018-07-09 19:31:40 +04:00
|
|
|
updateItemView();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-07-15 18:52:23 +02:00
|
|
|
}
|
|
|
|
|
2020-02-19 22:41:22 +03:00
|
|
|
// If the item has a script, set OnPCEquip or PCSkipEquip to 1
|
|
|
|
if (!script.empty())
|
2014-01-13 06:15:22 +01:00
|
|
|
{
|
2020-02-19 22:41:22 +03:00
|
|
|
// Ingredients, books and repair hammers must not have OnPCEquip set to 1 here
|
2021-10-11 11:46:21 +00:00
|
|
|
auto type = ptr.getType();
|
|
|
|
bool isBook = type == ESM::Book::sRecordId;
|
|
|
|
if (!isBook && type != ESM::Ingredient::sRecordId && type != ESM::Repair::sRecordId)
|
2020-02-19 22:41:22 +03:00
|
|
|
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
|
|
|
|
// Books must have PCSkipEquip set to 1 instead
|
|
|
|
else if (isBook)
|
|
|
|
ptr.getRefData().getLocals().setVarByInt(script, "pcskipequip", 1);
|
2014-01-13 06:15:22 +01:00
|
|
|
}
|
|
|
|
|
2022-04-06 17:06:55 +02:00
|
|
|
std::unique_ptr<MWWorld::Action> action = ptr.getClass().use(ptr, force);
|
2020-02-19 22:41:22 +03:00
|
|
|
action->execute(player);
|
2014-01-13 06:15:22 +01:00
|
|
|
|
2014-08-12 16:36:13 +02:00
|
|
|
if (isVisible())
|
|
|
|
{
|
|
|
|
mItemView->update();
|
2014-01-13 06:15:22 +01:00
|
|
|
|
2014-08-12 16:36:13 +02:00
|
|
|
notifyContentChanged();
|
|
|
|
}
|
|
|
|
// else: will be updated in open()
|
2014-01-13 06:15:22 +01:00
|
|
|
}
|
|
|
|
|
2012-05-15 18:05:53 +02:00
|
|
|
void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender)
|
|
|
|
{
|
|
|
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
|
|
|
{
|
2013-05-11 18:38:27 +02:00
|
|
|
MWWorld::Ptr ptr = mDragAndDrop->mItem.mBase;
|
2017-10-19 16:50:04 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
mDragAndDrop->finish();
|
2012-05-15 18:05:53 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
if (mDragAndDrop->mSourceModel != mTradeModel)
|
2012-05-15 18:05:53 +02:00
|
|
|
{
|
2014-05-15 04:41:31 +02:00
|
|
|
// Move item to the player's inventory
|
|
|
|
ptr = mDragAndDrop->mSourceModel->moveItem(
|
|
|
|
mDragAndDrop->mItem, mDragAndDrop->mDraggedCount, mTradeModel);
|
2012-05-16 16:08:55 +02:00
|
|
|
}
|
2017-10-19 17:17:14 +02:00
|
|
|
|
2023-06-28 09:32:15 +00:00
|
|
|
// Handles partial equipping
|
|
|
|
const std::pair<std::vector<int>, bool> slots = ptr.getClass().getEquipmentSlots(ptr);
|
|
|
|
if (!slots.first.empty() && slots.second)
|
|
|
|
{
|
|
|
|
int equippedStackableCount = 0;
|
|
|
|
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
|
|
|
MWWorld::ConstContainerStoreIterator slotIt = invStore.getSlot(slots.first.front());
|
|
|
|
|
|
|
|
// Get the count before useItem()
|
|
|
|
if (slotIt != invStore.end() && slotIt->getCellRef().getRefId() == ptr.getCellRef().getRefId())
|
|
|
|
equippedStackableCount = slotIt->getRefData().getCount();
|
|
|
|
|
|
|
|
useItem(ptr);
|
|
|
|
int unequipCount = ptr.getRefData().getCount() - mDragAndDrop->mDraggedCount - equippedStackableCount;
|
|
|
|
if (unequipCount > 0)
|
|
|
|
{
|
|
|
|
invStore.unequipItemQuantity(ptr, unequipCount);
|
|
|
|
updateItemView();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
useItem(ptr);
|
2017-10-19 16:50:04 +02:00
|
|
|
|
2017-10-19 17:17:14 +02:00
|
|
|
// If item is ingredient or potion don't stop drag and drop to simplify action of taking more than one 1
|
|
|
|
// item
|
2021-10-11 11:46:21 +00:00
|
|
|
if ((ptr.getType() == ESM::Potion::sRecordId || ptr.getType() == ESM::Ingredient::sRecordId)
|
2017-10-19 17:17:14 +02:00
|
|
|
&& mDragAndDrop->mDraggedCount > 1)
|
2017-10-19 16:50:04 +02:00
|
|
|
{
|
2017-10-20 01:10:17 +02:00
|
|
|
// Item can be provided from other window for example container.
|
|
|
|
// But after DragAndDrop::startDrag item automaticly always gets to player inventory.
|
|
|
|
mSelectedItem = getModel()->getIndex(mDragAndDrop->mItem);
|
|
|
|
dragItem(nullptr, mDragAndDrop->mDraggedCount - 1);
|
2017-10-19 16:50:04 +02:00
|
|
|
}
|
2012-05-15 18:05:53 +02:00
|
|
|
}
|
2012-09-14 14:34:18 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
MyGUI::IntPoint mousePos
|
|
|
|
= MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
|
2014-02-03 22:32:50 +01:00
|
|
|
MyGUI::IntPoint relPos = mousePos - mAvatarImage->getAbsolutePosition();
|
2012-09-15 00:57:29 +02:00
|
|
|
|
2015-05-20 03:35:52 +02:00
|
|
|
MWWorld::Ptr itemSelected = getAvatarSelectedItem(relPos.left, relPos.top);
|
2012-09-14 14:34:18 +02:00
|
|
|
if (itemSelected.isEmpty())
|
|
|
|
return;
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
for (size_t i = 0; i < mTradeModel->getItemCount(); ++i)
|
2012-09-14 14:34:18 +02:00
|
|
|
{
|
2013-05-11 18:38:27 +02:00
|
|
|
if (mTradeModel->getItem(i).mBase == itemSelected)
|
2012-09-14 14:34:18 +02:00
|
|
|
{
|
2017-10-19 17:17:14 +02:00
|
|
|
onItemSelectedFromSourceModel(i);
|
2012-09-14 14:34:18 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-05-11 18:38:27 +02:00
|
|
|
throw std::runtime_error("Can't find clicked item");
|
2012-09-14 14:34:18 +02:00
|
|
|
}
|
2012-05-15 18:05:53 +02:00
|
|
|
}
|
|
|
|
|
2012-09-15 00:57:29 +02:00
|
|
|
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
|
|
|
|
{
|
2021-07-04 08:36:59 +00:00
|
|
|
const osg::Vec2f viewport_coords = mapPreviewWindowToViewport(x, y);
|
|
|
|
int slot = mPreview->getSlotSelected(viewport_coords.x(), viewport_coords.y());
|
2012-09-15 00:57:29 +02:00
|
|
|
|
|
|
|
if (slot == -1)
|
|
|
|
return MWWorld::Ptr();
|
|
|
|
|
2014-05-22 20:37:22 +02:00
|
|
|
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
2013-08-08 16:05:26 -07:00
|
|
|
if (invStore.getSlot(slot) != invStore.end())
|
|
|
|
{
|
|
|
|
MWWorld::Ptr item = *invStore.getSlot(slot);
|
2016-09-24 18:01:31 +02:00
|
|
|
if (!item.getClass().showsInInventory(item))
|
2013-08-08 16:05:26 -07:00
|
|
|
return MWWorld::Ptr();
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MWWorld::Ptr();
|
2012-09-15 00:57:29 +02:00
|
|
|
}
|
|
|
|
|
2012-05-15 22:45:46 +02:00
|
|
|
void InventoryWindow::updateEncumbranceBar()
|
|
|
|
{
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
2012-05-15 22:45:46 +02:00
|
|
|
|
2014-05-22 20:37:22 +02:00
|
|
|
float capacity = player.getClass().getCapacity(player);
|
|
|
|
float encumbrance = player.getClass().getEncumbrance(player);
|
2014-08-24 19:15:02 +02:00
|
|
|
mTradeModel->adjustEncumbrance(encumbrance);
|
2018-02-24 15:13:14 +03:00
|
|
|
mEncumbranceBar->setValue(std::ceil(encumbrance), static_cast<int>(capacity));
|
2012-05-15 22:45:46 +02:00
|
|
|
}
|
|
|
|
|
2017-09-23 22:00:15 +02:00
|
|
|
void InventoryWindow::onFrame(float dt)
|
2012-05-15 22:45:46 +02:00
|
|
|
{
|
|
|
|
updateEncumbranceBar();
|
2018-08-27 09:37:08 +04:00
|
|
|
|
|
|
|
if (mPinned)
|
|
|
|
{
|
|
|
|
mUpdateTimer += dt;
|
|
|
|
if (0.1f < mUpdateTimer)
|
|
|
|
{
|
|
|
|
mUpdateTimer = 0;
|
|
|
|
|
|
|
|
// Update pinned inventory in-game
|
|
|
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
|
|
|
{
|
|
|
|
mItemView->update();
|
|
|
|
notifyContentChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-15 22:45:46 +02:00
|
|
|
}
|
2012-05-17 21:56:16 +02:00
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
void InventoryWindow::setTrading(bool trading)
|
2012-05-18 17:27:55 +02:00
|
|
|
{
|
2013-05-11 18:38:27 +02:00
|
|
|
mTrading = trading;
|
2012-05-18 17:27:55 +02:00
|
|
|
}
|
2012-05-29 12:35:03 +02:00
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
void InventoryWindow::dirtyPreview()
|
2013-04-03 00:27:29 +02:00
|
|
|
{
|
2015-05-20 02:18:20 +02:00
|
|
|
mPreview->update();
|
2014-08-12 16:36:13 +02:00
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
updateArmorRating();
|
2013-04-03 00:27:29 +02:00
|
|
|
}
|
|
|
|
|
2012-05-29 12:35:03 +02:00
|
|
|
void InventoryWindow::notifyContentChanged()
|
|
|
|
{
|
|
|
|
// update the spell window just in case new enchanted items were added to inventory
|
2015-03-11 20:04:25 +01:00
|
|
|
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
2012-05-29 18:33:01 +02:00
|
|
|
|
2014-08-15 01:13:38 +02:00
|
|
|
MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(MWMechanics::getPlayer());
|
|
|
|
|
2015-05-20 02:18:20 +02:00
|
|
|
dirtyPreview();
|
2012-06-02 14:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void InventoryWindow::pickUpObject(MWWorld::Ptr object)
|
|
|
|
{
|
2014-03-08 13:45:54 -05:00
|
|
|
// If the inventory is not yet enabled, don't pick anything up
|
|
|
|
if (!MWBase::Environment::get().getWindowManager()->isAllowed(GW_Inventory))
|
|
|
|
return;
|
2012-06-02 14:19:02 +02:00
|
|
|
// make sure the object is of a type that can be picked up
|
2021-10-11 11:46:21 +00:00
|
|
|
auto type = object.getType();
|
|
|
|
if ((type != ESM::Apparatus::sRecordId) && (type != ESM::Armor::sRecordId) && (type != ESM::Book::sRecordId)
|
|
|
|
&& (type != ESM::Clothing::sRecordId) && (type != ESM::Ingredient::sRecordId)
|
|
|
|
&& (type != ESM::Light::sRecordId) && (type != ESM::Miscellaneous::sRecordId)
|
|
|
|
&& (type != ESM::Lockpick::sRecordId) && (type != ESM::Probe::sRecordId) && (type != ESM::Repair::sRecordId)
|
|
|
|
&& (type != ESM::Weapon::sRecordId) && (type != ESM::Potion::sRecordId))
|
2012-06-02 14:19:02 +02:00
|
|
|
return;
|
2012-05-29 18:33:01 +02:00
|
|
|
|
2020-04-20 22:09:09 +03:00
|
|
|
// An object that can be picked up must have a tooltip.
|
|
|
|
if (!object.getClass().hasToolTip(object))
|
2012-07-05 17:13:23 +02:00
|
|
|
return;
|
|
|
|
|
2012-06-02 14:19:02 +02:00
|
|
|
int count = object.getRefData().getCount();
|
2018-08-22 22:30:46 +03:00
|
|
|
if (object.getClass().isGold(object))
|
|
|
|
count *= object.getClass().getValue(object);
|
2012-06-04 21:09:51 +02:00
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
2014-05-12 02:20:56 +02:00
|
|
|
MWBase::Environment::get().getWorld()->breakInvisibility(player);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2017-11-04 00:44:16 +00:00
|
|
|
if (!object.getRefData().activate())
|
|
|
|
return;
|
2014-05-12 02:20:56 +02:00
|
|
|
|
2021-07-21 07:46:02 +00:00
|
|
|
// Player must not be paralyzed, knocked down, or dead to pick up an item.
|
|
|
|
const MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats(player);
|
|
|
|
bool godmode = MWBase::Environment::get().getWorld()->getGodModeState();
|
|
|
|
if ((!godmode && playerStats.isParalyzed()) || playerStats.getKnockedDown() || playerStats.isDead())
|
|
|
|
return;
|
|
|
|
|
2015-05-08 02:22:39 +02:00
|
|
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, object, MWWorld::Ptr(), count);
|
|
|
|
|
2012-06-04 21:09:51 +02:00
|
|
|
// add to player inventory
|
|
|
|
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
2014-01-05 20:53:45 +01:00
|
|
|
MWWorld::Ptr newObject
|
2023-01-16 23:51:04 +01:00
|
|
|
= *player.getClass().getContainerStore(player).add(object, object.getRefData().getCount());
|
2017-10-31 18:16:40 +00:00
|
|
|
|
2012-06-04 21:09:51 +02:00
|
|
|
// remove from world
|
|
|
|
MWBase::Environment::get().getWorld()->deleteObject(object);
|
|
|
|
|
2013-05-11 18:38:27 +02:00
|
|
|
// get ModelIndex to the item
|
|
|
|
mTradeModel->update();
|
|
|
|
size_t i = 0;
|
|
|
|
for (; i < mTradeModel->getItemCount(); ++i)
|
|
|
|
{
|
|
|
|
if (mTradeModel->getItem(i).mBase == newObject)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == mTradeModel->getItemCount())
|
|
|
|
throw std::runtime_error("Added item not found");
|
|
|
|
mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count);
|
2014-01-07 19:49:16 +01:00
|
|
|
|
2015-03-11 20:04:25 +01:00
|
|
|
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
2012-05-29 12:35:03 +02:00
|
|
|
}
|
2014-12-15 15:23:03 +01:00
|
|
|
|
|
|
|
void InventoryWindow::cycle(bool next)
|
|
|
|
{
|
2017-08-18 19:24:34 +04:00
|
|
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
|
|
|
|
|
|
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
2020-10-09 20:34:36 +03:00
|
|
|
bool godmode = MWBase::Environment::get().getWorld()->getGodModeState();
|
|
|
|
if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
|
2017-08-18 19:24:34 +04:00
|
|
|
return;
|
|
|
|
|
2014-12-15 17:38:32 +01:00
|
|
|
ItemModel::ModelIndex selected = -1;
|
2014-12-15 15:23:03 +01:00
|
|
|
// not using mSortFilterModel as we only need sorting, not filtering
|
2022-08-31 18:49:50 +02:00
|
|
|
SortFilterItemModel model(std::make_unique<InventoryItemModel>(player));
|
2014-12-15 15:23:03 +01:00
|
|
|
model.setSortByType(false);
|
|
|
|
model.update();
|
|
|
|
if (model.getItemCount() == 0)
|
|
|
|
return;
|
2014-12-15 17:38:32 +01:00
|
|
|
|
2014-12-15 15:23:03 +01:00
|
|
|
for (ItemModel::ModelIndex i = 0; i < int(model.getItemCount()); ++i)
|
|
|
|
{
|
|
|
|
MWWorld::Ptr item = model.getItem(i).mBase;
|
|
|
|
if (model.getItem(i).mType & ItemStack::Type_Equipped && isRightHandWeapon(item))
|
|
|
|
selected = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int incr = next ? 1 : -1;
|
|
|
|
bool found = false;
|
2023-02-20 23:18:05 +01:00
|
|
|
ESM::RefId lastId;
|
2014-12-15 17:38:32 +01:00
|
|
|
if (selected != -1)
|
2023-02-20 23:18:05 +01:00
|
|
|
lastId = model.getItem(selected).mBase.getCellRef().getRefId();
|
2014-12-15 15:23:03 +01:00
|
|
|
ItemModel::ModelIndex cycled = selected;
|
2023-05-21 18:14:12 +02:00
|
|
|
for (size_t i = 0; i < model.getItemCount(); ++i)
|
2014-12-15 15:23:03 +01:00
|
|
|
{
|
|
|
|
cycled += incr;
|
|
|
|
cycled = (cycled + model.getItemCount()) % model.getItemCount();
|
|
|
|
|
|
|
|
MWWorld::Ptr item = model.getItem(cycled).mBase;
|
|
|
|
|
2014-12-15 17:38:32 +01:00
|
|
|
// skip different stacks of the same item, or we will get stuck as stacking/unstacking them may change their
|
|
|
|
// relative ordering
|
2023-02-20 23:18:05 +01:00
|
|
|
if (lastId == item.getCellRef().getRefId())
|
2014-12-15 17:38:32 +01:00
|
|
|
continue;
|
|
|
|
|
2023-02-20 23:18:05 +01:00
|
|
|
lastId = item.getCellRef().getRefId();
|
2014-12-15 17:38:32 +01:00
|
|
|
|
2021-10-11 11:46:21 +00:00
|
|
|
if (item.getClass().getType() == ESM::Weapon::sRecordId && isRightHandWeapon(item)
|
2017-09-17 17:04:30 +04:00
|
|
|
&& item.getClass().canBeEquipped(item, player).first)
|
2015-03-02 17:25:26 +01:00
|
|
|
{
|
2014-12-15 17:38:32 +01:00
|
|
|
found = true;
|
2015-03-02 17:25:26 +01:00
|
|
|
break;
|
|
|
|
}
|
2014-12-15 15:23:03 +01:00
|
|
|
}
|
|
|
|
|
2017-10-30 18:05:45 +01:00
|
|
|
if (!found || selected == cycled)
|
2015-03-02 17:25:26 +01:00
|
|
|
return;
|
|
|
|
|
2014-12-15 15:23:03 +01:00
|
|
|
useItem(model.getItem(cycled).mBase);
|
|
|
|
}
|
2015-01-10 02:50:43 +01:00
|
|
|
|
|
|
|
void InventoryWindow::rebuildAvatar()
|
|
|
|
{
|
|
|
|
mPreview->rebuild();
|
|
|
|
}
|
2021-07-04 08:36:59 +00:00
|
|
|
|
|
|
|
MyGUI::IntSize InventoryWindow::getPreviewViewportSize() const
|
|
|
|
{
|
|
|
|
const MyGUI::IntSize previewWindowSize = mAvatarImage->getSize();
|
|
|
|
const float scale = MWBase::Environment::get().getWindowManager()->getScalingFactor();
|
|
|
|
|
|
|
|
return MyGUI::IntSize(std::min<int>(mPreview->getTextureWidth(), previewWindowSize.width * scale),
|
|
|
|
std::min<int>(mPreview->getTextureHeight(), previewWindowSize.height * scale));
|
|
|
|
}
|
|
|
|
|
|
|
|
osg::Vec2f InventoryWindow::mapPreviewWindowToViewport(int x, int y) const
|
|
|
|
{
|
|
|
|
const MyGUI::IntSize previewWindowSize = mAvatarImage->getSize();
|
|
|
|
const float normalisedX = x / std::max<float>(1.0f, previewWindowSize.width);
|
|
|
|
const float normalisedY = y / std::max<float>(1.0f, previewWindowSize.height);
|
|
|
|
|
|
|
|
const MyGUI::IntSize viewport = getPreviewViewportSize();
|
|
|
|
return osg::Vec2f(normalisedX * float(viewport.width - 1), (1.0 - normalisedY) * float(viewport.height - 1));
|
|
|
|
}
|
2012-04-22 21:06:08 +02:00
|
|
|
}
|