1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-12 19:13:07 +00:00

Merge branch 'quick_item_transfer' into 'master'

Support quick item transfer (#2522)

Closes #2522

See merge request OpenMW/openmw!4659
This commit is contained in:
Alexei Kotov 2025-07-13 12:33:56 +03:00
commit 79c689784b
23 changed files with 365 additions and 150 deletions

View file

@ -44,7 +44,7 @@ add_openmw_dir (mwgui
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher
postprocessorhud settings
postprocessorhud settings worlditemmodel itemtransfer
)
add_openmw_dir (mwdialogue

View file

@ -14,6 +14,7 @@
#include "companionitemmodel.hpp"
#include "countdialog.hpp"
#include "draganddrop.hpp"
#include "itemtransfer.hpp"
#include "itemview.hpp"
#include "messagebox.hpp"
#include "sortfilteritemmodel.hpp"
@ -38,13 +39,14 @@ namespace
namespace MWGui
{
CompanionWindow::CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager)
CompanionWindow::CompanionWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer, MessageBoxManager* manager)
: WindowBase("openmw_companion_window.layout")
, mSortModel(nullptr)
, mModel(nullptr)
, mSelectedItem(-1)
, mUpdateNextFrame(false)
, mDragAndDrop(dragAndDrop)
, mDragAndDrop(&dragAndDrop)
, mItemTransfer(&itemTransfer)
, mMessageBoxManager(manager)
{
getWidget(mCloseButton, "CloseButton");
@ -94,8 +96,14 @@ namespace MWGui
name += MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, "#{sTake}", count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem);
if (MyGUI::InputManager::getInstance().isAltPressed())
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::transferItem);
else
dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem);
}
else if (MyGUI::InputManager::getInstance().isAltPressed())
transferItem(nullptr, count);
else
dragItem(nullptr, count);
}
@ -106,11 +114,16 @@ namespace MWGui
mItemView->update();
}
void CompanionWindow::dragItem(MyGUI::Widget* sender, int count)
void CompanionWindow::dragItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
}
void CompanionWindow::transferItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
mItemTransfer->apply(mModel->getItem(mSelectedItem), count, *mItemView);
}
void CompanionWindow::onBackgroundSelected()
{
if (mDragAndDrop->mIsOnDragAndDrop)
@ -220,4 +233,14 @@ namespace MWGui
{
mUpdateNextFrame = true;
}
void CompanionWindow::onOpen()
{
mItemTransfer->addTarget(*mItemView);
}
void CompanionWindow::onClose()
{
mItemTransfer->removeTarget(*mItemView);
}
}

View file

@ -6,6 +6,8 @@
#include "../mwworld/containerstore.hpp"
#include <components/misc/notnullptr.hpp>
namespace MWGui
{
namespace Widgets
@ -18,11 +20,12 @@ namespace MWGui
class DragAndDrop;
class SortFilterItemModel;
class CompanionItemModel;
class ItemTransfer;
class CompanionWindow : public WindowBase, public ReferenceInterface, public MWWorld::ContainerStoreListener
{
public:
CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager);
explicit CompanionWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer, MessageBoxManager* manager);
bool exit() override;
@ -44,7 +47,8 @@ namespace MWGui
int mSelectedItem;
bool mUpdateNextFrame;
DragAndDrop* mDragAndDrop;
Misc::NotNullPtr<DragAndDrop> mDragAndDrop;
Misc::NotNullPtr<ItemTransfer> mItemTransfer;
MyGUI::Button* mCloseButton;
MyGUI::EditBox* mFilterEdit;
@ -55,7 +59,8 @@ namespace MWGui
void onItemSelected(int index);
void onNameFilterChanged(MyGUI::EditBox* _sender);
void onBackgroundSelected();
void dragItem(MyGUI::Widget* sender, int count);
void dragItem(MyGUI::Widget* sender, std::size_t count);
void transferItem(MyGUI::Widget* sender, std::size_t count);
void onMessageBoxButtonClicked(int button);
@ -64,6 +69,10 @@ namespace MWGui
void onCloseButtonClicked(MyGUI::Widget* _sender);
void onReferenceUnavailable() override;
void onOpen() override;
void onClose() override;
};
}

