diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e3629d6f27..4dc2fd1fd1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -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 diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 95dbc8ae22..52fc4cc4ce 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -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); } @@ -111,6 +119,11 @@ namespace MWGui 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); + } } diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 8ecefa6931..5e78d17334 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -6,6 +6,8 @@ #include "../mwworld/containerstore.hpp" +#include + 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 mDragAndDrop; + Misc::NotNullPtr mItemTransfer; MyGUI::Button* mCloseButton; MyGUI::EditBox* mFilterEdit; @@ -56,6 +60,7 @@ namespace MWGui void onNameFilterChanged(MyGUI::EditBox* _sender); void onBackgroundSelected(); 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; }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 28ec1b5060..937bab0851 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -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,15 +90,21 @@ 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*/, std::size_t count) { - if (!mModel) + if (mModel == nullptr) return; const ItemStack item = mModel->getItem(mSelectedItem); @@ -108,9 +115,22 @@ namespace MWGui 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); @@ -175,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; @@ -189,6 +212,8 @@ namespace MWGui if (!mPtr.isEmpty()) MWBase::Environment::get().getMechanicsManager()->onClose(mPtr); resetReference(); + + mItemTransfer->removeTarget(*mItemView); } void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 697e47ee1b..86ded2ff75 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -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 #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 mDragAndDrop; + Misc::NotNullPtr mItemTransfer; MWGui::ItemView* mItemView; SortFilterItemModel* mSortModel; @@ -60,7 +64,8 @@ namespace MWGui void onItemSelected(int index); void onBackgroundSelected(); - void dragItem(MyGUI::Widget*, std::size_t 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); diff --git a/apps/openmw/mwgui/draganddrop.cpp b/apps/openmw/mwgui/draganddrop.cpp index ee4dc92a7e..85229d0a13 100644 --- a/apps/openmw/mwgui/draganddrop.cpp +++ b/apps/openmw/mwgui/draganddrop.cpp @@ -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() diff --git a/apps/openmw/mwgui/draganddrop.hpp b/apps/openmw/mwgui/draganddrop.hpp index afe4fd0df2..511e2b7765 100644 --- a/apps/openmw/mwgui/draganddrop.hpp +++ b/apps/openmw/mwgui/draganddrop.hpp @@ -4,6 +4,8 @@ #include "itemmodel.hpp" #include "itemwidget.hpp" +#include + namespace MyGUI { class Widget; @@ -29,7 +31,7 @@ namespace MWGui DragAndDrop(); void startDrag( - int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, std::size_t count); + int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, std::size_t count); void drop(ItemModel* targetModel, ItemView* targetView); void update(); void onFrame(); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 0a37c93b4f..e5adce7624 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -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(viewSize.width); + const float cursorY = cursorPosition.top / static_cast(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"); } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 234df1040e..c558f1bad9 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -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); } @@ -368,6 +377,13 @@ namespace MWGui notifyContentChanged(); } + 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); @@ -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(); } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 15c93d14eb..2dc25144d5 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -8,6 +8,8 @@ #include "../mwworld/containerstore.hpp" #include "../mwworld/ptr.hpp" +#include + 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 mDragAndDrop; + Misc::NotNullPtr mItemTransfer; int mSelectedItem; std::optional mEquippedStackableCount; @@ -122,6 +129,7 @@ namespace MWGui 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); diff --git a/apps/openmw/mwgui/itemtransfer.hpp b/apps/openmw/mwgui/itemtransfer.hpp new file mode 100644 index 0000000000..fbd37bf136 --- /dev/null +++ b/apps/openmw/mwgui/itemtransfer.hpp @@ -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 +#include + +#include + +#include + +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 mWindowManager; + std::unordered_set mTargets; + }; +} + +#endif diff --git a/apps/openmw/mwgui/itemview.hpp b/apps/openmw/mwgui/itemview.hpp index cfbc8a37ac..aeed0a9113 100644 --- a/apps/openmw/mwgui/itemview.hpp +++ b/apps/openmw/mwgui/itemview.hpp @@ -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 model); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 4ff297dd94..c7c4b575a5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -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(); + mItemTransfer = std::make_unique(*this); auto recharge = std::make_unique(); mGuiModeStates[GM_Recharge] = GuiModeState(recharge.get()); @@ -334,7 +336,7 @@ namespace MWGui trackWindow(mStatsWindow, makeStatsWindowSettingValues()); auto inventoryWindow = std::make_unique( - 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(mDragAndDrop.get()); + auto containerWindow = std::make_unique(*mDragAndDrop, *mItemTransfer); mContainerWindow = containerWindow.get(); mWindows.push_back(std::move(containerWindow)); trackWindow(mContainerWindow, makeContainerWindowSettingValues()); @@ -457,7 +459,8 @@ namespace MWGui mSoulgemDialog = std::make_unique(mMessageBoxManager.get()); - auto companionWindow = std::make_unique(mDragAndDrop.get(), mMessageBoxManager.get()); + auto companionWindow + = std::make_unique(*mDragAndDrop, *mItemTransfer, mMessageBoxManager.get()); trackWindow(companionWindow.get(), makeCompanionWindowSettingValues()); mGuiModeStates[GM_Companion] = GuiModeState({ mInventoryWindow, companionWindow.get() }); mWindows.push_back(std::move(companionWindow)); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 1a96092b60..b04c648986 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -8,7 +8,6 @@ **/ #include -#include #include #include @@ -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 mDragAndDrop; + std::unique_ptr mItemTransfer; InventoryWindow* mInventoryWindow; ScrollWindow* mScrollWindow; BookWindow* mBookWindow; diff --git a/apps/openmw/mwgui/worlditemmodel.hpp b/apps/openmw/mwgui/worlditemmodel.hpp new file mode 100644 index 0000000000..137062eeb4 --- /dev/null +++ b/apps/openmw/mwgui/worlditemmodel.hpp @@ -0,0 +1,82 @@ +#ifndef OPENMW_APPS_OPENMW_MWGUI_WORLDITEMMODEL_H +#define OPENMW_APPS_OPENMW_MWGUI_WORLDITEMMODEL_H + +#include "itemmodel.hpp" + +#include +#include + +#include + +#include +#include + +#include + +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 diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 4dcac4def5..c290e2733c 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -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(std::abs(std::visit(Visitor(), mCellRef.mVariant))); + } + void setCount(int value); // Write the content of this CellRef into the given ObjectState