#include "draganddrop.hpp" #include #include #include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" #include "sortfilteritemmodel.hpp" #include "inventorywindow.hpp" #include "itemwidget.hpp" #include "itemview.hpp" #include "controllers.hpp" namespace MWGui { DragAndDrop::DragAndDrop() : mIsOnDragAndDrop(false) , mDraggedWidget(NULL) , mSourceModel(NULL) , mSourceView(NULL) , mSourceSortModel(NULL) , mDraggedCount(0) { } void DragAndDrop::startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count) { mItem = sourceModel->getItem(index); mDraggedCount = count; mSourceModel = sourceModel; mSourceView = sourceView; mSourceSortModel = sortModel; // If picking up an item that isn't from the player's inventory, the item gets added to player inventory backend // immediately, even though it's still floating beneath the mouse cursor. A bit counterintuitive, // but this is how it works in vanilla, and not doing so would break quests (BM_beasts for instance). ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); if (mSourceModel != playerModel) { MWWorld::Ptr item = mSourceModel->moveItem(mItem, mDraggedCount, playerModel); playerModel->update(); ItemModel::ModelIndex newIndex = -1; for (unsigned int i=0; igetItemCount(); ++i) { if (playerModel->getItem(i).mBase == item) { newIndex = i; break; } } mItem = playerModel->getItem(newIndex); mSourceModel = playerModel; SortFilterItemModel* playerFilterModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getSortFilterModel(); mSourceSortModel = playerFilterModel; } std::string sound = mItem.mBase.getClass().getUpSoundId(mItem.mBase); MWBase::Environment::get().getWindowManager()->playSound (sound); if (mSourceSortModel) { mSourceSortModel->clearDragItems(); mSourceSortModel->addDragItem(mItem.mBase, count); } ItemWidget* baseWidget = MyGUI::Gui::getInstance().createWidget("MW_ItemIcon", 0, 0, 42, 42, MyGUI::Align::Default, "DragAndDrop"); Controllers::ControllerFollowMouse* controller = MyGUI::ControllerManager::getInstance().createItem(Controllers::ControllerFollowMouse::getClassTypeName()) ->castType(); MyGUI::ControllerManager::getInstance().addItem(baseWidget, controller); mDraggedWidget = baseWidget; baseWidget->setItem(mItem.mBase); baseWidget->setNeedMouseFocus(false); baseWidget->setCount(count); sourceView->update(); MWBase::Environment::get().getWindowManager()->setDragDrop(true); mIsOnDragAndDrop = true; } void DragAndDrop::drop(ItemModel *targetModel, ItemView *targetView) { std::string sound = mItem.mBase.getClass().getDownSoundId(mItem.mBase); MWBase::Environment::get().getWindowManager()->playSound(sound); // We can't drop a conjured item to the ground; the target container should always be the source container if (mItem.mFlags & ItemStack::Flag_Bound && targetModel != mSourceModel) { MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}"); return; } // If item is dropped where it was taken from, we don't need to do anything - // otherwise, do the transfer if (targetModel != mSourceModel) { mSourceModel->moveItem(mItem, mDraggedCount, targetModel); } mSourceModel->update(); finish(); if (targetView) targetView->update(); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); // We need to update the view since an other item could be auto-equipped. mSourceView->update(); } void DragAndDrop::onFrame() { if (mIsOnDragAndDrop && mItem.mBase.getRefData().getCount() == 0) finish(); } /* Start of tes3mp change (minor) Add a deleteDragItems argument that allows the deletion of the items in the drag as oppposed to the regular behavior of returning them to their source model This is required to reduce unpredictable behavior for drags approved or rejected by the server */ void DragAndDrop::finish(bool deleteDragItems) /* End of tes3mp change (minor) */ { mIsOnDragAndDrop = false; mSourceSortModel->clearDragItems(); /* Start of tes3mp addition Make it possible to entirely delete the items in the drag */ if (deleteDragItems) mSourceModel->removeItem(mItem, mDraggedCount); /* End of tes3mp addition */ // since mSourceView doesn't get updated in drag() MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); MyGUI::Gui::getInstance().destroyWidget(mDraggedWidget); mDraggedWidget = 0; MWBase::Environment::get().getWindowManager()->setDragDrop(false); } }