View file

@ -18,12 +18,12 @@
#include "../mwscript/interpretercontext.hpp"
#include "countdialog.hpp"
#include "inventorywindow.hpp"
#include "containeritemmodel.hpp"
#include "countdialog.hpp"
#include "draganddrop.hpp"
#include "inventoryitemmodel.hpp"
#include "inventorywindow.hpp"
#include "itemtransfer.hpp"
#include "itemview.hpp"
#include "pickpocketitemmodel.hpp"
#include "sortfilteritemmodel.hpp"
@ -32,9 +32,10 @@
namespace MWGui
{
ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
ContainerWindow::ContainerWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer)
: WindowBase("openmw_container_window.layout")
, mDragAndDrop(dragAndDrop)
, mDragAndDrop(&dragAndDrop)
, mItemTransfer(&itemTransfer)
, mSortModel(nullptr)
, mModel(nullptr)
, mSelectedItem(-1)
@ -89,26 +90,47 @@ namespace MWGui
name += MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, "#{sTake}", count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem);
if (MyGUI::InputManager::getInstance().isAltPressed())
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::transferItem);
else
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem);
}
else if (MyGUI::InputManager::getInstance().isAltPressed())
transferItem(nullptr, count);
else
dragItem(nullptr, count);
}
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
void ContainerWindow::dragItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
if (!mModel)
if (mModel == nullptr)
return;
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
const ItemStack item = mModel->getItem(mSelectedItem);
if (!mModel->onTakeItem(item.mBase, count))
return;
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
}
void ContainerWindow::transferItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
if (mModel == nullptr)
return;
const ItemStack item = mModel->getItem(mSelectedItem);
if (!mModel->onTakeItem(item.mBase, count))
return;
mItemTransfer->apply(item, count, *mItemView);
}
void ContainerWindow::dropItem()
{
if (!mModel)
if (mModel == nullptr)
return;
bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount);
@ -173,10 +195,13 @@ namespace MWGui
mSortModel = nullptr;
}
void ContainerWindow::onOpen()
{
mItemTransfer->addTarget(*mItemView);
}
void ContainerWindow::onClose()
{
WindowBase::onClose();
// Make sure the window was actually closed and not temporarily hidden.
if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Container))
return;
@ -187,6 +212,8 @@ namespace MWGui
if (!mPtr.isEmpty())
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr);
resetReference();
mItemTransfer->removeTarget(*mItemView);
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
@ -234,9 +261,9 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->playSound(sound);
}
const ItemStack& item = mModel->getItem(i);
const ItemStack item = mModel->getItem(i);
if (!onTakeItem(item, item.mCount))
if (!mModel->onTakeItem(item.mBase, item.mCount))
break;
mModel->moveItem(item, item.mCount, playerModel);
@ -313,11 +340,6 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
bool ContainerWindow::onTakeItem(const ItemStack& item, int count)
{
return mModel->onTakeItem(item.mBase, count);
}
void ContainerWindow::onDeleteCustomData(const MWWorld::Ptr& ptr)
{
if (mModel && mModel->usesContainer(ptr))

View file

@ -1,10 +1,11 @@
#ifndef MGUI_CONTAINER_H
#define MGUI_CONTAINER_H
#include "itemmodel.hpp"
#include "referenceinterface.hpp"
#include "windowbase.hpp"
#include "itemmodel.hpp"
#include <components/misc/notnullptr.hpp>
#include "../mwworld/containerstore.hpp"
@ -19,17 +20,19 @@ namespace MWGui
class ContainerWindow;
class ItemView;
class SortFilterItemModel;
}
class ItemTransfer;
namespace MWGui
{
class ContainerWindow : public WindowBase, public ReferenceInterface, public MWWorld::ContainerStoreListener
{
public:
ContainerWindow(DragAndDrop* dragAndDrop);
explicit ContainerWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer);
void setPtr(const MWWorld::Ptr& container) override;
void onOpen() override;
void onClose() override;
void clear() override { resetReference(); }
void onFrame(float dt) override;
@ -46,7 +49,8 @@ namespace MWGui
std::string_view getWindowIdForLua() const override { return "Container"; }
private:
DragAndDrop* mDragAndDrop;
Misc::NotNullPtr<DragAndDrop> mDragAndDrop;
Misc::NotNullPtr<ItemTransfer> mItemTransfer;
MWGui::ItemView* mItemView;
SortFilterItemModel* mSortModel;
@ -60,15 +64,13 @@ namespace MWGui
void onItemSelected(int index);
void onBackgroundSelected();
void dragItem(MyGUI::Widget* sender, int count);
void dragItem(MyGUI::Widget* sender, std::size_t count);
void transferItem(MyGUI::Widget* sender, std::size_t count);
void dropItem();
void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
/// @return is taking the item allowed?
bool onTakeItem(const ItemStack& item, int count);
void onReferenceUnavailable() override;
};
}

