mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-12 16:13:06 +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:
commit
79c689784b
23 changed files with 365 additions and 150 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
78
apps/openmw/mwgui/itemtransfer.hpp
Normal file
78
apps/openmw/mwgui/itemtransfer.hpp
Normal 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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
82
apps/openmw/mwgui/worlditemmodel.hpp
Normal file
82
apps/openmw/mwgui/worlditemmodel.hpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
#include <MyGUI_Colour.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace Settings
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ GUI Settings
|
|||
:type: boolean
|
||||
:range: true, false
|
||||
:default: true
|
||||
|
||||
|
||||
|
||||
Enables or disables the red flash overlay when the character takes damage.
|
||||
Disabling causes the player to "bleed" like NPCs.
|
||||
|
|
@ -87,7 +87,7 @@ GUI Settings
|
|||
:type: boolean
|
||||
:range: true, false
|
||||
:default: true
|
||||
|
||||
|
||||
|
||||
Enable or disable the werewolf visual effect in first-person mode.
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ GUI Settings
|
|||
:type: color
|
||||
:range: [0, 1]
|
||||
:default: 0.15 0.0 0.0 1.0
|
||||
|
||||
|
||||
|
||||
Background color of tooltip and crosshair when hovering over an NPC-owned item.
|
||||
Four floating point values: red, green, blue, alpha (alpha ignored).
|
||||
|
|
@ -107,7 +107,7 @@ GUI Settings
|
|||
:type: color
|
||||
:range: [0, 1]
|
||||
:default: 1.0 0.15 0.15 1.0
|
||||
|
||||
|
||||
|
||||
Crosshair color when hovering over an NPC-owned item.
|
||||
Four floating point values: red, green, blue, alpha (alpha ignored).
|
||||
|
|
|
|||
|
|
@ -767,10 +767,10 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin
|
|||
the specular map texture would have to be named foo_spec.dds).
|
||||
If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file
|
||||
(.osg file, not supported in .nif files). Affects objects.</p></body></html></source>
|
||||
<translation><html><head/><body><p>Om den här funktionen är aktiverad kommer spekularitetskartor (specular maps) att hittas och användas
|
||||
<translation><html><head/><body><p>Om den här funktionen är aktiverad kommer spekularitetskartor (specular maps) att hittas och användas
|
||||
(see 'specular map pattern', t.ex. för en bastextur foo.dds,
|
||||
ska spekularitetskartan heta foo_spec.dds).
|
||||
Om funktionen är inaktiverad kommer normalkartor bara användas om texturerna är explicit listade i 3D-modell-filen
|
||||
Om funktionen är inaktiverad kommer normalkartor bara användas om texturerna är explicit listade i 3D-modell-filen
|
||||
(.nif eller .osg fil). Påverkar objekt.</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ unarmed creature attacks damage armor = false
|
|||
# 2 = Cylinder
|
||||
actor collision shape type = 0
|
||||
|
||||
# When false the player character will base movement on animations. This will sway the camera
|
||||
# while moving in third person like in vanilla, and reproduce movement bugs caused by glitchy
|
||||
# When false the player character will base movement on animations. This will sway the camera
|
||||
# while moving in third person like in vanilla, and reproduce movement bugs caused by glitchy
|
||||
# vanilla animations.
|
||||
player movement ignores animation = false
|
||||
|
||||
|
|
@ -1136,7 +1136,7 @@ xargonianswimknakf = meshes/xargonian_swimkna.kf
|
|||
# Sky atmosphere mesh
|
||||
skyatmosphere = meshes/sky_atmosphere.nif
|
||||
|
||||
# Sky clouds mesh
|
||||
# Sky clouds mesh
|
||||
skyclouds = meshes/sky_clouds_01.nif
|
||||
|
||||
# Sky stars mesh 01
|
||||
|
|
@ -1269,7 +1269,7 @@ right eye fov down = -0.8
|
|||
|
||||
[Post Processing]
|
||||
|
||||
# Enables post-processing
|
||||
# Enables post-processing
|
||||
enabled = false
|
||||
|
||||
# List of active shaders. This is more easily with the in-game shader HUD, by default accessible with the F2 key.
|
||||
|
|
|
|||
Loading…
Reference in a new issue