View file

@ -16,12 +16,10 @@ namespace MWGui
CountDialog();
void openCountDialog(const std::string& item, const std::string& message, const int maxCount);
typedef MyGUI::delegates::MultiDelegate<MyGUI::Widget*, int> EventHandle_WidgetInt;
/** Event : Ok button was clicked.\n
signature : void method(MyGUI::Widget* _sender, int _count)\n
signature : void method(MyGUI::Widget* sender, std::size_t count)\n
*/
EventHandle_WidgetInt eventOkClicked;
MyGUI::delegates::MultiDelegate<MyGUI::Widget*, std::size_t> eventOkClicked;
private:
MyGUI::ScrollBar* mSlider;

View file

@ -27,7 +27,7 @@ namespace MWGui
}
void DragAndDrop::startDrag(
int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count)
int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, std::size_t count)
{
mItem = sourceModel->getItem(index);
mDraggedCount = count;
@ -125,18 +125,18 @@ namespace MWGui
void DragAndDrop::update()
{
if (mIsOnDragAndDrop)
{
int count = mItem.mBase.getCellRef().getCount();
if (count < mDraggedCount)
{
mItem.mCount = count;
mDraggedCount = count;
mDraggedWidget->setCount(mDraggedCount);
mSourceSortModel->clearDragItems();
mSourceSortModel->addDragItem(mItem.mBase, mDraggedCount);
}
}
if (!mIsOnDragAndDrop)
return;
const unsigned count = mItem.mBase.getCellRef().getAbsCount();
if (count >= mDraggedCount)
return;
mItem.mCount = count;
mDraggedCount = count;
mDraggedWidget->setCount(mDraggedCount);
mSourceSortModel->clearDragItems();
mSourceSortModel->addDragItem(mItem.mBase, mDraggedCount);
}
void DragAndDrop::onFrame()

View file

@ -4,6 +4,8 @@
#include "itemmodel.hpp"
#include "itemwidget.hpp"
#include <cstddef>
namespace MyGUI
{
class Widget;
@ -24,12 +26,12 @@ namespace MWGui
ItemView* mSourceView;
SortFilterItemModel* mSourceSortModel;
ItemStack mItem;
int mDraggedCount;
std::size_t mDraggedCount;
DragAndDrop();
void startDrag(
int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count);
int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, std::size_t count);
void drop(ItemModel* targetModel, ItemView* targetView);
void update();
void onFrame();

View file

@ -25,67 +25,12 @@
#include "draganddrop.hpp"
#include "inventorywindow.hpp"
#include "itemmodel.hpp"
#include "spellicons.hpp"
#include "itemwidget.hpp"
#include "spellicons.hpp"
#include "worlditemmodel.hpp"
namespace MWGui
{
/**
* Makes it possible to use ItemModel::moveItem to move an item from an inventory to the world.
*/
class WorldItemModel : public ItemModel
{
public:
WorldItemModel(float left, float top)
: mLeft(left)
, mTop(top)
{
}
virtual ~WorldItemModel() override {}
MWWorld::Ptr dropItemImpl(const ItemStack& item, size_t count, bool copy)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr dropped;
if (world->canPlaceObject(mLeft, mTop))
dropped = world->placeObject(item.mBase, mLeft, mTop, count, copy);
else
dropped = world->dropObjectOnGround(world->getPlayerPtr(), item.mBase, count, copy);
dropped.getCellRef().setOwner(ESM::RefId());
return dropped;
}
MWWorld::Ptr addItem(const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override
{
return dropItemImpl(item, count, false);
}
MWWorld::Ptr copyItem(const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override
{
return dropItemImpl(item, count, true);
}
void removeItem(const ItemStack& item, size_t count) override
{
throw std::runtime_error("removeItem not implemented");
}
ModelIndex getIndex(const ItemStack& item) override { throw std::runtime_error("getIndex not implemented"); }
void update() override {}
size_t getItemCount() override { return 0; }
ItemStack getItem(ModelIndex index) override { throw std::runtime_error("getItem not implemented"); }
bool usesContainer(const MWWorld::Ptr&) override { return false; }
private:
// Where to drop the item
float mLeft;
float mTop;
};
HUD::HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
: WindowBase("openmw_hud.layout")
, LocalMapBase(customMarkers, localMapRender, Settings::map().mLocalMapHudFogOfWar)
@ -251,16 +196,14 @@ namespace MWGui
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
if (mDragAndDrop->mIsOnDragAndDrop)
{
const MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
const MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
const float cursorX = cursorPosition.left / static_cast<float>(viewSize.width);
const float cursorY = cursorPosition.top / static_cast<float>(viewSize.height);
// drop item into the gameworld
MWBase::Environment::get().getWorld()->breakInvisibility(MWMechanics::getPlayer());
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
float mouseX = cursorPosition.left / float(viewSize.width);
float mouseY = cursorPosition.top / float(viewSize.height);
WorldItemModel drop(mouseX, mouseY);
mDragAndDrop->drop(&drop, nullptr);
WorldItemModel worldItemModel(cursorX, cursorY);
mDragAndDrop->drop(&worldItemModel, nullptr);
winMgr->changePointer("arrow");
}

View file

@ -34,6 +34,7 @@
#include "countdialog.hpp"
#include "draganddrop.hpp"
#include "inventoryitemmodel.hpp"
#include "itemtransfer.hpp"
#include "itemview.hpp"
#include "settings.hpp"
#include "sortfilteritemmodel.hpp"
@ -74,10 +75,11 @@ namespace MWGui
}
}
InventoryWindow::InventoryWindow(
DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem)
InventoryWindow::InventoryWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer, osg::Group* parent,
Resource::ResourceSystem* resourceSystem)
: WindowPinnableBase("openmw_inventory_window.layout")
, mDragAndDrop(dragAndDrop)
, mDragAndDrop(&dragAndDrop)
, mItemTransfer(&itemTransfer)
, mSelectedItem(-1)
, mSortModel(nullptr)
, mTradeModel(nullptr)
@ -312,17 +314,24 @@ namespace MWGui
name += MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, message, count);
dialog->eventOkClicked.clear();
if (mTrading)
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem);
else if (MyGUI::InputManager::getInstance().isAltPressed())
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::transferItem);
else
dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::dragItem);
mSelectedItem = index;
}
else
{
mSelectedItem = index;
if (mTrading)
sellItem(nullptr, count);
else if (MyGUI::InputManager::getInstance().isAltPressed())
transferItem(nullptr, count);
else
dragItem(nullptr, count);
}
@ -361,14 +370,21 @@ namespace MWGui
}
}
void InventoryWindow::dragItem(MyGUI::Widget* sender, int count)
void InventoryWindow::dragItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
ensureSelectedItemUnequipped(count);
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count);
notifyContentChanged();
}
void InventoryWindow::sellItem(MyGUI::Widget* sender, int count)
void InventoryWindow::transferItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
ensureSelectedItemUnequipped(count);
mItemTransfer->apply(mTradeModel->getItem(mSelectedItem), count, *mItemView);
notifyContentChanged();
}
void InventoryWindow::sellItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
ensureSelectedItemUnequipped(count);
const ItemStack& item = mTradeModel->getItem(mSelectedItem);
@ -415,6 +431,13 @@ namespace MWGui
notifyContentChanged();
}
adjustPanes();
mItemTransfer->addTarget(*mItemView);
}
void InventoryWindow::onClose()
{
mItemTransfer->removeTarget(*mItemView);
}
void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
@ -776,7 +799,16 @@ namespace MWGui
if (mDragAndDrop->mIsOnDragAndDrop)
mDragAndDrop->finish();
mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count);
if (MyGUI::InputManager::getInstance().isAltPressed())
{
const MWWorld::Ptr item = mTradeModel->getItem(i).mBase;
MWBase::Environment::get().getWindowManager()->playSound(item.getClass().getDownSoundId(item));
mItemView->update();
}
else
{
mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count);
}
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
}

View file

@ -8,6 +8,8 @@
#include "../mwworld/containerstore.hpp"
#include "../mwworld/ptr.hpp"
#include <components/misc/notnullptr.hpp>
namespace osg
{
class Group;
@ -30,14 +32,18 @@ namespace MWGui
class TradeItemModel;
class DragAndDrop;
class ItemModel;
class ItemTransfer;
class InventoryWindow : public WindowPinnableBase, public MWWorld::ContainerStoreListener
{
public:
InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem);
explicit InventoryWindow(DragAndDrop& dragAndDrop, ItemTransfer& itemTransfer, osg::Group* parent,
Resource::ResourceSystem* resourceSystem);
void onOpen() override;
void onClose() override;
/// start trading, disables item drag&drop
void setTrading(bool trading);
@ -75,7 +81,8 @@ namespace MWGui
void onTitleDoubleClicked() override;
private:
DragAndDrop* mDragAndDrop;
Misc::NotNullPtr<DragAndDrop> mDragAndDrop;
Misc::NotNullPtr<ItemTransfer> mItemTransfer;
int mSelectedItem;
std::optional<int> mEquippedStackableCount;
@ -120,8 +127,9 @@ namespace MWGui
void onBackgroundSelected();
void sellItem(MyGUI::Widget* sender, int count);
void dragItem(MyGUI::Widget* sender, int count);
void sellItem(MyGUI::Widget* sender, std::size_t count);
void dragItem(MyGUI::Widget* sender, std::size_t count);
void transferItem(MyGUI::Widget* sender, std::size_t count);
void onWindowResize(MyGUI::Window* _sender);
void onFilterChanged(MyGUI::Widget* _sender);

View file

@ -0,0 +1,78 @@
#ifndef OPENMW_APPS_OPENMW_MWGUI_ITEMTRANSFER_H
#define OPENMW_APPS_OPENMW_MWGUI_ITEMTRANSFER_H
#include "inventorywindow.hpp"
#include "itemmodel.hpp"
#include "itemview.hpp"
#include "windowmanagerimp.hpp"
#include "worlditemmodel.hpp"
#include <apps/openmw/mwbase/windowmanager.hpp>
#include <apps/openmw/mwworld/class.hpp>
#include <components/misc/notnullptr.hpp>
#include <unordered_set>
namespace MWGui
{
class ItemTransfer
{
public:
explicit ItemTransfer(WindowManager& windowManager)
: mWindowManager(&windowManager)
{
}
void addTarget(ItemView& view) { mTargets.insert(&view); }
void removeTarget(ItemView& view) { mTargets.erase(&view); }
void apply(const ItemStack& item, std::size_t count, ItemView& sourceView)
{
if (item.mFlags & ItemStack::Flag_Bound)
{
mWindowManager->messageBox("#{sBarterDialog12}");
return;
}
ItemView* targetView = nullptr;
for (ItemView* const view : mTargets)
{
if (view == &sourceView)
continue;
if (targetView != nullptr)
{
mWindowManager->messageBox("#{sContentsMessage2}");
return;
}
targetView = view;
}
WorldItemModel worldItemModel(0.5f, 0.5f);
ItemModel* const targetModel = targetView == nullptr ? &worldItemModel : targetView->getModel();
if (!targetModel->onDropItem(item.mBase, count))
return;
sourceView.getModel()->moveItem(item, count, targetModel);
if (targetView != nullptr)
targetView->update();
sourceView.update();
mWindowManager->getInventoryWindow()->updateItemView();
mWindowManager->playSound(item.mBase.getClass().getDownSoundId(item.mBase));
}
private:
Misc::NotNullPtr<WindowManager> mWindowManager;
std::unordered_set<ItemView*> mTargets;
};
}
#endif

View file

@ -17,6 +17,8 @@ namespace MWGui
/// Register needed components with MyGUI's factory manager
static void registerComponents();
ItemModel* getModel() { return mModel.get(); }
/// Takes ownership of \a model
void setModel(std::unique_ptr<ItemModel> model);

View file

@ -292,7 +292,7 @@ namespace MWGui
}
}
void TradeWindow::sellItem(MyGUI::Widget* sender, int count)
void TradeWindow::sellItem(MyGUI::Widget* /*sender*/, std::size_t count)
{
const ItemStack& item = mTradeModel->getItem(mItemToSell);
const ESM::RefId& sound = item.mBase.getClass().getUpSoundId(item.mBase);

View file

@ -95,7 +95,7 @@ namespace MWGui
void updateOffer();
void onItemSelected(int index);
void sellItem(MyGUI::Widget* sender, int count);
void sellItem(MyGUI::Widget* sender, std::size_t count);
void borrowItem(int index, size_t count);
void returnItem(int index, size_t count);

View file

@ -93,6 +93,7 @@
#include "hud.hpp"
#include "inventorywindow.hpp"
#include "itemchargeview.hpp"
#include "itemtransfer.hpp"
#include "itemview.hpp"
#include "itemwidget.hpp"
#include "jailscreen.hpp"
@ -312,6 +313,7 @@ namespace MWGui
mTextColours.loadColours();
mDragAndDrop = std::make_unique<DragAndDrop>();
mItemTransfer = std::make_unique<ItemTransfer>(*this);
auto recharge = std::make_unique<Recharge>();
mGuiModeStates[GM_Recharge] = GuiModeState(recharge.get());
@ -334,7 +336,7 @@ namespace MWGui
trackWindow(mStatsWindow, makeStatsWindowSettingValues());
auto inventoryWindow = std::make_unique<InventoryWindow>(
mDragAndDrop.get(), mViewer->getSceneData()->asGroup(), mResourceSystem);
*mDragAndDrop, *mItemTransfer, mViewer->getSceneData()->asGroup(), mResourceSystem);
mInventoryWindow = inventoryWindow.get();
mWindows.push_back(std::move(inventoryWindow));
@ -381,7 +383,7 @@ namespace MWGui
mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow);
mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete);
auto containerWindow = std::make_unique<ContainerWindow>(mDragAndDrop.get());
auto containerWindow = std::make_unique<ContainerWindow>(*mDragAndDrop, *mItemTransfer);
mContainerWindow = containerWindow.get();
mWindows.push_back(std::move(containerWindow));
trackWindow(mContainerWindow, makeContainerWindowSettingValues());
@ -457,7 +459,8 @@ namespace MWGui
mSoulgemDialog = std::make_unique<SoulgemDialog>(mMessageBoxManager.get());
auto companionWindow = std::make_unique<CompanionWindow>(mDragAndDrop.get(), mMessageBoxManager.get());
auto companionWindow
= std::make_unique<CompanionWindow>(*mDragAndDrop, *mItemTransfer, mMessageBoxManager.get());
trackWindow(companionWindow.get(), makeCompanionWindowSettingValues());
mGuiModeStates[GM_Companion] = GuiModeState({ mInventoryWindow, companionWindow.get() });
mWindows.push_back(std::move(companionWindow));

View file

@ -8,7 +8,6 @@
**/
#include <memory>
#include <stack>
#include <vector>
#include <osg/ref_ptr>
@ -118,6 +117,7 @@ namespace MWGui
class PostProcessorHud;
class JailScreen;
class KeyboardNavigation;
class ItemTransfer;
class WindowManager : public MWBase::WindowManager
{
@ -433,6 +433,7 @@ namespace MWGui
Console* mConsole;
DialogueWindow* mDialogueWindow;
std::unique_ptr<DragAndDrop> mDragAndDrop;
std::unique_ptr<ItemTransfer> mItemTransfer;
InventoryWindow* mInventoryWindow;
ScrollWindow* mScrollWindow;
BookWindow* mBookWindow;

View file

@ -0,0 +1,82 @@
#ifndef OPENMW_APPS_OPENMW_MWGUI_WORLDITEMMODEL_H
#define OPENMW_APPS_OPENMW_MWGUI_WORLDITEMMODEL_H
#include "itemmodel.hpp"
#include <apps/openmw/mwbase/environment.hpp>
#include <apps/openmw/mwbase/world.hpp>
#include <components/esm/refid.hpp>
#include <MyGUI_InputManager.h>
#include <MyGUI_RenderManager.h>
#include <stdexcept>
namespace MWGui
{
// Makes it possible to use ItemModel::moveItem to move an item from an inventory to the world.
class WorldItemModel : public ItemModel
{
public:
explicit WorldItemModel(float cursorX, float cursorY)
: mCursorX(cursorX)
, mCursorY(cursorY)
{
}
MWWorld::Ptr dropItemImpl(const ItemStack& item, size_t count, bool copy)
{
MWBase::World& world = *MWBase::Environment::get().getWorld();
const MWWorld::Ptr player = world.getPlayerPtr();
world.breakInvisibility(player);
const MWWorld::Ptr dropped = world.canPlaceObject(mCursorX, mCursorY)
? world.placeObject(item.mBase, mCursorX, mCursorY, count, copy)
: world.dropObjectOnGround(player, item.mBase, count, copy);
dropped.getCellRef().setOwner(ESM::RefId());
return dropped;
}
MWWorld::Ptr addItem(const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override
{
return dropItemImpl(item, count, false);
}
MWWorld::Ptr copyItem(const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override
{
return dropItemImpl(item, count, true);
}
void removeItem(const ItemStack& /*item*/, size_t /*count*/) override
{
throw std::runtime_error("WorldItemModel::removeItem is not implemented");
}
ModelIndex getIndex(const ItemStack& /*item*/) override
{
throw std::runtime_error("WorldItemModel::getIndex is not implemented");
}
void update() override {}
size_t getItemCount() override { return 0; }
ItemStack getItem(ModelIndex /*index*/) override
{
throw std::runtime_error("WorldItemModel::getItem is not implemented");
}
bool usesContainer(const MWWorld::Ptr&) override { return false; }
private:
float mCursorX;
float mCursorY;
};
}
#endif

View file

@ -244,6 +244,18 @@ namespace MWWorld
return std::abs(count);
return count;
}
unsigned getAbsCount() const
{
struct Visitor
{
int operator()(const ESM::CellRef& ref) { return ref.mCount; }
int operator()(const ESM4::Reference& ref) { return ref.mCount; }
int operator()(const ESM4::ActorCharacter& ref) { return ref.mCount; }
};
return static_cast<unsigned>(std::abs(std::visit(Visitor(), mCellRef.mVariant)));
}
void setCount(int value);
// Write the content of this CellRef into the given ObjectState

View file

@ -10,8 +10,6 @@
#include <MyGUI_Colour.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace Settings