mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 21:26:48 +00:00 
			
		
		
		
	Container UI rewrite
This commit is contained in:
		
							parent
							
								
									7e05b725d0
								
							
						
					
					
						commit
						0c4a963132
					
				
					 87 changed files with 2276 additions and 1081 deletions
				
			
		|  | @ -32,7 +32,8 @@ add_openmw_dir (mwgui | |||
|     itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog | ||||
|     enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons | ||||
|     merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks | ||||
|     keywordsearch | ||||
|     keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview | ||||
|     tradeitemmodel companionitemmodel pickpocketitemmodel | ||||
|     ) | ||||
| 
 | ||||
| add_openmw_dir (mwdialogue | ||||
|  |  | |||
|  | @ -338,6 +338,9 @@ namespace MWBase | |||
|             virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object
 | ||||
|             virtual float getWindSpeed() = 0; | ||||
| 
 | ||||
|             virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0; | ||||
|             ///< get all containers in active cells owned by this Npc
 | ||||
| 
 | ||||
|             virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; | ||||
| 
 | ||||
|             virtual int canRest() = 0; | ||||
|  |  | |||
|  | @ -164,4 +164,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Apparatus; | ||||
|     } | ||||
| 
 | ||||
|     float Apparatus::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Apparatus> *ref = | ||||
|             ptr.get<ESM::Apparatus>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ namespace MWClass | |||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; | ||||
|             ///< Add reference into a cell for rendering
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -387,4 +387,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Armor; | ||||
|     } | ||||
| 
 | ||||
|     float Armor::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Armor> *ref = | ||||
|             ptr.get<ESM::Armor>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ namespace MWClass | |||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; | ||||
|             ///< Add reference into a cell for rendering
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -188,4 +188,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Books; | ||||
|     } | ||||
| 
 | ||||
|     float Book::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Book> *ref = | ||||
|             ptr.get<ESM::Book>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -307,4 +307,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Clothing; | ||||
|     } | ||||
| 
 | ||||
|     float Clothing::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Clothing> *ref = | ||||
|             ptr.get<ESM::Clothing>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -73,6 +73,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -225,6 +225,16 @@ namespace MWClass | |||
|         return weight; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     int Creature::getServices(const MWWorld::Ptr &actor) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Creature>* ref = actor.get<ESM::Creature>(); | ||||
|         if (ref->mBase->mHasAI) | ||||
|             return ref->mBase->mAiData.mServices; | ||||
|         else | ||||
|             return 0; | ||||
|     } | ||||
| 
 | ||||
|     MWWorld::Ptr | ||||
|     Creature::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const | ||||
|     { | ||||
|  |  | |||
|  | @ -62,6 +62,8 @@ namespace MWClass | |||
|             virtual bool isEssential (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)
 | ||||
|              | ||||
|             virtual int getServices (const MWWorld::Ptr& actor) const; | ||||
| 
 | ||||
|             static void registerSelf(); | ||||
| 
 | ||||
|             virtual std::string getModel(const MWWorld::Ptr &ptr) const; | ||||
|  |  | |||
|  | @ -202,4 +202,12 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Ingredients; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     float Ingredient::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Ingredient> *ref = | ||||
|             ptr.get<ESM::Ingredient>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -57,6 +57,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual std::string getModel(const MWWorld::Ptr &ptr) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -208,4 +208,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Lights; | ||||
|     } | ||||
| 
 | ||||
|     float Light::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Light> *ref = | ||||
|             ptr.get<ESM::Light>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -58,6 +58,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual std::string getModel(const MWWorld::Ptr &ptr) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -189,4 +189,11 @@ namespace MWClass | |||
| 
 | ||||
|         return ref->mBase->mData.mUses; | ||||
|     } | ||||
| 
 | ||||
|     float Lockpick::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Lockpick> *ref = | ||||
|             ptr.get<ESM::Lockpick>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Return item max health or throw an exception, if class does not have item health
 | ||||
|     }; | ||||
|  |  | |||
|  | @ -254,4 +254,11 @@ namespace MWClass | |||
|         return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc); | ||||
|     } | ||||
| 
 | ||||
|     float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = | ||||
|             ptr.get<ESM::Miscellaneous>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -54,6 +54,8 @@ namespace MWClass | |||
|                 const; | ||||
|             ///< Generate action for using via inventory menu
 | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -648,6 +648,15 @@ namespace MWClass | |||
|             scale *= race->mData.mHeight.mFemale; | ||||
|     } | ||||
| 
 | ||||
|     int Npc::getServices(const MWWorld::Ptr &actor) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::NPC>* ref = actor.get<ESM::NPC>(); | ||||
|         if (ref->mBase->mHasAI) | ||||
|             return ref->mBase->mAiData.mServices; | ||||
|         else | ||||
|             return 0; | ||||
|     } | ||||
| 
 | ||||
|     MWWorld::Ptr | ||||
|     Npc::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const | ||||
|     { | ||||
|  |  | |||
|  | @ -127,6 +127,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual bool isEssential (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)
 | ||||
| 
 | ||||
|             virtual int getServices (const MWWorld::Ptr& actor) const; | ||||
|              | ||||
|             static void registerSelf(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -199,4 +199,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Potions; | ||||
|     } | ||||
| 
 | ||||
|     float Potion::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Potion> *ref = | ||||
|             ptr.get<ESM::Potion>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -53,6 +53,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual std::string getModel(const MWWorld::Ptr &ptr) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -188,4 +188,11 @@ namespace MWClass | |||
| 
 | ||||
|         return ref->mBase->mData.mUses; | ||||
|     } | ||||
| 
 | ||||
|     float Probe::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Probe> *ref = | ||||
|             ptr.get<ESM::Probe>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; | ||||
|             ///< Return item max health or throw an exception, if class does not have item health
 | ||||
|     }; | ||||
|  |  | |||
|  | @ -180,4 +180,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::RepairItem; | ||||
|     } | ||||
| 
 | ||||
|     float Repair::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Repair> *ref = | ||||
|             ptr.get<ESM::Repair>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -62,6 +62,8 @@ namespace MWClass | |||
|             ///< Return item max health or throw an exception, if class does not have item health
 | ||||
|             /// (default implementation: throw an exceoption)
 | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -440,4 +440,11 @@ namespace MWClass | |||
|     { | ||||
|         return npcServices & ESM::NPC::Weapon; | ||||
|     } | ||||
| 
 | ||||
|     float Weapon::getWeight(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Weapon> *ref = | ||||
|             ptr.get<ESM::Weapon>(); | ||||
|         return ref->mBase->mData.mWeight; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -79,6 +79,8 @@ namespace MWClass | |||
| 
 | ||||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const; | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| #include "alchemywindow.hpp" | ||||
| 
 | ||||
| #include <boost/algorithm/string.hpp> | ||||
| #include <boost/lexical_cast.hpp> | ||||
| 
 | ||||
| #include "../mwbase/environment.hpp" | ||||
| #include "../mwbase/world.hpp" | ||||
|  | @ -8,6 +9,11 @@ | |||
| #include "../mwbase/windowmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "inventoryitemmodel.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| #include "itemview.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|  | @ -20,13 +26,25 @@ namespace | |||
|         path.append(".dds"); | ||||
|         return path; | ||||
|     } | ||||
| 
 | ||||
|     std::string getCountString(const int count) | ||||
|     { | ||||
|         if (count == 1) | ||||
|             return ""; | ||||
|         if (count > 9999) | ||||
|             return boost::lexical_cast<std::string>(int(count/1000.f)) + "k"; | ||||
|         else | ||||
|             return boost::lexical_cast<std::string>(count); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     AlchemyWindow::AlchemyWindow() | ||||
|         : WindowBase("openmw_alchemy_window.layout") | ||||
|         , ContainerBase(0), mApparatus (4), mIngredients (4) | ||||
|         , mApparatus (4) | ||||
|         , mIngredients (4) | ||||
|     { | ||||
|         getWidget(mCreateButton, "CreateButton"); | ||||
|         getWidget(mCancelButton, "CancelButton"); | ||||
|  | @ -40,6 +58,13 @@ namespace MWGui | |||
|         getWidget(mApparatus[3], "Apparatus4"); | ||||
|         getWidget(mEffectsBox, "CreatedEffects"); | ||||
|         getWidget(mNameEdit, "NameEdit"); | ||||
|         getWidget(mItemView, "ItemView"); | ||||
| 
 | ||||
|         InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); | ||||
|         mSortModel = new SortFilterItemModel(model); | ||||
|         mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients); | ||||
|         mItemView->setModel (mSortModel); | ||||
|         mItemView->eventItemClicked += MyGUI::newDelegate(this, &AlchemyWindow::onSelectedItem); | ||||
| 
 | ||||
|         mIngredients[0]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); | ||||
|         mIngredients[1]->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); | ||||
|  | @ -49,12 +74,6 @@ namespace MWGui | |||
|         mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked); | ||||
|         mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked); | ||||
| 
 | ||||
|         MyGUI::ScrollView* itemView; | ||||
|         MyGUI::Widget* containerWidget; | ||||
|         getWidget(containerWidget, "Items"); | ||||
|         getWidget(itemView, "ItemView"); | ||||
|         setWidgets(containerWidget, itemView); | ||||
| 
 | ||||
|         center(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -126,12 +145,9 @@ namespace MWGui | |||
| 
 | ||||
|     void AlchemyWindow::open() | ||||
|     { | ||||
|         openContainer (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); // this sets mPtr
 | ||||
|         setFilter (ContainerBase::Filter_Ingredients); | ||||
| 
 | ||||
|         mNameEdit->setCaption(""); | ||||
| 
 | ||||
|         mAlchemy.setAlchemist (mPtr); | ||||
|         mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); | ||||
| 
 | ||||
|         int index = 0; | ||||
| 
 | ||||
|  | @ -155,8 +171,9 @@ namespace MWGui | |||
|         update(); | ||||
|     } | ||||
| 
 | ||||
|     void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item) | ||||
|     void AlchemyWindow::onSelectedItem(int index) | ||||
|     { | ||||
|         MWWorld::Ptr item = mSortModel->getItem(index).mBase; | ||||
|         int res = mAlchemy.addIngredient(item); | ||||
| 
 | ||||
|         if (res != -1) | ||||
|  | @ -168,19 +185,10 @@ namespace MWGui | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::vector<MWWorld::Ptr> AlchemyWindow::itemsToIgnore() | ||||
|     { | ||||
|         std::vector<MWWorld::Ptr> ignore; | ||||
|         // don't show ingredients that are currently selected in the "available ingredients" box.
 | ||||
|         for (int i=0; i<4; ++i) | ||||
|             if (mIngredients[i]->isUserString("ToolTipType")) | ||||
|                 ignore.push_back(*mIngredients[i]->getUserData<MWWorld::Ptr>()); | ||||
| 
 | ||||
|         return ignore; | ||||
|     } | ||||
| 
 | ||||
|     void AlchemyWindow::update() | ||||
|     { | ||||
|         mSortModel->clearDragItems(); | ||||
| 
 | ||||
|         MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients (); | ||||
|         for (int i=0; i<4; ++i) | ||||
|         { | ||||
|  | @ -193,6 +201,9 @@ namespace MWGui | |||
|                 ++it; | ||||
|             } | ||||
| 
 | ||||
|             if (!item.isEmpty()) | ||||
|                 mSortModel->addDragItem(item, item.getRefData().getCount()); | ||||
| 
 | ||||
|             if (ingredient->getChildCount()) | ||||
|                 MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); | ||||
| 
 | ||||
|  | @ -214,7 +225,7 @@ namespace MWGui | |||
|             text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount())); | ||||
|         } | ||||
| 
 | ||||
|         drawItems(); | ||||
|         mItemView->update(); | ||||
| 
 | ||||
|         std::vector<ESM::ENAMstruct> effects; | ||||
|         ESM::EffectList list; | ||||
|  |  | |||
|  | @ -5,19 +5,25 @@ | |||
| 
 | ||||
| #include "../mwmechanics/alchemy.hpp" | ||||
| 
 | ||||
| #include "container.hpp" | ||||
| #include "widgets.hpp" | ||||
| #include "windowbase.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     class AlchemyWindow : public WindowBase, public ContainerBase | ||||
|     class ItemView; | ||||
|     class SortFilterItemModel; | ||||
| 
 | ||||
|     class AlchemyWindow : public WindowBase | ||||
|     { | ||||
|     public: | ||||
|         AlchemyWindow(); | ||||
| 
 | ||||
|         virtual void open(); | ||||
| 
 | ||||
|     protected: | ||||
|     private: | ||||
|         ItemView* mItemView; | ||||
|         SortFilterItemModel* mSortModel; | ||||
| 
 | ||||
|         MyGUI::Button* mCreateButton; | ||||
|         MyGUI::Button* mCancelButton; | ||||
| 
 | ||||
|  | @ -29,17 +35,12 @@ namespace MWGui | |||
|         void onCreateButtonClicked(MyGUI::Widget* _sender); | ||||
|         void onIngredientSelected(MyGUI::Widget* _sender); | ||||
| 
 | ||||
|         virtual void onSelectedItemImpl(MWWorld::Ptr item); | ||||
|         virtual std::vector<MWWorld::Ptr> itemsToIgnore(); | ||||
|         void onSelectedItem(int index); | ||||
| 
 | ||||
|         void removeIngredient(MyGUI::Widget* ingredient); | ||||
| 
 | ||||
|         virtual void onReferenceUnavailable() { ; } | ||||
| 
 | ||||
|         void update(); | ||||
| 
 | ||||
|     private: | ||||
| 
 | ||||
|         MWMechanics::Alchemy mAlchemy; | ||||
| 
 | ||||
|         std::vector<MyGUI::ImageBox *> mApparatus; | ||||
|  |  | |||
							
								
								
									
										34
									
								
								apps/openmw/mwgui/companionitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								apps/openmw/mwgui/companionitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| #include "companionitemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     CompanionItemModel::CompanionItemModel(const MWWorld::Ptr &actor) | ||||
|         : InventoryItemModel(actor) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void CompanionItemModel::copyItem (const ItemStack& item, size_t count) | ||||
|     { | ||||
|         if (mActor.getTypeName() == typeid(ESM::NPC).name()) | ||||
|         { | ||||
|             MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); | ||||
|             stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); | ||||
|         } | ||||
| 
 | ||||
|         InventoryItemModel::copyItem(item, count); | ||||
|     } | ||||
| 
 | ||||
|     void CompanionItemModel::removeItem (const ItemStack& item, size_t count) | ||||
|     { | ||||
|         if (mActor.getTypeName() == typeid(ESM::NPC).name()) | ||||
|         { | ||||
|             MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); | ||||
|             stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); | ||||
|         } | ||||
| 
 | ||||
|         InventoryItemModel::removeItem(item, count); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								apps/openmw/mwgui/companionitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								apps/openmw/mwgui/companionitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| #ifndef MWGUI_COMPANION_ITEM_MODEL_H | ||||
| #define MWGUI_COMPANION_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "inventoryitemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     /// @brief The companion item model keeps track of the companion's profit by
 | ||||
|     /// monitoring which items are being added to and removed from the model.
 | ||||
|     class CompanionItemModel : public InventoryItemModel | ||||
|     { | ||||
|     public: | ||||
|         CompanionItemModel (const MWWorld::Ptr& actor); | ||||
| 
 | ||||
|         virtual void copyItem (const ItemStack& item, size_t count); | ||||
|         virtual void removeItem (const ItemStack& item, size_t count); | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -7,51 +7,102 @@ | |||
| 
 | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "messagebox.hpp" | ||||
| #include "itemview.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| #include "companionitemmodel.hpp" | ||||
| #include "container.hpp" | ||||
| #include "countdialog.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
| CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* manager) | ||||
|     : ContainerBase(dragAndDrop) | ||||
|     , WindowBase("openmw_companion_window.layout") | ||||
|     : WindowBase("openmw_companion_window.layout") | ||||
|     , mDragAndDrop(dragAndDrop) | ||||
|     , mMessageBoxManager(manager) | ||||
|     , mSelectedItem(-1) | ||||
|     , mModel(NULL) | ||||
|     , mSortModel(NULL) | ||||
| { | ||||
|     MyGUI::ScrollView* itemView; | ||||
|     MyGUI::Widget* containerWidget; | ||||
|     getWidget(containerWidget, "Items"); | ||||
|     getWidget(itemView, "ItemView"); | ||||
|     setWidgets(containerWidget, itemView); | ||||
| 
 | ||||
|     getWidget(mCloseButton, "CloseButton"); | ||||
|     getWidget(mProfitLabel, "ProfitLabel"); | ||||
|     getWidget(mEncumbranceBar, "EncumbranceBar"); | ||||
|     getWidget(mItemView, "ItemView"); | ||||
|     mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &CompanionWindow::onBackgroundSelected); | ||||
|     mItemView->eventItemClicked += MyGUI::newDelegate(this, &CompanionWindow::onItemSelected); | ||||
| 
 | ||||
|     mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked); | ||||
| 
 | ||||
|     setCoord(200,0,600,300); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::open(MWWorld::Ptr npc) | ||||
| void CompanionWindow::onItemSelected(int index) | ||||
| { | ||||
|     openContainer(npc); | ||||
|     setTitle(MWWorld::Class::get(npc).getName(npc)); | ||||
|     drawItems(); | ||||
|     updateEncumbranceBar(); | ||||
|     if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|     { | ||||
|         mDragAndDrop->drop(mModel, mItemView); | ||||
|         updateEncumbranceBar(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const ItemStack& item = mSortModel->getItem(index); | ||||
| 
 | ||||
|     MWWorld::Ptr object = item.mBase; | ||||
|     int count = item.mCount; | ||||
|     bool shift = MyGUI::InputManager::getInstance().isShiftPressed(); | ||||
|     if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|         count = 1; | ||||
| 
 | ||||
|     mSelectedItem = mSortModel->mapToSource(index); | ||||
| 
 | ||||
|     if (count > 1 && !shift) | ||||
|     { | ||||
|         CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|         dialog->open(MWWorld::Class::get(object).getName(object), "#{sTake}", count); | ||||
|         dialog->eventOkClicked.clear(); | ||||
|         dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem); | ||||
|     } | ||||
|     else | ||||
|         dragItem (NULL, count); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::notifyItemDragged(MWWorld::Ptr item, int count) | ||||
| void CompanionWindow::dragItem(MyGUI::Widget* sender, int count) | ||||
| { | ||||
|     if (mPtr.getTypeName() == typeid(ESM::NPC).name()) | ||||
|     mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::onBackgroundSelected() | ||||
| { | ||||
|     if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|     { | ||||
|         MWMechanics::NpcStats& stats = MWWorld::Class::get(mPtr).getNpcStats(mPtr); | ||||
|         stats.modifyProfit(MWWorld::Class::get(item).getValue(item) * count); | ||||
|         mDragAndDrop->drop(mModel, mItemView); | ||||
|         updateEncumbranceBar(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::open(const MWWorld::Ptr& npc) | ||||
| { | ||||
|     mPtr = npc; | ||||
|     setTitle(MWWorld::Class::get(npc).getName(npc)); | ||||
|     updateEncumbranceBar(); | ||||
| 
 | ||||
|     mModel = new CompanionItemModel(npc); | ||||
|     mSortModel = new SortFilterItemModel(mModel); | ||||
|     mItemView->setModel(mSortModel); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::onFrame() | ||||
| { | ||||
|     updateEncumbranceBar(); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::updateEncumbranceBar() | ||||
| { | ||||
|     if (mPtr.isEmpty()) | ||||
|         return; | ||||
|     float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr); | ||||
|     float encumbrance = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); | ||||
|     mEncumbranceBar->setValue(encumbrance, capacity); | ||||
|  | @ -65,11 +116,6 @@ void CompanionWindow::updateEncumbranceBar() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::onWindowResize(MyGUI::Window* window) | ||||
| { | ||||
|     drawItems(); | ||||
| } | ||||
| 
 | ||||
| void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender) | ||||
| { | ||||
|     if (mPtr.getTypeName() == typeid(ESM::NPC).name() && MWWorld::Class::get(mPtr).getNpcStats(mPtr).getProfit() < 0) | ||||
|  |  | |||
|  | @ -1,34 +1,47 @@ | |||
| #ifndef OPENMW_MWGUI_COMPANIONWINDOW_H | ||||
| #define OPENMW_MWGUI_COMPANIONWINDOW_H | ||||
| 
 | ||||
| #include "container.hpp" | ||||
| #include "widgets.hpp" | ||||
| #include "windowbase.hpp" | ||||
| #include "referenceinterface.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     class MessageBoxManager; | ||||
|     class ItemView; | ||||
|     class DragAndDrop; | ||||
|     class SortFilterItemModel; | ||||
|     class CompanionItemModel; | ||||
| 
 | ||||
|     class CompanionWindow : public ContainerBase, public WindowBase | ||||
|     class CompanionWindow : public WindowBase, public ReferenceInterface | ||||
|     { | ||||
|     public: | ||||
|         CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager); | ||||
|         virtual ~CompanionWindow() {} | ||||
| 
 | ||||
|         void open(MWWorld::Ptr npc); | ||||
|         void open(const MWWorld::Ptr& npc); | ||||
|         void onFrame (); | ||||
| 
 | ||||
|         virtual void notifyItemDragged(MWWorld::Ptr item, int count); | ||||
|     private: | ||||
|         ItemView* mItemView; | ||||
|         SortFilterItemModel* mSortModel; | ||||
|         CompanionItemModel* mModel; | ||||
|         size_t mSelectedItem; | ||||
| 
 | ||||
|         DragAndDrop* mDragAndDrop; | ||||
| 
 | ||||
|     protected: | ||||
|         MyGUI::Button* mCloseButton; | ||||
|         MyGUI::TextBox* mProfitLabel; | ||||
|         Widgets::MWDynamicStat* mEncumbranceBar; | ||||
|         MessageBoxManager* mMessageBoxManager; | ||||
| 
 | ||||
|         void onItemSelected(int index); | ||||
|         void onBackgroundSelected(); | ||||
|         void dragItem(MyGUI::Widget* sender, int count); | ||||
| 
 | ||||
|         void onMessageBoxButtonClicked(int button); | ||||
| 
 | ||||
|         void updateEncumbranceBar(); | ||||
| 
 | ||||
|         void onWindowResize(MyGUI::Window* window); | ||||
|         void onCloseButtonClicked(MyGUI::Widget* _sender); | ||||
| 
 | ||||
|         virtual void onReferenceUnavailable(); | ||||
|  |  | |||
|  | @ -7,558 +7,21 @@ | |||
| #include "../mwbase/soundmanager.hpp" | ||||
| #include "../mwbase/windowmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/inventorystore.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/player.hpp" | ||||
| 
 | ||||
| #include "countdialog.hpp" | ||||
| #include "tradewindow.hpp" | ||||
| #include "inventorywindow.hpp" | ||||
| 
 | ||||
| #include "itemview.hpp" | ||||
| #include "inventoryitemmodel.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| #include "pickpocketitemmodel.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     bool compareType(std::string type1, std::string type2) | ||||
|     { | ||||
|         // this defines the sorting order of types. types that are first in the vector, appear before other types.
 | ||||
|         std::vector<std::string> mapping; | ||||
|         mapping.push_back( typeid(ESM::Weapon).name() ); | ||||
|         mapping.push_back( typeid(ESM::Armor).name() ); | ||||
|         mapping.push_back( typeid(ESM::Clothing).name() ); | ||||
|         mapping.push_back( typeid(ESM::Potion).name() ); | ||||
|         mapping.push_back( typeid(ESM::Ingredient).name() ); | ||||
|         mapping.push_back( typeid(ESM::Apparatus).name() ); | ||||
|         mapping.push_back( typeid(ESM::Book).name() ); | ||||
|         mapping.push_back( typeid(ESM::Light).name() ); | ||||
|         mapping.push_back( typeid(ESM::Miscellaneous).name() ); | ||||
|         mapping.push_back( typeid(ESM::Lockpick).name() ); | ||||
|         mapping.push_back( typeid(ESM::Repair).name() ); | ||||
|         mapping.push_back( typeid(ESM::Probe).name() ); | ||||
| 
 | ||||
|         assert( std::find(mapping.begin(), mapping.end(), type1) != mapping.end() ); | ||||
|         assert( std::find(mapping.begin(), mapping.end(), type2) != mapping.end() ); | ||||
| 
 | ||||
|         return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2); | ||||
|     } | ||||
| 
 | ||||
|     bool sortItems(MWWorld::Ptr left, MWWorld::Ptr right) | ||||
|     { | ||||
|         if (left.getTypeName() == right.getTypeName()) | ||||
|         { | ||||
|             int cmp = MWWorld::Class::get(left).getName(left).compare( | ||||
|                         MWWorld::Class::get(right).getName(right)); | ||||
|             return cmp < 0; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return compareType(left.getTypeName(), right.getTypeName()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool isChargedSoulstone (MWWorld::Ptr ptr) | ||||
|     { | ||||
|         if (ptr.getTypeName() != typeid(ESM::Miscellaneous).name()) | ||||
|             return false; | ||||
|         MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = | ||||
|             ptr.get<ESM::Miscellaneous>(); | ||||
| 
 | ||||
|         return (ref->mRef.mSoul != ""); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) | ||||
|         : mDragAndDrop(dragAndDrop) | ||||
|         , mFilter(ContainerBase::Filter_All) | ||||
|         , mDisplayEquippedItems(true) | ||||
|         , mHighlightEquippedItems(true) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView) | ||||
|     { | ||||
|         mContainerWidget = containerWidget; | ||||
|         mItemView = itemView; | ||||
| 
 | ||||
|         mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); | ||||
|         mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel); | ||||
|     } | ||||
| 
 | ||||
|     ContainerBase::~ContainerBase() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         mSelectedItem = _sender; | ||||
| 
 | ||||
|         if (mDragAndDrop && !isTrading()) | ||||
|         { | ||||
|             if(!mDragAndDrop->mIsOnDragAndDrop) | ||||
|             { | ||||
|                 MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>()); | ||||
|                 int count = object.getRefData().getCount(); | ||||
| 
 | ||||
|                 if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) | ||||
|                 { | ||||
|                     startDragItem(_sender, count); | ||||
|                 } | ||||
|                 else if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|                 { | ||||
|                     startDragItem(_sender, 1); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     std::string message = "#{sTake}"; | ||||
|                     CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|                     dialog->open(MWWorld::Class::get(object).getName(object), message, count); | ||||
|                     dialog->eventOkClicked.clear(); | ||||
|                     dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|                 onContainerClicked(mContainerWidget); | ||||
|         } | ||||
|         else if (isTrading()) | ||||
|         { | ||||
|             MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>()); | ||||
|             int count = object.getRefData().getCount(); | ||||
| 
 | ||||
|             if (isInventory()) | ||||
|             { | ||||
|                 // the player is trying to sell an item, check if the merchant accepts it
 | ||||
|                 if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) | ||||
|                 { | ||||
|                     // user notification "i don't buy this item"
 | ||||
|                     MWBase::Environment::get().getWindowManager()-> | ||||
|                             messageBox("#{sBarterDialog4}"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             bool buying = isTradeWindow(); // buying or selling?
 | ||||
|             std::string message = buying ? "#{sQuanityMenuMessage02}" : "#{sQuanityMenuMessage01}"; | ||||
| 
 | ||||
|             if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end()) | ||||
|             { | ||||
|                 if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) | ||||
|                 { | ||||
|                     sellAlreadyBoughtItem(NULL, count); | ||||
|                 } | ||||
|                 else if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|                 { | ||||
|                     sellAlreadyBoughtItem(NULL, 1); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|                     dialog->open(MWWorld::Class::get(object).getName(object), message, count); | ||||
|                     dialog->eventOkClicked.clear(); | ||||
|                     dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellAlreadyBoughtItem); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) | ||||
|                 { | ||||
|                     sellItem(NULL, count); | ||||
|                 } | ||||
|                 else if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|                 { | ||||
|                     sellItem(NULL, 1); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|                     dialog->open(MWWorld::Class::get(object).getName(object), message, count); | ||||
|                     dialog->eventOkClicked.clear(); | ||||
|                     dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) | ||||
|     { | ||||
|         MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>(); | ||||
| 
 | ||||
|         if (isInventory()) | ||||
|         { | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count, true); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count, true); | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); | ||||
|         } | ||||
| 
 | ||||
|         std::string sound = MWWorld::Class::get(object).getUpSoundId(object); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         drawItems(); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) | ||||
|     { | ||||
|         MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>(); | ||||
| 
 | ||||
|         if (isInventory()) | ||||
|         { | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(object, count); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count, false); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(object, count); | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count, false); | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); | ||||
|         } | ||||
| 
 | ||||
|         std::string sound = MWWorld::Class::get(object).getUpSoundId(object); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         drawItems(); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count) | ||||
|     { | ||||
|         mDragAndDrop->mIsOnDragAndDrop = true; | ||||
|         mSelectedItem->detachFromWidget(); | ||||
|         mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget); | ||||
| 
 | ||||
|         MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>(); | ||||
|         _unequipItem(object); | ||||
| 
 | ||||
|         mDragAndDrop->mDraggedCount = count; | ||||
| 
 | ||||
|         mDragAndDrop->mDraggedFrom = this; | ||||
| 
 | ||||
|         std::string sound = MWWorld::Class::get(object).getUpSoundId(object); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         mDragAndDrop->mDraggedWidget = mSelectedItem; | ||||
|         static_cast<MyGUI::ImageBox*>(mSelectedItem)->setImageTexture(""); // remove the background texture (not visible during drag)
 | ||||
|         static_cast<MyGUI::TextBox*>(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( | ||||
|             getCountString(mDragAndDrop->mDraggedCount)); | ||||
| 
 | ||||
|         drawItems(); | ||||
| 
 | ||||
|         MWBase::Environment::get().getWindowManager()->setDragDrop(true); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         if (mDragAndDrop == NULL) return; | ||||
| 
 | ||||
|         if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
 | ||||
|         { | ||||
|             MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>(); | ||||
|             MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
| 
 | ||||
|             if (mDragAndDrop->mDraggedFrom != this) | ||||
|             { | ||||
|                 assert(object.getContainerStore() && "Item is not in a container!"); | ||||
| 
 | ||||
|                 // check the container's Organic flag (if this is a container). container with Organic flag doesn't allow putting items inside
 | ||||
|                 if (mPtr.getTypeName() == typeid(ESM::Container).name()) | ||||
|                 { | ||||
|                     MWWorld::LiveCellRef<ESM::Container>* ref = mPtr.get<ESM::Container>(); | ||||
|                     if (ref->mBase->mFlags & ESM::Container::Organic) | ||||
|                     { | ||||
|                         // user notification
 | ||||
|                         MWBase::Environment::get().getWindowManager()-> | ||||
|                             messageBox("#{sContentsMessage2}"); | ||||
| 
 | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 int origCount = object.getRefData().getCount(); | ||||
| 
 | ||||
|                 // check that we don't exceed the allowed weight (only for containers, not for inventory)
 | ||||
|                 if (!isInventory()) | ||||
|                 { | ||||
|                     float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr); | ||||
| 
 | ||||
|                     // try adding the item, and if weight is exceeded, just remove it again.
 | ||||
|                     object.getRefData().setCount(mDragAndDrop->mDraggedCount); | ||||
|                     MWWorld::ContainerStoreIterator it = containerStore.add(object); | ||||
| 
 | ||||
|                     float curWeight = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); | ||||
|                     if (curWeight > capacity) | ||||
|                     { | ||||
|                         it->getRefData().setCount(0); | ||||
|                         object.getRefData().setCount(origCount); | ||||
|                         // user notification
 | ||||
|                         MWBase::Environment::get().getWindowManager()-> | ||||
|                             messageBox("#{sContentsMessage3}"); | ||||
| 
 | ||||
|                         return; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     object.getRefData().setCount (mDragAndDrop->mDraggedCount); | ||||
|                     containerStore.add(object); | ||||
|                     object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             mDragAndDrop->mIsOnDragAndDrop = false; | ||||
|             MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); | ||||
|             drawItems(); | ||||
|             mDragAndDrop->mDraggedFrom->drawItems(); | ||||
| 
 | ||||
|             mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount); | ||||
|             notifyItemDragged(object, mDragAndDrop->mDraggedCount); | ||||
| 
 | ||||
|             MWBase::Environment::get().getWindowManager()->setDragDrop(false); | ||||
| 
 | ||||
|             std::string sound = MWWorld::Class::get(object).getDownSoundId(object); | ||||
|             MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel) | ||||
|     { | ||||
|         if (mItemView->getViewOffset().left + _rel*0.3 > 0) | ||||
|             mItemView->setViewOffset(MyGUI::IntPoint(0, 0)); | ||||
|         else | ||||
|             mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0)); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::setFilter(int filter) | ||||
|     { | ||||
|         mFilter = filter; | ||||
|         drawItems(); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::openContainer(MWWorld::Ptr container) | ||||
|     { | ||||
|         mPtr = container; | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::drawItems() | ||||
|     { | ||||
|         while (mContainerWidget->getChildCount()) | ||||
|         { | ||||
|             MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); | ||||
|         } | ||||
|         MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
| 
 | ||||
|         int x = 0; | ||||
|         int y = 0; | ||||
|         int maxHeight = mItemView->getSize().height - 58; | ||||
| 
 | ||||
|         bool onlyMagic = false; | ||||
|         bool noMagic = false; | ||||
|         int categories = 0; | ||||
|         if (mFilter & Filter_All) | ||||
|             categories |= MWWorld::ContainerStore::Type_All; | ||||
|         if (mFilter & Filter_Weapon) | ||||
|             categories |= MWWorld::ContainerStore::Type_Weapon; | ||||
|         if (mFilter & Filter_Apparel) | ||||
|             categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor; | ||||
|         if (mFilter & Filter_Magic) | ||||
|         { | ||||
|             categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor | ||||
|                         | MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Book | ||||
|                         | MWWorld::ContainerStore::Type_Potion; | ||||
|             onlyMagic = true; | ||||
|         } | ||||
|         if (mFilter & Filter_Misc) | ||||
|         { | ||||
|             categories |= MWWorld::ContainerStore::Type_Miscellaneous | MWWorld::ContainerStore::Type_Book | ||||
|                         | MWWorld::ContainerStore::Type_Ingredient | MWWorld::ContainerStore::Type_Repair | ||||
|                         | MWWorld::ContainerStore::Type_Lockpick | MWWorld::ContainerStore::Type_Light | ||||
|                         | MWWorld::ContainerStore::Type_Apparatus | MWWorld::ContainerStore::Type_Probe; | ||||
|         } | ||||
|         if (mFilter & Filter_Ingredients) | ||||
|             categories |= MWWorld::ContainerStore::Type_Ingredient; | ||||
|         if (mFilter & Filter_ChargedSoulstones) | ||||
|             categories |= MWWorld::ContainerStore::Type_Miscellaneous; | ||||
|         if (mFilter & Filter_NoMagic) | ||||
|             noMagic = true; | ||||
| 
 | ||||
|         /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
 | ||||
| 
 | ||||
|         std::vector< std::pair<MWWorld::Ptr, ItemState> > items; | ||||
| 
 | ||||
|         std::vector<MWWorld::Ptr> equippedItems = getEquippedItems(); | ||||
| 
 | ||||
|         // add bought items (always at the beginning)
 | ||||
|         std::vector<MWWorld::Ptr> boughtItems; | ||||
|         for (MWWorld::ContainerStoreIterator it (mBoughtItems.begin()); it!=mBoughtItems.end(); ++it) | ||||
|         { | ||||
|             boughtItems.push_back(*it); | ||||
|         } | ||||
|         std::sort(boughtItems.begin(), boughtItems.end(), sortItems); | ||||
| 
 | ||||
|         for (std::vector<MWWorld::Ptr>::iterator it=boughtItems.begin(); | ||||
|             it != boughtItems.end(); ++it) | ||||
|         { | ||||
|             items.push_back( std::make_pair(*it, ItemState_Barter) ); | ||||
|         } | ||||
| 
 | ||||
|         // filter out the equipped items of categories we don't want
 | ||||
|         std::vector<MWWorld::Ptr> unwantedItems = equippedItems; | ||||
|         for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) | ||||
|         { | ||||
|             std::vector<MWWorld::Ptr>::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *iter); | ||||
|             if (found != unwantedItems.end()) | ||||
|             { | ||||
|                 unwantedItems.erase(found); | ||||
|             } | ||||
|         } | ||||
|         // now erase everything that's still in unwantedItems.
 | ||||
|         for (std::vector<MWWorld::Ptr>::iterator it=unwantedItems.begin(); | ||||
|             it != unwantedItems.end(); ++it) | ||||
|         { | ||||
|             std::vector<MWWorld::Ptr>::iterator found = std::find(equippedItems.begin(), equippedItems.end(), *it); | ||||
|             assert(found != equippedItems.end()); | ||||
|             equippedItems.erase(found); | ||||
|         } | ||||
|         // and add the items that are left (= have the correct category)
 | ||||
|         if (mDisplayEquippedItems && mHighlightEquippedItems) | ||||
|         { | ||||
|             for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin(); | ||||
|                 it != equippedItems.end(); ++it) | ||||
|             { | ||||
|                 items.push_back( std::make_pair(*it, ItemState_Equipped) ); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         std::vector<MWWorld::Ptr> ignoreItems = itemsToIgnore(); | ||||
| 
 | ||||
|         // now add the regular items
 | ||||
|         std::vector<MWWorld::Ptr> regularItems; | ||||
|         for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) | ||||
|         { | ||||
|             if ( (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() | ||||
|                   || (!mHighlightEquippedItems && mDisplayEquippedItems)) | ||||
|                 && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end() | ||||
|                 && std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end()) | ||||
|                 regularItems.push_back(*iter); | ||||
|         } | ||||
| 
 | ||||
|         // sort them and add
 | ||||
|         std::sort(regularItems.begin(), regularItems.end(), sortItems); | ||||
|         for (std::vector<MWWorld::Ptr>::const_iterator it=regularItems.begin(); it!=regularItems.end(); ++it) | ||||
|         { | ||||
|             items.push_back( std::make_pair(*it, ItemState_Normal) ); | ||||
|         } | ||||
| 
 | ||||
|         for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin(); | ||||
|             it != items.end(); ++it) | ||||
|         { | ||||
|             const MWWorld::Ptr* iter = &((*it).first); | ||||
| 
 | ||||
| 
 | ||||
|             if (onlyMagic | ||||
|                     && it->second != ItemState_Barter | ||||
|                     && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" | ||||
|                     && iter->getTypeName() != typeid(ESM::Potion).name()) | ||||
|                 continue; | ||||
| 
 | ||||
|             if (noMagic | ||||
|                     && it->second != ItemState_Barter | ||||
|                     && (MWWorld::Class::get(*iter).getEnchantment(*iter) != "" | ||||
|                     || iter->getTypeName() == typeid(ESM::Potion).name())) | ||||
|                 continue; | ||||
| 
 | ||||
|             if ( (mFilter & Filter_ChargedSoulstones) | ||||
|                     && !isChargedSoulstone(*iter)) | ||||
|                 continue; | ||||
| 
 | ||||
|             int displayCount = iter->getRefData().getCount(); | ||||
|             if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>()) | ||||
|             { | ||||
|                 displayCount -= mDragAndDrop->mDraggedCount; | ||||
|             } | ||||
|             if(displayCount > 0) | ||||
|             { | ||||
|                 std::string path = std::string("icons\\"); | ||||
|                 path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); | ||||
| 
 | ||||
|                 // background widget (for the "equipped" frame and magic item background image)
 | ||||
|                 bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""); | ||||
|                 MyGUI::ImageBox* backgroundWidget = mContainerWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); | ||||
|                 backgroundWidget->setUserString("ToolTipType", "ItemPtr"); | ||||
|                 backgroundWidget->setUserData(*iter); | ||||
| 
 | ||||
|                 std::string backgroundTex = "textures\\menu_icon"; | ||||
|                 if (isMagic) | ||||
|                     backgroundTex += "_magic"; | ||||
|                 if (it->second == ItemState_Normal) | ||||
|                 { | ||||
|                     if (!isMagic) | ||||
|                         backgroundTex = ""; | ||||
|                 } | ||||
|                 else if (it->second == ItemState_Equipped) | ||||
|                 { | ||||
|                     backgroundTex += "_equip"; | ||||
|                 } | ||||
|                 else if (it->second == ItemState_Barter) | ||||
|                 { | ||||
|                     backgroundTex += "_barter"; | ||||
|                 } | ||||
|                 if (backgroundTex != "") | ||||
|                     backgroundTex += ".dds"; | ||||
| 
 | ||||
|                 backgroundWidget->setImageTexture(backgroundTex); | ||||
|                 if (it->second == ItemState_Barter && !isMagic) | ||||
|                     backgroundWidget->setProperty("ImageCoord", "2 2 42 42"); | ||||
|                 else | ||||
|                     backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); | ||||
|                 backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem); | ||||
|                 backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel); | ||||
| 
 | ||||
|                 // image
 | ||||
|                 MyGUI::ImageBox* image = backgroundWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); | ||||
|                 int pos = path.rfind("."); | ||||
|                 path.erase(pos); | ||||
|                 path.append(".dds"); | ||||
|                 image->setImageTexture(path); | ||||
|                 image->setNeedMouseFocus(false); | ||||
| 
 | ||||
|                 // text widget that shows item count
 | ||||
|                 MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); | ||||
|                 text->setTextAlign(MyGUI::Align::Right); | ||||
|                 text->setNeedMouseFocus(false); | ||||
|                 text->setTextShadow(true); | ||||
|                 text->setTextShadowColour(MyGUI::Colour(0,0,0)); | ||||
|                 text->setCaption(getCountString(displayCount)); | ||||
| 
 | ||||
|                 y += 42; | ||||
|                 if (y > maxHeight) | ||||
|                 { | ||||
|                     x += 42; | ||||
|                     y = 0; | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height); | ||||
|         mItemView->setCanvasSize(size); | ||||
|         mContainerWidget->setSize(size); | ||||
| 
 | ||||
|         notifyContentChanged(); | ||||
|     } | ||||
| 
 | ||||
|     std::string ContainerBase::getCountString(const int count) | ||||
|     std::string getCountString(const int count) | ||||
|     { | ||||
|         if (count == 1) | ||||
|             return ""; | ||||
|  | @ -567,121 +30,193 @@ namespace MWGui | |||
|         else | ||||
|             return boost::lexical_cast<std::string>(count); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     void DragAndDrop::startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count) | ||||
|     { | ||||
|         int origCount = item.getRefData().getCount(); | ||||
|         item.getRefData().setCount(count); | ||||
|         MWWorld::ContainerStoreIterator it = mBoughtItems.add(item); | ||||
|         item.getRefData().setCount(origCount - count); | ||||
|     } | ||||
|         mItem = sourceModel->getItem(index); | ||||
|         mDraggedCount = count; | ||||
|         mSourceModel = sourceModel; | ||||
|         mSourceView = sourceView; | ||||
|         mSourceSortModel = sortModel; | ||||
|         mIsOnDragAndDrop = true; | ||||
|         mDragAndDropWidget->setVisible(true); | ||||
| 
 | ||||
|     void ContainerBase::addItem(MWWorld::Ptr item, int count) | ||||
|     { | ||||
|         MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
|         std::string sound = MWWorld::Class::get(mItem.mBase).getUpSoundId(mItem.mBase); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         int origCount = item.getRefData().getCount(); | ||||
| 
 | ||||
|         item.getRefData().setCount(count); | ||||
|         MWWorld::ContainerStoreIterator it = containerStore.add(item); | ||||
| 
 | ||||
|         item.getRefData().setCount(origCount - count); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::transferBoughtItems() | ||||
|     { | ||||
|         MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
| 
 | ||||
|         for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) | ||||
|         if (mSourceSortModel) | ||||
|         { | ||||
|             containerStore.add(*it); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) | ||||
|     { | ||||
|         for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) | ||||
|         { | ||||
|             store.add(*it); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::vector<MWWorld::Ptr> ContainerBase::getEquippedItems() | ||||
|     { | ||||
|         if (mPtr.getTypeName() != typeid(ESM::NPC).name()) | ||||
|             return std::vector<MWWorld::Ptr>(); | ||||
| 
 | ||||
|         MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); | ||||
| 
 | ||||
|         std::vector<MWWorld::Ptr> items; | ||||
| 
 | ||||
|         for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) | ||||
|         { | ||||
|             MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); | ||||
|             if (it != invStore.end()) | ||||
|             { | ||||
|                 items.push_back(*it); | ||||
|             } | ||||
|             mSourceSortModel->clearDragItems(); | ||||
|             mSourceSortModel->addDragItem(mItem.mBase, count); | ||||
|         } | ||||
| 
 | ||||
|         return items; | ||||
|         std::string path = std::string("icons\\"); | ||||
|         path += MWWorld::Class::get(mItem.mBase).getInventoryIcon(mItem.mBase); | ||||
|         MyGUI::ImageBox* baseWidget = mDragAndDropWidget->createWidget<MyGUI::ImageBox> | ||||
|                 ("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); | ||||
|         mDraggedWidget = baseWidget; | ||||
|         MyGUI::ImageBox* image = baseWidget->createWidget<MyGUI::ImageBox>("ImageBox", | ||||
|             MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); | ||||
|         int pos = path.rfind("."); | ||||
|         path.erase(pos); | ||||
|         path.append(".dds"); | ||||
|         image->setImageTexture(path); | ||||
|         image->setNeedMouseFocus(false); | ||||
| 
 | ||||
|         // text widget that shows item count
 | ||||
|         MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", | ||||
|             MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); | ||||
|         text->setTextAlign(MyGUI::Align::Right); | ||||
|         text->setNeedMouseFocus(false); | ||||
|         text->setTextShadow(true); | ||||
|         text->setTextShadowColour(MyGUI::Colour(0,0,0)); | ||||
|         text->setCaption(getCountString(count)); | ||||
| 
 | ||||
|         sourceView->update(); | ||||
| 
 | ||||
|         MWBase::Environment::get().getWindowManager()->setDragDrop(true); | ||||
|     } | ||||
| 
 | ||||
|     MWWorld::ContainerStore& ContainerBase::getContainerStore() | ||||
|     void DragAndDrop::drop(ItemModel *targetModel, ItemView *targetView) | ||||
|     { | ||||
|         MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
|         return store; | ||||
|         std::string sound = MWWorld::Class::get(mItem.mBase).getDownSoundId(mItem.mBase); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         mDragAndDropWidget->setVisible(false); | ||||
| 
 | ||||
|         targetModel->copyItem(mItem, mDraggedCount); | ||||
|         mSourceModel->removeItem(mItem, mDraggedCount); | ||||
| 
 | ||||
|         mSourceModel->update(); | ||||
| 
 | ||||
|         finish(); | ||||
|         targetView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void DragAndDrop::finish() | ||||
|     { | ||||
|         mIsOnDragAndDrop = false; | ||||
|         mSourceSortModel->clearDragItems(); | ||||
| 
 | ||||
|         MyGUI::Gui::getInstance().destroyWidget(mDraggedWidget); | ||||
|         mDraggedWidget = 0; | ||||
|         MWBase::Environment::get().getWindowManager()->setDragDrop(false); | ||||
|     } | ||||
| 
 | ||||
|     // ------------------------------------------------------------------------------------------------
 | ||||
| 
 | ||||
|     ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) | ||||
|         : ContainerBase(dragAndDrop) | ||||
|         , WindowBase("openmw_container_window.layout") | ||||
|         : WindowBase("openmw_container_window.layout") | ||||
|         , mDragAndDrop(dragAndDrop) | ||||
|         , mSelectedItem(-1) | ||||
|         , mModel(NULL) | ||||
|         , mSortModel(NULL) | ||||
|     { | ||||
|         getWidget(mDisposeCorpseButton, "DisposeCorpseButton"); | ||||
|         getWidget(mTakeButton, "TakeButton"); | ||||
|         getWidget(mCloseButton, "CloseButton"); | ||||
| 
 | ||||
|         MyGUI::ScrollView* itemView; | ||||
|         MyGUI::Widget* containerWidget; | ||||
|         getWidget(containerWidget, "Items"); | ||||
|         getWidget(itemView, "ItemView"); | ||||
|         setWidgets(containerWidget, itemView); | ||||
|         getWidget(mItemView, "ItemView"); | ||||
|         mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &ContainerWindow::onBackgroundSelected); | ||||
|         mItemView->eventItemClicked += MyGUI::newDelegate(this, &ContainerWindow::onItemSelected); | ||||
| 
 | ||||
|         mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked); | ||||
|         mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); | ||||
|         mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); | ||||
| 
 | ||||
|         static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize); | ||||
| 
 | ||||
|         setCoord(200,0,600,300); | ||||
|     } | ||||
| 
 | ||||
|     ContainerWindow::~ContainerWindow() | ||||
|     void ContainerWindow::onItemSelected(int index) | ||||
|     { | ||||
|         if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|         { | ||||
|             if (!dynamic_cast<PickpocketItemModel*>(mModel)) | ||||
|                 dropItem(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const ItemStack& item = mSortModel->getItem(index); | ||||
| 
 | ||||
|         MWWorld::Ptr object = item.mBase; | ||||
|         int count = item.mCount; | ||||
|         bool shift = MyGUI::InputManager::getInstance().isShiftPressed(); | ||||
|         if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|             count = 1; | ||||
| 
 | ||||
|         mSelectedItem = mSortModel->mapToSource(index); | ||||
| 
 | ||||
|         if (count > 1 && !shift) | ||||
|         { | ||||
|             CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|             dialog->open(MWWorld::Class::get(object).getName(object), "#{sTake}", count); | ||||
|             dialog->eventOkClicked.clear(); | ||||
|             dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); | ||||
|         } | ||||
|         else | ||||
|             dragItem (NULL, count); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerWindow::onWindowResize(MyGUI::Window* window) | ||||
|     void ContainerWindow::dragItem(MyGUI::Widget* sender, int count) | ||||
|     { | ||||
|         drawItems(); | ||||
|         mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerWindow::open(MWWorld::Ptr container, bool loot) | ||||
|     void ContainerWindow::dropItem() | ||||
|     { | ||||
|         mDisplayEquippedItems = true; | ||||
|         mHighlightEquippedItems = false; | ||||
|         if (mPtr.getTypeName() == typeid(ESM::Container).name()) | ||||
|         { | ||||
|             // check that we don't exceed container capacity
 | ||||
|             MWWorld::Ptr item = mDragAndDrop->mItem.mBase; | ||||
|             float weight = MWWorld::Class::get(item).getWeight(item) * mDragAndDrop->mDraggedCount; | ||||
|             if (MWWorld::Class::get(mPtr).getCapacity(mPtr) < MWWorld::Class::get(mPtr).getEncumbrance(mPtr) + weight) | ||||
|             { | ||||
|                 MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}"); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // check container organic flag
 | ||||
|             MWWorld::LiveCellRef<ESM::Container>* ref = mPtr.get<ESM::Container>(); | ||||
|             if (ref->mBase->mFlags & ESM::Container::Organic) | ||||
|             { | ||||
|                 MWBase::Environment::get().getWindowManager()-> | ||||
|                     messageBox("#{sContentsMessage2}"); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         mDragAndDrop->drop(mModel, mItemView); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerWindow::onBackgroundSelected() | ||||
|     { | ||||
|         if (mDragAndDrop->mIsOnDragAndDrop && !dynamic_cast<PickpocketItemModel*>(mModel)) | ||||
|             dropItem(); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerWindow::open(const MWWorld::Ptr& container, bool loot) | ||||
|     { | ||||
|         mPtr = container; | ||||
| 
 | ||||
|         if (container.getTypeName() == typeid(ESM::NPC).name() && !loot) | ||||
|         { | ||||
|             // we are stealing stuff
 | ||||
|             mDisplayEquippedItems = false; | ||||
|             MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); | ||||
|             mModel = new PickpocketItemModel(player, new InventoryItemModel(container)); | ||||
|         } | ||||
|         else | ||||
|             mModel = new InventoryItemModel(container); | ||||
| 
 | ||||
|         mDisposeCorpseButton->setVisible(loot); | ||||
| 
 | ||||
|         openContainer(container); | ||||
|         setTitle(MWWorld::Class::get(container).getName(container)); | ||||
|         drawItems(); | ||||
| 
 | ||||
|         mSortModel = new SortFilterItemModel(mModel); | ||||
| 
 | ||||
|         mItemView->setModel (mSortModel); | ||||
|     } | ||||
| 
 | ||||
|     void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) | ||||
|  | @ -697,32 +232,19 @@ namespace MWGui | |||
|         if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) | ||||
|         { | ||||
|             // transfer everything into the player's inventory
 | ||||
|             MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
| 
 | ||||
|             std::vector<MWWorld::Ptr> equippedItems = getEquippedItems(); | ||||
| 
 | ||||
|             MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); | ||||
|             MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); | ||||
| 
 | ||||
|             int i=0; | ||||
|             for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) | ||||
|             ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); | ||||
|             for (size_t i=0; i<mModel->getItemCount(); ++i) | ||||
|             { | ||||
|                 if (std::find(equippedItems.begin(), equippedItems.end(), *iter) != equippedItems.end() | ||||
|                         && !mDisplayEquippedItems) | ||||
|                     continue; | ||||
| 
 | ||||
|                 playerStore.add(*iter); | ||||
| 
 | ||||
|                 if (i==0) | ||||
|                 { | ||||
|                     // play the sound of the first object
 | ||||
|                     std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter); | ||||
|                     MWWorld::Ptr item = mModel->getItem(i).mBase; | ||||
|                     std::string sound = MWWorld::Class::get(item).getUpSoundId(item); | ||||
|                     MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
|                 } | ||||
| 
 | ||||
|                 iter->getRefData().setCount(0); | ||||
| 
 | ||||
|                 ++i; | ||||
|                 playerModel->copyItem(mModel->getItem(i), mModel->getItem(i).mCount); | ||||
|                 mModel->removeItem(mModel->getItem(i), mModel->getItem(i).mCount); | ||||
|             } | ||||
| 
 | ||||
|             MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); | ||||
|  | @ -735,10 +257,10 @@ namespace MWGui | |||
|         { | ||||
|             onTakeAllButtonClicked(mTakeButton); | ||||
| 
 | ||||
|             /// \todo I don't think this is the correct flag to check
 | ||||
|             if (MWWorld::Class::get(mPtr).isEssential(mPtr)) | ||||
|                 MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); | ||||
|             else | ||||
|             /// \todo if corpse is non-disposable: messagebox #{sDisposeCorpseFail}
 | ||||
|             //if ()
 | ||||
|             //    MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
 | ||||
|             //else
 | ||||
|                 MWBase::Environment::get().getWorld()->deleteObject(mPtr); | ||||
| 
 | ||||
|             mPtr = MWWorld::Ptr(); | ||||
|  |  | |||
|  | @ -4,9 +4,7 @@ | |||
| #include "windowbase.hpp" | ||||
| #include "referenceinterface.hpp" | ||||
| 
 | ||||
| #include "../mwclass/container.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|  | @ -23,7 +21,8 @@ namespace MWGui | |||
| { | ||||
|     class WindowManager; | ||||
|     class ContainerWindow; | ||||
|     class ContainerBase; | ||||
|     class ItemView; | ||||
|     class SortFilterItemModel; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -35,114 +34,41 @@ namespace MWGui | |||
|         bool mIsOnDragAndDrop; | ||||
|         MyGUI::Widget* mDraggedWidget; | ||||
|         MyGUI::Widget* mDragAndDropWidget; | ||||
|         ContainerBase* mDraggedFrom; | ||||
|         ItemModel* mSourceModel; | ||||
|         ItemView* mSourceView; | ||||
|         SortFilterItemModel* mSourceSortModel; | ||||
|         ItemStack mItem; | ||||
|         int mDraggedCount; | ||||
| 
 | ||||
|         void startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count); | ||||
|         void drop (ItemModel* targetModel, ItemView* targetView); | ||||
| 
 | ||||
|         void finish(); | ||||
|     }; | ||||
| 
 | ||||
|     class ContainerBase : public ReferenceInterface | ||||
|     { | ||||
|     public: | ||||
|         ContainerBase(DragAndDrop* dragAndDrop); | ||||
|         virtual ~ContainerBase(); | ||||
| 
 | ||||
|         // basic types (inclusive)
 | ||||
|         static const int Filter_All = (1<<0); | ||||
|         static const int Filter_Weapon = (1<<1); | ||||
|         static const int Filter_Apparel = (1<<2); | ||||
|         static const int Filter_Ingredients = (1<<3); | ||||
|         static const int Filter_Misc = (1<<4); | ||||
| 
 | ||||
|         // special filtering (exclusive)
 | ||||
|         static const int Filter_Magic = (1<<5); | ||||
|         static const int Filter_NoMagic = (1<<6); | ||||
|         static const int Filter_ChargedSoulstones = (1<<7); | ||||
| 
 | ||||
|         enum ItemState | ||||
|         { | ||||
|             ItemState_Normal = 0x01, | ||||
|             ItemState_Equipped = 0x02, | ||||
|             ItemState_Barter = 0x03 | ||||
|         }; | ||||
| 
 | ||||
|         void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once
 | ||||
| 
 | ||||
|         void addBarteredItem(MWWorld::Ptr item, int count); | ||||
|         void addItem(MWWorld::Ptr item, int count); | ||||
| 
 | ||||
|         void transferBoughtItems(); ///< transfer bought items into the inventory
 | ||||
|         void returnBoughtItems(MWWorld::ContainerStore& store); ///< return bought items into the specified ContainerStore
 | ||||
| 
 | ||||
|         MWWorld::ContainerStore& getContainerStore(); | ||||
|         MWWorld::ContainerStore& getBoughtItems() { return mBoughtItems; } | ||||
| 
 | ||||
|         void openContainer(MWWorld::Ptr container); | ||||
|         void setFilter(int filter); ///< set category filter
 | ||||
|         void drawItems(); | ||||
| 
 | ||||
|         /// fired when an item was moved by drag&drop. \n
 | ||||
|         /// if it was removed from this container, count will be negative.
 | ||||
|         virtual void notifyItemDragged(MWWorld::Ptr item, int count) {} | ||||
| 
 | ||||
|     protected: | ||||
|         bool mDisplayEquippedItems; | ||||
|         bool mHighlightEquippedItems; | ||||
| 
 | ||||
|         MyGUI::ScrollView* mItemView; | ||||
|         MyGUI::Widget* mContainerWidget; | ||||
| 
 | ||||
|         MyGUI::Widget* mSelectedItem; | ||||
| 
 | ||||
|         DragAndDrop* mDragAndDrop; | ||||
| 
 | ||||
|         int mFilter; | ||||
| 
 | ||||
|         // bought items are put in a separate ContainerStore so that they don't stack with other (not bought) items.
 | ||||
|         MWWorld::ContainerStore mBoughtItems; | ||||
| 
 | ||||
|         void onSelectedItem(MyGUI::Widget* _sender); | ||||
|         void onContainerClicked(MyGUI::Widget* _sender); | ||||
|         void onMouseWheel(MyGUI::Widget* _sender, int _rel); | ||||
| 
 | ||||
|         /// start dragging an item (drag & drop)
 | ||||
|         void startDragItem(MyGUI::Widget* _sender, int count); | ||||
| 
 | ||||
|         /// sell an item from this container
 | ||||
|         void sellItem(MyGUI::Widget* _sender, int count); | ||||
| 
 | ||||
|         /// sell an item from this container, that was previously just bought
 | ||||
|         void sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count); | ||||
| 
 | ||||
|         std::string getCountString(const int count); | ||||
| 
 | ||||
|         virtual bool isTradeWindow() { return false; } | ||||
|         virtual bool isInventory() { return false; } | ||||
|         virtual std::vector<MWWorld::Ptr> getEquippedItems(); | ||||
|         virtual void _unequipItem(MWWorld::Ptr item) { ; } | ||||
| 
 | ||||
|         virtual bool isTrading() { return false; } | ||||
| 
 | ||||
|         virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; } | ||||
| 
 | ||||
|         virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); } | ||||
| 
 | ||||
|         virtual void notifyContentChanged() { ; } | ||||
|     }; | ||||
| 
 | ||||
|     class ContainerWindow : public ContainerBase, public WindowBase | ||||
|     class ContainerWindow : public WindowBase, public ReferenceInterface | ||||
|     { | ||||
|     public: | ||||
|         ContainerWindow(DragAndDrop* dragAndDrop); | ||||
| 
 | ||||
|         virtual ~ContainerWindow(); | ||||
|         void open(const MWWorld::Ptr& container, bool loot=false); | ||||
| 
 | ||||
|         void open(MWWorld::Ptr container, bool loot=false); | ||||
|     private: | ||||
|         DragAndDrop* mDragAndDrop; | ||||
| 
 | ||||
|         MWGui::ItemView* mItemView; | ||||
|         SortFilterItemModel* mSortModel; | ||||
|         ItemModel* mModel; | ||||
|         size_t mSelectedItem; | ||||
| 
 | ||||
|     protected: | ||||
|         MyGUI::Button* mDisposeCorpseButton; | ||||
|         MyGUI::Button* mTakeButton; | ||||
|         MyGUI::Button* mCloseButton; | ||||
| 
 | ||||
|         void onWindowResize(MyGUI::Window* window); | ||||
|         void onItemSelected(int index); | ||||
|         void onBackgroundSelected(); | ||||
|         void dragItem(MyGUI::Widget* sender, int count); | ||||
|         void dropItem(); | ||||
|         void onCloseButtonClicked(MyGUI::Widget* _sender); | ||||
|         void onTakeAllButtonClicked(MyGUI::Widget* _sender); | ||||
|         void onDisposeCorpseButtonClicked(MyGUI::Widget* sender); | ||||
|  |  | |||
							
								
								
									
										113
									
								
								apps/openmw/mwgui/containeritemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								apps/openmw/mwgui/containeritemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | |||
| #include "containeritemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
| ContainerItemModel::ContainerItemModel(const std::vector<MWWorld::Ptr>& itemSources) | ||||
|     : mItemSources(itemSources) | ||||
| { | ||||
|     assert (mItemSources.size()); | ||||
| } | ||||
| 
 | ||||
| ContainerItemModel::ContainerItemModel (const MWWorld::Ptr& source) | ||||
| { | ||||
|     mItemSources.push_back(source); | ||||
| } | ||||
| 
 | ||||
| ItemStack ContainerItemModel::getItem (ModelIndex index) | ||||
| { | ||||
|     if (index < 0) | ||||
|         throw std::runtime_error("Invalid index supplied"); | ||||
|     if (mItems.size() <= static_cast<size_t>(index)) | ||||
|         throw std::runtime_error("Item index out of range"); | ||||
|     return mItems[index]; | ||||
| } | ||||
| 
 | ||||
| size_t ContainerItemModel::getItemCount() | ||||
| { | ||||
|     return mItems.size(); | ||||
| } | ||||
| 
 | ||||
| ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) | ||||
| { | ||||
|     size_t i = 0; | ||||
|     for (std::vector<ItemStack>::iterator it = mItems.begin(); it != mItems.end(); ++it) | ||||
|     { | ||||
|         if (*it == item) | ||||
|             return i; | ||||
|         ++i; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| void ContainerItemModel::copyItem (const ItemStack& item, size_t count) | ||||
| { | ||||
|     const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; | ||||
|     int origCount = item.mBase.getRefData().getCount(); | ||||
|     item.mBase.getRefData().setCount(count); | ||||
|     MWWorld::ContainerStoreIterator it = MWWorld::Class::get(source).getContainerStore(source).add(item.mBase); | ||||
|     if (*it != item.mBase) | ||||
|         item.mBase.getRefData().setCount(origCount); | ||||
|     else | ||||
|         item.mBase.getRefData().setCount(origCount + count); // item copied onto itself
 | ||||
| } | ||||
| 
 | ||||
| void ContainerItemModel::removeItem (const ItemStack& item, size_t count) | ||||
| { | ||||
|     int toRemove = count; | ||||
| 
 | ||||
|     for (std::vector<MWWorld::Ptr>::iterator source = mItemSources.begin(); source != mItemSources.end(); ++source) | ||||
|     { | ||||
|         MWWorld::ContainerStore& store = MWWorld::Class::get(*source).getContainerStore(*source); | ||||
| 
 | ||||
|         for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) | ||||
|         { | ||||
|             // If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
 | ||||
|             if (*it == item.mBase || (store.stacks(*it, item.mBase) && item.mBase.getContainerStore()->stacks(*it, item.mBase))) | ||||
|             { | ||||
|                 int refCount = it->getRefData().getCount(); | ||||
|                 it->getRefData().setCount(std::max(0, refCount - toRemove)); | ||||
|                 toRemove -= refCount; | ||||
|                 if (toRemove <= 0) | ||||
|                     return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     throw std::runtime_error("Not enough items to remove could be found"); | ||||
| } | ||||
| 
 | ||||
| void ContainerItemModel::update() | ||||
| { | ||||
|     mItems.clear(); | ||||
|     for (std::vector<MWWorld::Ptr>::iterator source = mItemSources.begin(); source != mItemSources.end(); ++source) | ||||
|     { | ||||
|         MWWorld::ContainerStore& store = MWWorld::Class::get(*source).getContainerStore(*source); | ||||
| 
 | ||||
|         for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) | ||||
|         { | ||||
|             std::vector<ItemStack>::iterator itemStack = mItems.begin(); | ||||
|             for (; itemStack != mItems.end(); ++itemStack) | ||||
|             { | ||||
|                 // If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
 | ||||
|                 if (store.stacks(itemStack->mBase, *it) && it->getContainerStore()->stacks(itemStack->mBase, *it)) | ||||
|                 { | ||||
|                     // we already have an item stack of this kind, add to it
 | ||||
|                     itemStack->mCount += it->getRefData().getCount(); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (itemStack == mItems.end()) | ||||
|             { | ||||
|                 // no stack yet, create one
 | ||||
|                 ItemStack newItem (*it, this, it->getRefData().getCount()); | ||||
|                 mItems.push_back(newItem); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										37
									
								
								apps/openmw/mwgui/containeritemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								apps/openmw/mwgui/containeritemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| #ifndef MWGUI_CONTAINER_ITEM_MODEL_H | ||||
| #define MWGUI_CONTAINER_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     /// @brief The container item model supports multiple item sources, which are needed for
 | ||||
|     /// making NPCs sell items from containers owned by them
 | ||||
|     class ContainerItemModel : public ItemModel | ||||
|     { | ||||
|     public: | ||||
|         ContainerItemModel (const std::vector<MWWorld::Ptr>& itemSources); | ||||
|         ///< @note The order of elements \a itemSources matters here. The first element has the highest priority for removal,
 | ||||
|         ///  while the last element will be used to add new items to.
 | ||||
| 
 | ||||
|         ContainerItemModel (const MWWorld::Ptr& source); | ||||
| 
 | ||||
|         virtual ItemStack getItem (ModelIndex index); | ||||
|         virtual ModelIndex getIndex (ItemStack item); | ||||
|         virtual size_t getItemCount(); | ||||
| 
 | ||||
|         virtual void copyItem (const ItemStack& item, size_t count); | ||||
|         virtual void removeItem (const ItemStack& item, size_t count); | ||||
| 
 | ||||
|         virtual void update(); | ||||
| 
 | ||||
|     private: | ||||
|         std::vector<MWWorld::Ptr> mItemSources; | ||||
| 
 | ||||
|         std::vector<ItemStack> mItems; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -9,6 +9,8 @@ | |||
| 
 | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "../mwdialogue/dialoguemanagerimp.hpp" | ||||
| 
 | ||||
| #include "widgets.hpp" | ||||
|  |  | |||
|  | @ -6,11 +6,14 @@ | |||
| #include "../mwbase/world.hpp" | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/manualref.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "itemselection.hpp" | ||||
| #include "container.hpp" | ||||
| #include "inventorywindow.hpp" | ||||
| 
 | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|  | @ -139,13 +142,12 @@ namespace MWGui | |||
|     void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) | ||||
|     { | ||||
|         delete mItemSelectionDialog; | ||||
|         mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}", | ||||
|             ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic); | ||||
|         mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}"); | ||||
|         mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); | ||||
|         mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); | ||||
|         mItemSelectionDialog->setVisible(true); | ||||
|         mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); | ||||
|         mItemSelectionDialog->drawItems (); | ||||
|         mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable); | ||||
|     } | ||||
| 
 | ||||
|     void EnchantingDialog::onItemSelected(MWWorld::Ptr item) | ||||
|  | @ -227,13 +229,12 @@ namespace MWGui | |||
|     void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender) | ||||
|     { | ||||
|         delete mItemSelectionDialog; | ||||
|         mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}", | ||||
|             ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones); | ||||
|         mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}"); | ||||
|         mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); | ||||
|         mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); | ||||
|         mItemSelectionDialog->setVisible(true); | ||||
|         mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); | ||||
|         mItemSelectionDialog->drawItems (); | ||||
|         mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones); | ||||
| 
 | ||||
|         //MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}");
 | ||||
|     } | ||||
|  |  | |||
|  | @ -7,10 +7,13 @@ | |||
| #include "../mwbase/windowmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "inventorywindow.hpp" | ||||
| #include "console.hpp" | ||||
| #include "spellicons.hpp" | ||||
| #include "itemmodel.hpp" | ||||
| #include "container.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|  | @ -195,7 +198,7 @@ namespace MWGui | |||
|         if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|         { | ||||
|             // drop item into the gameworld
 | ||||
|             MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>(); | ||||
|             MWWorld::Ptr object = mDragAndDrop->mItem.mBase; | ||||
| 
 | ||||
|             MWBase::World* world = MWBase::Environment::get().getWorld(); | ||||
| 
 | ||||
|  | @ -217,16 +220,11 @@ namespace MWGui | |||
|             std::string sound = MWWorld::Class::get(object).getDownSoundId(object); | ||||
|             MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|             object.getRefData().setCount(origCount); | ||||
| 
 | ||||
|             // remove object from the container it was coming from
 | ||||
|             object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); | ||||
| 
 | ||||
|             mDragAndDrop->mIsOnDragAndDrop = false; | ||||
|             MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); | ||||
|             mDragAndDrop->mDraggedWidget = 0; | ||||
| 
 | ||||
|             MWBase::Environment::get().getWindowManager()->setDragDrop(false); | ||||
|             mDragAndDrop->mDraggedFrom->drawItems(); | ||||
|             mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount); | ||||
|             mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); | ||||
|             mDragAndDrop->finish(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  |  | |||
							
								
								
									
										97
									
								
								apps/openmw/mwgui/inventoryitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								apps/openmw/mwgui/inventoryitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | |||
| #include "inventoryitemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/inventorystore.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
| InventoryItemModel::InventoryItemModel(const MWWorld::Ptr &actor) | ||||
|     : mActor(actor) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| ItemStack InventoryItemModel::getItem (ModelIndex index) | ||||
| { | ||||
|     if (index < 0) | ||||
|         throw std::runtime_error("Invalid index supplied"); | ||||
|     if (mItems.size() <= static_cast<size_t>(index)) | ||||
|         throw std::runtime_error("Item index out of range"); | ||||
|     return mItems[index]; | ||||
| } | ||||
| 
 | ||||
| size_t InventoryItemModel::getItemCount() | ||||
| { | ||||
|     return mItems.size(); | ||||
| } | ||||
| 
 | ||||
| ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item) | ||||
| { | ||||
|     size_t i = 0; | ||||
|     for (std::vector<ItemStack>::iterator it = mItems.begin(); it != mItems.end(); ++it) | ||||
|     { | ||||
|         if (*it == item) | ||||
|             return i; | ||||
|         ++i; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| void InventoryItemModel::copyItem (const ItemStack& item, size_t count) | ||||
| { | ||||
|     int origCount = item.mBase.getRefData().getCount(); | ||||
|     item.mBase.getRefData().setCount(count); | ||||
|     MWWorld::ContainerStoreIterator it = MWWorld::Class::get(mActor).getContainerStore(mActor).add(item.mBase); | ||||
|     if (*it != item.mBase) | ||||
|         item.mBase.getRefData().setCount(origCount); | ||||
|     else | ||||
|         item.mBase.getRefData().setCount(origCount + count); // item copied onto itself
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void InventoryItemModel::removeItem (const ItemStack& item, size_t count) | ||||
| { | ||||
|     MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor); | ||||
| 
 | ||||
|     for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) | ||||
|     { | ||||
|         if (*it == item.mBase) | ||||
|         { | ||||
|             if (it->getRefData().getCount() < static_cast<int>(count)) | ||||
|                 throw std::runtime_error("Not enough items in the stack to remove"); | ||||
|             it->getRefData().setCount(it->getRefData().getCount() - count); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     throw std::runtime_error("Item to remove not found in container store"); | ||||
| } | ||||
| 
 | ||||
| void InventoryItemModel::update() | ||||
| { | ||||
|     MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor); | ||||
| 
 | ||||
|     mItems.clear(); | ||||
| 
 | ||||
|     for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) | ||||
|     { | ||||
|         ItemStack newItem (*it, this, it->getRefData().getCount()); | ||||
| 
 | ||||
|         if (mActor.getTypeName() == typeid(ESM::NPC).name()) | ||||
|         { | ||||
|             MWWorld::InventoryStore& store = MWWorld::Class::get(mActor).getInventoryStore(mActor); | ||||
|             for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot) | ||||
|             { | ||||
|                 MWWorld::ContainerStoreIterator equipped = store.getSlot(slot); | ||||
|                 if (equipped == store.end()) | ||||
|                     continue; | ||||
|                 if (*equipped == newItem.mBase) | ||||
|                     newItem.mType = ItemStack::Type_Equipped; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         mItems.push_back(newItem); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										31
									
								
								apps/openmw/mwgui/inventoryitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								apps/openmw/mwgui/inventoryitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| #ifndef MWGUI_INVENTORY_ITEM_MODEL_H | ||||
| #define MWGUI_INVENTORY_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     class InventoryItemModel : public ItemModel | ||||
|     { | ||||
|     public: | ||||
|         InventoryItemModel (const MWWorld::Ptr& actor); | ||||
| 
 | ||||
|         virtual ItemStack getItem (ModelIndex index); | ||||
|         virtual ModelIndex getIndex (ItemStack item); | ||||
|         virtual size_t getItemCount(); | ||||
| 
 | ||||
|         virtual void copyItem (const ItemStack& item, size_t count); | ||||
|         virtual void removeItem (const ItemStack& item, size_t count); | ||||
| 
 | ||||
|         virtual void update(); | ||||
| 
 | ||||
|     protected: | ||||
|         MWWorld::Ptr mActor; | ||||
|     private: | ||||
|         std::vector<ItemStack> mItems; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,5 +1,7 @@ | |||
| #include "inventorywindow.hpp" | ||||
| 
 | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| #include <boost/lexical_cast.hpp> | ||||
| 
 | ||||
| #include "../mwbase/world.hpp" | ||||
|  | @ -9,22 +11,31 @@ | |||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/inventorystore.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/action.hpp" | ||||
| 
 | ||||
| #include "bookwindow.hpp" | ||||
| #include "scrollwindow.hpp" | ||||
| #include "spellwindow.hpp" | ||||
| #include "itemview.hpp" | ||||
| #include "inventoryitemmodel.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| #include "tradeitemmodel.hpp" | ||||
| #include "countdialog.hpp" | ||||
| #include "tradewindow.hpp" | ||||
| #include "container.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop) | ||||
|         : ContainerBase(dragAndDrop) | ||||
|         , WindowPinnableBase("openmw_inventory_window.layout") | ||||
|         : WindowPinnableBase("openmw_inventory_window.layout") | ||||
|         , mTrading(false) | ||||
|         , mLastXSize(0) | ||||
|         , mLastYSize(0) | ||||
|         , mPreview(MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()) | ||||
|         , mPreviewDirty(true) | ||||
|         , mDragAndDrop(dragAndDrop) | ||||
|     { | ||||
|         static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); | ||||
| 
 | ||||
|  | @ -42,11 +53,14 @@ namespace MWGui | |||
| 
 | ||||
|         mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked); | ||||
| 
 | ||||
|         MyGUI::ScrollView* itemView; | ||||
|         MyGUI::Widget* containerWidget; | ||||
|         getWidget(containerWidget, "Items"); | ||||
|         getWidget(itemView, "ItemView"); | ||||
|         setWidgets(containerWidget, itemView); | ||||
|         mPtr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer (); | ||||
| 
 | ||||
|         getWidget(mItemView, "ItemView"); | ||||
|         mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr()); | ||||
|         mSortModel = new SortFilterItemModel(mTradeModel); | ||||
|         mItemView->setModel(mSortModel); | ||||
|         mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected); | ||||
|         mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &InventoryWindow::onBackgroundSelected); | ||||
| 
 | ||||
|         mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); | ||||
|         mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); | ||||
|  | @ -57,23 +71,127 @@ namespace MWGui | |||
|         mFilterAll->setStateSelected(true); | ||||
| 
 | ||||
|         setCoord(0, 342, 498, 258); | ||||
|         onWindowResize(static_cast<MyGUI::Window*>(mMainWidget)); | ||||
| 
 | ||||
|         mPreview.setup(); | ||||
|     } | ||||
| 
 | ||||
|         MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); | ||||
|         openContainer(player); | ||||
|     TradeItemModel* InventoryWindow::getTradeModel() | ||||
|     { | ||||
|         return mTradeModel; | ||||
|     } | ||||
| 
 | ||||
|     ItemModel* InventoryWindow::getModel() | ||||
|     { | ||||
|         return mTradeModel; | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::onBackgroundSelected() | ||||
|     { | ||||
|         if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|             mDragAndDrop->drop(mTradeModel, mItemView); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::onItemSelected (int index) | ||||
|     { | ||||
|         onItemSelectedFromSourceModel (mSortModel->mapToSource(index)); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::onItemSelectedFromSourceModel (int index) | ||||
|     { | ||||
|         if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|         { | ||||
|             mDragAndDrop->drop(mTradeModel, mItemView); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const ItemStack& item = mTradeModel->getItem(index); | ||||
| 
 | ||||
|         unequipItem(item.mBase); | ||||
| 
 | ||||
|         MWWorld::Ptr object = item.mBase; | ||||
|         int count = item.mCount; | ||||
|         bool shift = MyGUI::InputManager::getInstance().isShiftPressed(); | ||||
|         if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|             count = 1; | ||||
| 
 | ||||
|         if (mTrading) | ||||
|         { | ||||
|             // check if merchant accepts item
 | ||||
|             int services = MWBase::Environment::get().getWindowManager()->getTradeWindow()->getMerchantServices(); | ||||
|             if (!MWWorld::Class::get(object).canSell(object, services)) | ||||
|             { | ||||
|                 MWBase::Environment::get().getWindowManager()-> | ||||
|                         messageBox("#{sBarterDialog4}"); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (count > 1 && !shift) | ||||
|         { | ||||
|             CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|             std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}"; | ||||
|             dialog->open(MWWorld::Class::get(object).getName(object), message, count); | ||||
|             dialog->eventOkClicked.clear(); | ||||
|             if (mTrading) | ||||
|                 dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem); | ||||
|             else | ||||
|                 dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::dragItem); | ||||
|             mSelectedItem = index; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             mSelectedItem = index; | ||||
|             if (mTrading) | ||||
|                 sellItem (NULL, count); | ||||
|             else | ||||
|                 dragItem (NULL, count); | ||||
|         } | ||||
| 
 | ||||
|         // item might have been unequipped
 | ||||
|         notifyContentChanged(); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::dragItem(MyGUI::Widget* sender, int count) | ||||
|     { | ||||
|         mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::sellItem(MyGUI::Widget* sender, int count) | ||||
|     { | ||||
|         const ItemStack& item = mTradeModel->getItem(mSelectedItem); | ||||
|         std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         if (item.mType == ItemStack::Type_Barter) | ||||
|         { | ||||
|             // this was an item borrowed to us by the merchant
 | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count); | ||||
|             mTradeModel->returnItemBorrowedToUs(mSelectedItem, count); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // borrow item to the merchant
 | ||||
|             MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count); | ||||
|             mTradeModel->borrowItemFromUs(mSelectedItem, count); | ||||
|         } | ||||
| 
 | ||||
|         mItemView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::updateItemView() | ||||
|     { | ||||
|         mItemView->update(); | ||||
|         mPreviewDirty = true; | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::open() | ||||
|     { | ||||
|         updateEncumbranceBar(); | ||||
| 
 | ||||
|         mTrading = false; | ||||
|         mItemView->update(); | ||||
| 
 | ||||
|         mBoughtItems.clear(); | ||||
| 
 | ||||
|         onWindowResize(static_cast<MyGUI::Window*>(mMainWidget)); | ||||
|         drawItems(); | ||||
|         notifyContentChanged(); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::onWindowResize(MyGUI::Window* _sender) | ||||
|  | @ -87,24 +205,24 @@ namespace MWGui | |||
| 
 | ||||
|         if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize) | ||||
|         { | ||||
|             drawItems(); | ||||
|             mLastXSize = mMainWidget->getSize().width; | ||||
|             mLastYSize = mMainWidget->getSize().height; | ||||
|             mPreviewDirty = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         if (_sender == mFilterAll) | ||||
|             setFilter(ContainerBase::Filter_All); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_All); | ||||
|         else if (_sender == mFilterWeapon) | ||||
|             setFilter(ContainerBase::Filter_Weapon); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Weapon); | ||||
|         else if (_sender == mFilterApparel) | ||||
|             setFilter(ContainerBase::Filter_Apparel); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Apparel); | ||||
|         else if (_sender == mFilterMagic) | ||||
|             setFilter(ContainerBase::Filter_Magic); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Magic); | ||||
|         else if (_sender == mFilterMisc) | ||||
|             setFilter(ContainerBase::Filter_Misc); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Misc); | ||||
| 
 | ||||
|         mFilterAll->setStateSelected(false); | ||||
|         mFilterWeapon->setStateSelected(false); | ||||
|  | @ -112,6 +230,8 @@ namespace MWGui | |||
|         mFilterMagic->setStateSelected(false); | ||||
|         mFilterMisc->setStateSelected(false); | ||||
| 
 | ||||
|         mItemView->update(); | ||||
| 
 | ||||
|         static_cast<MyGUI::Button*>(_sender)->setStateSelected(true); | ||||
|     } | ||||
| 
 | ||||
|  | @ -124,23 +244,23 @@ namespace MWGui | |||
|     { | ||||
|         if (mDragAndDrop->mIsOnDragAndDrop) | ||||
|         { | ||||
|             MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>(); | ||||
|             MWWorld::Ptr ptr = mDragAndDrop->mItem.mBase; | ||||
|             mDragAndDrop->finish(); | ||||
| 
 | ||||
|             if (mDragAndDrop->mDraggedFrom != this) | ||||
|             if (mDragAndDrop->mSourceModel != mTradeModel) | ||||
|             { | ||||
|                 // add item to the player's inventory
 | ||||
|                 MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
|                 MWWorld::ContainerStoreIterator it = invStore.begin(); | ||||
| 
 | ||||
|                 int origCount = ptr.getRefData().getCount(); | ||||
|                 ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); | ||||
|                 ptr.getRefData().setCount(mDragAndDrop->mDraggedCount); | ||||
|                 it = invStore.add(ptr); | ||||
|                 (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); | ||||
|                 ptr = *it; | ||||
|                 mDragAndDrop->mDraggedFrom->notifyItemDragged(ptr, -mDragAndDrop->mDraggedCount); | ||||
|             } | ||||
|                 ptr.getRefData().setCount(origCount); | ||||
| 
 | ||||
|             /// \todo scripts
 | ||||
|                 mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); | ||||
|                 ptr = *it; | ||||
|             } | ||||
| 
 | ||||
|             boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(ptr).use(ptr); | ||||
| 
 | ||||
|  | @ -153,12 +273,7 @@ namespace MWGui | |||
|             MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false); | ||||
|             MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false); | ||||
| 
 | ||||
|             mDragAndDrop->mIsOnDragAndDrop = false; | ||||
|             MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); | ||||
| 
 | ||||
|             MWBase::Environment::get().getWindowManager()->setDragDrop(false); | ||||
| 
 | ||||
|             drawItems(); | ||||
|             mItemView->update(); | ||||
| 
 | ||||
|             notifyContentChanged(); | ||||
|         } | ||||
|  | @ -173,16 +288,15 @@ namespace MWGui | |||
|             if (itemSelected.isEmpty ()) | ||||
|                 return; | ||||
| 
 | ||||
|             for (unsigned int i=0; i < mContainerWidget->getChildCount (); ++i) | ||||
|             for (size_t i=0; i < mTradeModel->getItemCount (); ++i) | ||||
|             { | ||||
|                 MyGUI::Widget* w = mContainerWidget->getChildAt (i); | ||||
| 
 | ||||
|                 if (*w->getUserData<MWWorld::Ptr>() == itemSelected) | ||||
|                 if (mTradeModel->getItem(i).mBase == itemSelected) | ||||
|                 { | ||||
|                     onSelectedItem(w); | ||||
|                     onItemSelectedFromSourceModel(i); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             throw std::runtime_error("Can't find clicked item"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -201,7 +315,7 @@ namespace MWGui | |||
|             return MWWorld::Ptr(); | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::_unequipItem(MWWorld::Ptr item) | ||||
|     void InventoryWindow::unequipItem(const MWWorld::Ptr& item) | ||||
|     { | ||||
|         MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); | ||||
| 
 | ||||
|  | @ -252,9 +366,9 @@ namespace MWGui | |||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::startTrade() | ||||
|     void InventoryWindow::setTrading(bool trading) | ||||
|     { | ||||
|         mTrading = true; | ||||
|         mTrading = trading; | ||||
|     } | ||||
| 
 | ||||
|     void InventoryWindow::doRenderUpdate () | ||||
|  | @ -282,7 +396,7 @@ namespace MWGui | |||
|         if (weaponSlot == invStore.end()) | ||||
|             MWBase::Environment::get().getWindowManager()->unsetSelectedWeapon(); | ||||
|         else | ||||
|             MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*weaponSlot); /// \todo track weapon durability
 | ||||
|             MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*weaponSlot); | ||||
| 
 | ||||
|         mPreviewDirty = true; | ||||
| 
 | ||||
|  | @ -292,8 +406,6 @@ namespace MWGui | |||
| 
 | ||||
|     void InventoryWindow::pickUpObject (MWWorld::Ptr object) | ||||
|     { | ||||
|         /// \todo scripts
 | ||||
| 
 | ||||
|         // make sure the object is of a type that can be picked up
 | ||||
|         std::string type = object.getTypeName(); | ||||
|         if ( (type != typeid(ESM::Apparatus).name()) | ||||
|  | @ -313,11 +425,9 @@ namespace MWGui | |||
|         if (MWWorld::Class::get(object).getName(object) == "") // objects without name presented to user can never be picked up
 | ||||
|             return; | ||||
| 
 | ||||
|         // sound
 | ||||
|         std::string sound = MWWorld::Class::get(object).getUpSoundId(object); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1); | ||||
| 
 | ||||
|         int count = object.getRefData().getCount(); | ||||
|         if (object.getCellRef().mGoldValue > 1) | ||||
|             count = object.getCellRef().mGoldValue; | ||||
| 
 | ||||
|         // add to player inventory
 | ||||
|         // can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
 | ||||
|  | @ -326,31 +436,17 @@ namespace MWGui | |||
|         // remove from world
 | ||||
|         MWBase::Environment::get().getWorld()->deleteObject (object); | ||||
| 
 | ||||
|         mDragAndDrop->mIsOnDragAndDrop = true; | ||||
|         mDragAndDrop->mDraggedCount = count; | ||||
| 
 | ||||
|         std::string path = std::string("icons\\"); | ||||
|         path += MWWorld::Class::get(newObject).getInventoryIcon(newObject); | ||||
|         MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); | ||||
|         baseWidget->detachFromWidget(); | ||||
|         baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget); | ||||
|         baseWidget->setUserData(newObject); | ||||
|         mDragAndDrop->mDraggedWidget = baseWidget; | ||||
|         MyGUI::ImageBox* image = baseWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); | ||||
|         int pos = path.rfind("."); | ||||
|         path.erase(pos); | ||||
|         path.append(".dds"); | ||||
|         image->setImageTexture(path); | ||||
|         image->setNeedMouseFocus(false); | ||||
| 
 | ||||
|         // text widget that shows item count
 | ||||
|         MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); | ||||
|         text->setTextAlign(MyGUI::Align::Right); | ||||
|         text->setNeedMouseFocus(false); | ||||
|         text->setTextShadow(true); | ||||
|         text->setTextShadowColour(MyGUI::Colour(0,0,0)); | ||||
|         text->setCaption(getCountString(count)); | ||||
|         mDragAndDrop->mDraggedFrom = this; | ||||
|         // get ModelIndex to the item
 | ||||
|         mTradeModel->update(); | ||||
|         size_t i=0; | ||||
|         for (; i<mTradeModel->getItemCount(); ++i) | ||||
|         { | ||||
|             if (mTradeModel->getItem(i).mBase == newObject) | ||||
|                 break; | ||||
|         } | ||||
|         if (i == mTradeModel->getItemCount()) | ||||
|             throw std::runtime_error("Added item not found"); | ||||
|         mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count); | ||||
|     } | ||||
| 
 | ||||
|     MyGUI::IntCoord InventoryWindow::getAvatarScreenCoord () | ||||
|  |  | |||
|  | @ -3,13 +3,18 @@ | |||
| 
 | ||||
| #include "../mwrender/characterpreview.hpp" | ||||
| 
 | ||||
| #include "container.hpp" | ||||
| #include "windowpinnablebase.hpp" | ||||
| #include "widgets.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     class InventoryWindow : public ContainerBase, public WindowPinnableBase | ||||
|     class ItemView; | ||||
|     class SortFilterItemModel; | ||||
|     class TradeItemModel; | ||||
|     class DragAndDrop; | ||||
|     class ItemModel; | ||||
| 
 | ||||
|     class InventoryWindow : public WindowPinnableBase | ||||
|     { | ||||
|         public: | ||||
|             InventoryWindow(DragAndDrop* dragAndDrop); | ||||
|  | @ -19,7 +24,7 @@ namespace MWGui | |||
|             void doRenderUpdate(); | ||||
| 
 | ||||
|             /// start trading, disables item drag&drop
 | ||||
|             void startTrade(); | ||||
|             void setTrading(bool trading); | ||||
| 
 | ||||
|             void onFrame(); | ||||
| 
 | ||||
|  | @ -35,8 +40,22 @@ namespace MWGui | |||
|                 mPreview.rebuild(); | ||||
|             } | ||||
| 
 | ||||
|         protected: | ||||
|             TradeItemModel* getTradeModel(); | ||||
|             ItemModel* getModel(); | ||||
| 
 | ||||
|             void updateItemView(); | ||||
| 
 | ||||
|         private: | ||||
|             DragAndDrop* mDragAndDrop; | ||||
| 
 | ||||
|             bool mPreviewDirty; | ||||
|             size_t mSelectedItem; | ||||
| 
 | ||||
|             MWWorld::Ptr mPtr; | ||||
| 
 | ||||
|             MWGui::ItemView* mItemView; | ||||
|             SortFilterItemModel* mSortModel; | ||||
|             TradeItemModel* mTradeModel; | ||||
| 
 | ||||
|             MyGUI::Widget* mAvatar; | ||||
|             MyGUI::ImageBox* mAvatarImage; | ||||
|  | @ -59,20 +78,22 @@ namespace MWGui | |||
| 
 | ||||
|             bool mTrading; | ||||
| 
 | ||||
|             void onItemSelected(int index); | ||||
|             void onItemSelectedFromSourceModel(int index); | ||||
| 
 | ||||
|             void onBackgroundSelected(); | ||||
| 
 | ||||
|             void sellItem(MyGUI::Widget* sender, int count); | ||||
|             void dragItem(MyGUI::Widget* sender, int count); | ||||
| 
 | ||||
|             void onWindowResize(MyGUI::Window* _sender); | ||||
|             void onFilterChanged(MyGUI::Widget* _sender); | ||||
|             void onAvatarClicked(MyGUI::Widget* _sender); | ||||
|             void onPinToggled(); | ||||
| 
 | ||||
|             void unequipItem(const MWWorld::Ptr& item); | ||||
|             void updateEncumbranceBar(); | ||||
| 
 | ||||
|             virtual bool isTrading() { return mTrading; } | ||||
|             virtual bool isInventory() { return true; } | ||||
|             virtual void _unequipItem(MWWorld::Ptr item); | ||||
| 
 | ||||
|             virtual void onReferenceUnavailable() { ; } | ||||
| 
 | ||||
|             virtual void notifyContentChanged(); | ||||
|             void notifyContentChanged(); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										98
									
								
								apps/openmw/mwgui/itemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								apps/openmw/mwgui/itemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | |||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     ItemStack::ItemStack(const MWWorld::Ptr &base, ItemModel *creator, size_t count) | ||||
|         : mCreator(creator) | ||||
|         , mCount(count) | ||||
|         , mFlags(0) | ||||
|         , mType(Type_Normal) | ||||
|         , mBase(base) | ||||
|     { | ||||
|         assert(base.getContainerStore()); | ||||
| 
 | ||||
|         if (MWWorld::Class::get(base).getEnchantment(base) != "") | ||||
|             mFlags |= Flag_Enchanted; | ||||
|     } | ||||
| 
 | ||||
|     ItemStack::ItemStack() | ||||
|         : mCreator(NULL) | ||||
|         , mCount(0) | ||||
|         , mFlags(0) | ||||
|         , mType(Type_Normal) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     bool ItemStack::stacks(const ItemStack &other) | ||||
|     { | ||||
|         if(mBase == other.mBase) | ||||
|             return true; | ||||
|         return mBase.getContainerStore()->stacks(mBase, other.mBase) | ||||
|                 && other.mBase.getContainerStore()->stacks(mBase, other.mBase); | ||||
|     } | ||||
| 
 | ||||
|     bool operator == (const ItemStack& left, const ItemStack& right) | ||||
|     { | ||||
|         if (left.mType != right.mType) | ||||
|             return false; | ||||
|         if(left.mBase == right.mBase) | ||||
|             return true; | ||||
|         return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase) | ||||
|                 && right.mBase.getContainerStore()->stacks(left.mBase, right.mBase); | ||||
|     } | ||||
| 
 | ||||
|     ItemModel::ItemModel() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     ProxyItemModel::~ProxyItemModel() | ||||
|     { | ||||
|         delete mSourceModel; | ||||
|     } | ||||
| 
 | ||||
|     void ProxyItemModel::copyItem (const ItemStack& item, size_t count) | ||||
|     { | ||||
|         // no need to use mapToSource since itemIndex refers to an index in the sourceModel
 | ||||
|         mSourceModel->copyItem (item, count); | ||||
|     } | ||||
| 
 | ||||
|     void ProxyItemModel::removeItem (const ItemStack& item, size_t count) | ||||
|     { | ||||
|         mSourceModel->removeItem (item, count); | ||||
|     } | ||||
| 
 | ||||
|     ItemModel::ModelIndex ProxyItemModel::mapToSource (ModelIndex index) | ||||
|     { | ||||
|         const ItemStack& itemToSearch = getItem(index); | ||||
|         for (size_t i=0; i<mSourceModel->getItemCount(); ++i) | ||||
|         { | ||||
|             const ItemStack& item = mSourceModel->getItem(i); | ||||
|             if (item == itemToSearch) | ||||
|                 return i; | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     ItemModel::ModelIndex ProxyItemModel::mapFromSource (ModelIndex index) | ||||
|     { | ||||
|         const ItemStack& itemToSearch = mSourceModel->getItem(index); | ||||
|         for (size_t i=0; i<getItemCount(); ++i) | ||||
|         { | ||||
|             const ItemStack& item = getItem(i); | ||||
|             if (item == itemToSearch) | ||||
|                 return i; | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     ItemModel::ModelIndex ProxyItemModel::getIndex (ItemStack item) | ||||
|     { | ||||
|         return mSourceModel->getIndex(item); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										84
									
								
								apps/openmw/mwgui/itemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								apps/openmw/mwgui/itemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| #ifndef MWGUI_ITEM_MODEL_H | ||||
| #define MWGUI_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "../mwworld/ptr.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     class ItemModel; | ||||
| 
 | ||||
|     /// @brief A single item stack managed by an item model
 | ||||
|     struct ItemStack | ||||
|     { | ||||
|         ItemStack (const MWWorld::Ptr& base, ItemModel* creator, size_t count); | ||||
|         ItemStack(); | ||||
|         bool stacks (const ItemStack& other); | ||||
|         ///< like operator==, only without checking mType
 | ||||
| 
 | ||||
|         enum Type | ||||
|         { | ||||
|             Type_Barter, | ||||
|             Type_Equipped, | ||||
|             Type_Normal | ||||
|         }; | ||||
|         Type mType; | ||||
| 
 | ||||
|         enum Flags | ||||
|         { | ||||
|             Flag_Enchanted = (1<<0) | ||||
|         }; | ||||
|         int mFlags; | ||||
| 
 | ||||
|         ItemModel* mCreator; | ||||
|         size_t mCount; | ||||
|         MWWorld::Ptr mBase; | ||||
|     }; | ||||
| 
 | ||||
|     bool operator == (const ItemStack& left, const ItemStack& right); | ||||
| 
 | ||||
| 
 | ||||
|     /// @brief The base class that all item models should derive from.
 | ||||
|     class ItemModel | ||||
|     { | ||||
|     public: | ||||
|         ItemModel(); | ||||
|         virtual ~ItemModel() {} | ||||
| 
 | ||||
|         typedef int ModelIndex; | ||||
| 
 | ||||
|         virtual ItemStack getItem (ModelIndex index) = 0; | ||||
|         ///< throws for invalid index
 | ||||
|         virtual size_t getItemCount() = 0; | ||||
| 
 | ||||
|         virtual ModelIndex getIndex (ItemStack item) = 0; | ||||
| 
 | ||||
|         virtual void update() = 0; | ||||
| 
 | ||||
|         virtual void copyItem (const ItemStack& item, size_t count) = 0; | ||||
|         virtual void removeItem (const ItemStack& item, size_t count) = 0; | ||||
| 
 | ||||
|     private: | ||||
|         ItemModel(const ItemModel&); | ||||
|         ItemModel& operator=(const ItemModel&); | ||||
|     }; | ||||
| 
 | ||||
|     /// @brief A proxy item model can be used to filter or rearrange items from a source model (or even add new items to it).
 | ||||
|     /// The neat thing is that this does not actually alter the source model.
 | ||||
|     class ProxyItemModel : public ItemModel | ||||
|     { | ||||
|     public: | ||||
|         virtual ~ProxyItemModel(); | ||||
|         virtual void copyItem (const ItemStack& item, size_t count); | ||||
|         virtual void removeItem (const ItemStack& item, size_t count); | ||||
|         virtual ModelIndex getIndex (ItemStack item); | ||||
| 
 | ||||
|         ModelIndex mapToSource (ModelIndex index); | ||||
|         ModelIndex mapFromSource (ModelIndex index); | ||||
|     protected: | ||||
|         ItemModel* mSourceModel; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,19 +1,17 @@ | |||
| #include "itemselection.hpp" | ||||
| 
 | ||||
| #include "itemview.hpp" | ||||
| #include "inventoryitemmodel.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     ItemSelectionDialog::ItemSelectionDialog(const std::string &label, int filter) | ||||
|         : ContainerBase(NULL) | ||||
|         , WindowModal("openmw_itemselection_dialog.layout") | ||||
|     ItemSelectionDialog::ItemSelectionDialog(const std::string &label) | ||||
|         : WindowModal("openmw_itemselection_dialog.layout") | ||||
|     { | ||||
|         mFilter = filter; | ||||
| 
 | ||||
|         MyGUI::ScrollView* itemView; | ||||
|         MyGUI::Widget* containerWidget; | ||||
|         getWidget(containerWidget, "Items"); | ||||
|         getWidget(itemView, "ItemView"); | ||||
|         setWidgets(containerWidget, itemView); | ||||
|         getWidget(mItemView, "ItemView"); | ||||
|         mItemView->eventItemClicked += MyGUI::newDelegate(this, &ItemSelectionDialog::onSelectedItem); | ||||
| 
 | ||||
|         MyGUI::TextBox* l; | ||||
|         getWidget(l, "Label"); | ||||
|  | @ -26,9 +24,29 @@ namespace MWGui | |||
|         center(); | ||||
|     } | ||||
| 
 | ||||
|     void ItemSelectionDialog::onSelectedItemImpl(MWWorld::Ptr item) | ||||
|     void ItemSelectionDialog::openContainer(const MWWorld::Ptr& container) | ||||
|     { | ||||
|         eventItemSelected(item); | ||||
|         mModel = new InventoryItemModel(container); | ||||
|         mSortModel = new SortFilterItemModel(mModel); | ||||
|         mItemView->setModel(mSortModel); | ||||
|     } | ||||
| 
 | ||||
|     void ItemSelectionDialog::setCategory(int category) | ||||
|     { | ||||
|         mSortModel->setCategory(category); | ||||
|         mItemView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void ItemSelectionDialog::setFilter(int filter) | ||||
|     { | ||||
|         mSortModel->setFilter(filter); | ||||
|         mItemView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void ItemSelectionDialog::onSelectedItem(int index) | ||||
|     { | ||||
|         ItemStack item = mSortModel->getItem(index); | ||||
|         eventItemSelected(item.mBase); | ||||
|     } | ||||
| 
 | ||||
|     void ItemSelectionDialog::onCancelButtonClicked(MyGUI::Widget* sender) | ||||
|  |  | |||
|  | @ -2,11 +2,14 @@ | |||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     class ItemView; | ||||
|     class SortFilterItemModel; | ||||
|     class InventoryItemModel; | ||||
| 
 | ||||
|     class ItemSelectionDialog : public ContainerBase, public WindowModal | ||||
|     class ItemSelectionDialog : public WindowModal | ||||
|     { | ||||
|     public: | ||||
|         ItemSelectionDialog(const std::string& label, int filter); | ||||
|         ItemSelectionDialog(const std::string& label); | ||||
| 
 | ||||
|         typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; | ||||
|         typedef MyGUI::delegates::CMultiDelegate1<MWWorld::Ptr> EventHandle_Item; | ||||
|  | @ -14,11 +17,16 @@ namespace MWGui | |||
|         EventHandle_Item eventItemSelected; | ||||
|         EventHandle_Void eventDialogCanceled; | ||||
| 
 | ||||
|         void openContainer (const MWWorld::Ptr& container); | ||||
|         void setCategory(int category); | ||||
|         void setFilter(int filter); | ||||
| 
 | ||||
|     private: | ||||
|         virtual void onReferenceUnavailable() { ; } | ||||
|         ItemView* mItemView; | ||||
|         SortFilterItemModel* mSortModel; | ||||
|         InventoryItemModel* mModel; | ||||
| 
 | ||||
|         virtual void onSelectedItemImpl(MWWorld::Ptr item); | ||||
|         void onSelectedItem(int index); | ||||
| 
 | ||||
|         void onCancelButtonClicked(MyGUI::Widget* sender); | ||||
|     }; | ||||
|  |  | |||
							
								
								
									
										200
									
								
								apps/openmw/mwgui/itemview.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								apps/openmw/mwgui/itemview.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,200 @@ | |||
| #include "itemview.hpp" | ||||
| 
 | ||||
| #include <boost/lexical_cast.hpp> | ||||
| 
 | ||||
| #include <MyGUI_FactoryManager.h> | ||||
| #include <MyGUI_Gui.h> | ||||
| #include <MyGUI_ImageBox.h> | ||||
| #include <MyGUI_TextBox.h> | ||||
| #include <MyGUI_ScrollView.h> | ||||
| #include <MyGUI_Button.h> | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     std::string getCountString(const int count) | ||||
|     { | ||||
|         if (count == 1) | ||||
|             return ""; | ||||
|         if (count > 9999) | ||||
|             return boost::lexical_cast<std::string>(int(count/1000.f)) + "k"; | ||||
|         else | ||||
|             return boost::lexical_cast<std::string>(count); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
| ItemView::ItemView() | ||||
|     : mModel(NULL) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| ItemView::~ItemView() | ||||
| { | ||||
|     delete mModel; | ||||
| } | ||||
| 
 | ||||
| void ItemView::setModel(ItemModel *model) | ||||
| { | ||||
|     delete mModel; | ||||
|     mModel = model; | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::initialiseOverride() | ||||
| { | ||||
|     Base::initialiseOverride(); | ||||
| 
 | ||||
|     assignWidget(mScrollView, "ScrollView"); | ||||
|     if (mScrollView == NULL) | ||||
|         throw std::runtime_error("Item view needs a scroll view"); | ||||
| 
 | ||||
|     mScrollView->setCanvasAlign(MyGUI::Align::Left | MyGUI::Align::Top); | ||||
| } | ||||
| 
 | ||||
| void ItemView::update() | ||||
| { | ||||
|     while (mScrollView->getChildCount()) | ||||
|         MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0)); | ||||
| 
 | ||||
|     if (!mModel) | ||||
|         return; | ||||
| 
 | ||||
|     int x = 0; | ||||
|     int y = 0; | ||||
|     int maxHeight = mScrollView->getSize().height - 58; | ||||
| 
 | ||||
|     mModel->update(); | ||||
| 
 | ||||
|     MyGUI::Widget* dragArea = mScrollView->createWidget<MyGUI::Widget>("",0,0,mScrollView->getWidth(),mScrollView->getHeight(), | ||||
|                                                                        MyGUI::Align::Stretch); | ||||
|     dragArea->setNeedMouseFocus(true); | ||||
|     dragArea->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedBackground); | ||||
|     dragArea->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel); | ||||
| 
 | ||||
|     for (ItemModel::ModelIndex i=0; i<static_cast<int>(mModel->getItemCount()); ++i) | ||||
|     { | ||||
|         const ItemStack& item = mModel->getItem(i); | ||||
| 
 | ||||
|         /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
 | ||||
|         std::string path = std::string("icons\\"); | ||||
|         path += MWWorld::Class::get(item.mBase).getInventoryIcon(item.mBase); | ||||
| 
 | ||||
|         // background widget (for the "equipped" frame and magic item background image)
 | ||||
|         bool isMagic = (item.mFlags & ItemStack::Flag_Enchanted); | ||||
|         MyGUI::ImageBox* backgroundWidget = dragArea->createWidget<MyGUI::ImageBox>("ImageBox", | ||||
|             MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); | ||||
|         backgroundWidget->setUserString("ToolTipType", "ItemModelIndex"); | ||||
|         backgroundWidget->setUserData(std::make_pair(i, mModel)); | ||||
| 
 | ||||
|         std::string backgroundTex = "textures\\menu_icon"; | ||||
|         if (isMagic) | ||||
|             backgroundTex += "_magic"; | ||||
|         if (item.mType == ItemStack::Type_Normal) | ||||
|         { | ||||
|             if (!isMagic) | ||||
|                 backgroundTex = ""; | ||||
|         } | ||||
|         else if (item.mType == ItemStack::Type_Equipped) | ||||
|             backgroundTex += "_equip"; | ||||
|         else if (item.mType == ItemStack::Type_Barter) | ||||
|             backgroundTex += "_barter"; | ||||
| 
 | ||||
|         if (backgroundTex != "") | ||||
|             backgroundTex += ".dds"; | ||||
| 
 | ||||
|         backgroundWidget->setImageTexture(backgroundTex); | ||||
|         if ((item.mType == ItemStack::Type_Barter) && !isMagic) | ||||
|             backgroundWidget->setProperty("ImageCoord", "2 2 42 42"); | ||||
|         else | ||||
|             backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); | ||||
|         backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedItem); | ||||
|         backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel); | ||||
| 
 | ||||
|         // image
 | ||||
|         MyGUI::ImageBox* image = backgroundWidget->createWidget<MyGUI::ImageBox>("ImageBox", | ||||
|             MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); | ||||
|         int pos = path.rfind("."); | ||||
|         path.erase(pos); | ||||
|         path.append(".dds"); | ||||
|         image->setImageTexture(path); | ||||
|         image->setNeedMouseFocus(false); | ||||
| 
 | ||||
|         // text widget that shows item count
 | ||||
|         MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", | ||||
|             MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); | ||||
|         text->setTextAlign(MyGUI::Align::Right); | ||||
|         text->setNeedMouseFocus(false); | ||||
|         text->setTextShadow(true); | ||||
|         text->setTextShadowColour(MyGUI::Colour(0,0,0)); | ||||
|         text->setCaption(getCountString(item.mCount)); | ||||
| 
 | ||||
|         y += 42; | ||||
|         if (y > maxHeight) | ||||
|         { | ||||
|             x += 42; | ||||
|             y = 0; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     x += 42; | ||||
|     MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height); | ||||
|     mScrollView->setCanvasSize(size); | ||||
|     dragArea->setSize(size); | ||||
| } | ||||
| 
 | ||||
| void ItemView::onSelectedItem(MyGUI::Widget *sender) | ||||
| { | ||||
|     ItemModel::ModelIndex index = (*sender->getUserData<std::pair<ItemModel::ModelIndex, ItemModel*> >()).first; | ||||
|     eventItemClicked(index); | ||||
| } | ||||
| 
 | ||||
| void ItemView::onSelectedBackground(MyGUI::Widget *sender) | ||||
| { | ||||
|     eventBackgroundClicked(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::onMouseWheel(MyGUI::Widget *_sender, int _rel) | ||||
| { | ||||
|     if (mScrollView->getViewOffset().left + _rel*0.3 > 0) | ||||
|         mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); | ||||
|     else | ||||
|         mScrollView->setViewOffset(MyGUI::IntPoint(mScrollView->getViewOffset().left + _rel*0.3, 0)); | ||||
| } | ||||
| 
 | ||||
| void ItemView::setSize(const MyGUI::IntSize &_value) | ||||
| { | ||||
|     Base::setSize(_value); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::setSize(int _width, int _height) | ||||
| { | ||||
|     Base::setSize(_width, _height); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::setCoord(const MyGUI::IntCoord &_value) | ||||
| { | ||||
|     Base::setCoord(_value); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::setCoord(int _left, int _top, int _width, int _height) | ||||
| { | ||||
|     Base::setCoord(_left, _top, _width, _height); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void ItemView::registerComponents() | ||||
| { | ||||
|     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ItemView>("Widget"); | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										52
									
								
								apps/openmw/mwgui/itemview.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								apps/openmw/mwgui/itemview.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| #ifndef MWGUI_ITEMVIEW_H | ||||
| #define MWGUI_ITEMVIEW_H | ||||
| 
 | ||||
| #include <MyGUI_Widget.h> | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     class ItemView : public MyGUI::Widget | ||||
|     { | ||||
|     MYGUI_RTTI_DERIVED(ItemView) | ||||
|     public: | ||||
|         ItemView(); | ||||
|         virtual ~ItemView(); | ||||
| 
 | ||||
|         /// Register needed components with MyGUI's factory manager
 | ||||
|         static void registerComponents (); | ||||
| 
 | ||||
|         /// Takes ownership of \a model
 | ||||
|         void setModel (ItemModel* model); | ||||
| 
 | ||||
|         typedef MyGUI::delegates::CMultiDelegate1<ItemModel::ModelIndex> EventHandle_ModelIndex; | ||||
|         typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; | ||||
|         /// Fired when an item was clicked
 | ||||
|         EventHandle_ModelIndex eventItemClicked; | ||||
|         /// Fired when the background was clicked (useful for drag and drop)
 | ||||
|         EventHandle_Void eventBackgroundClicked; | ||||
| 
 | ||||
|         void update(); | ||||
| 
 | ||||
|     private: | ||||
|         virtual void initialiseOverride(); | ||||
| 
 | ||||
|         virtual void setSize(const MyGUI::IntSize& _value); | ||||
|         virtual void setCoord(const MyGUI::IntCoord& _value); | ||||
|         void setSize(int _width, int _height); | ||||
|         void setCoord(int _left, int _top, int _width, int _height); | ||||
| 
 | ||||
|         void onSelectedItem (MyGUI::Widget* sender); | ||||
|         void onSelectedBackground (MyGUI::Widget* sender); | ||||
|         void onMouseWheel(MyGUI::Widget* _sender, int _rel); | ||||
| 
 | ||||
|         ItemModel* mModel; | ||||
|         MyGUI::ScrollView* mScrollView; | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -9,6 +9,8 @@ | |||
| #include "../mwbase/soundmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| 
 | ||||
| #include "inventorywindow.hpp" | ||||
| #include "tradewindow.hpp" | ||||
|  |  | |||
							
								
								
									
										55
									
								
								apps/openmw/mwgui/pickpocketitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								apps/openmw/mwgui/pickpocketitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| #include "pickpocketitemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     PickpocketItemModel::PickpocketItemModel(const MWWorld::Ptr& thief, ItemModel *sourceModel) | ||||
|     { | ||||
|         mSourceModel = sourceModel; | ||||
|         int chance = MWWorld::Class::get(thief).getNpcStats(thief).getSkill(ESM::Skill::Sneak).getModified(); | ||||
| 
 | ||||
|         mSourceModel->update(); | ||||
|         for (size_t i = 0; i<mSourceModel->getItemCount(); ++i) | ||||
|         { | ||||
|             if (std::rand() / static_cast<float>(RAND_MAX) * 100 > chance) | ||||
|                 mHiddenItems.push_back(mSourceModel->getItem(i)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ItemStack PickpocketItemModel::getItem (ModelIndex index) | ||||
|     { | ||||
|         if (index < 0) | ||||
|             throw std::runtime_error("Invalid index supplied"); | ||||
|         if (mItems.size() <= static_cast<size_t>(index)) | ||||
|             throw std::runtime_error("Item index out of range"); | ||||
|         return mItems[index]; | ||||
|     } | ||||
| 
 | ||||
|     size_t PickpocketItemModel::getItemCount() | ||||
|     { | ||||
|         return mItems.size(); | ||||
|     } | ||||
| 
 | ||||
|     void PickpocketItemModel::update() | ||||
|     { | ||||
|         mSourceModel->update(); | ||||
|         mItems.clear(); | ||||
|         for (size_t i = 0; i<mSourceModel->getItemCount(); ++i) | ||||
|         { | ||||
|             const ItemStack& item = mSourceModel->getItem(i); | ||||
|             if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end() | ||||
|                     && item.mType != ItemStack::Type_Equipped) | ||||
|                 mItems.push_back(item); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void PickpocketItemModel::removeItem (const ItemStack &item, size_t count) | ||||
|     { | ||||
|         ProxyItemModel::removeItem(item, count); | ||||
|         /// \todo check if player is detected
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										26
									
								
								apps/openmw/mwgui/pickpocketitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								apps/openmw/mwgui/pickpocketitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| #ifndef MWGUI_PICKPOCKET_ITEM_MODEL_H | ||||
| #define MWGUI_PICKPOCKET_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     /// @brief The pickpocket item model randomly hides item stacks based on a specified chance. Equipped items are always hidden.
 | ||||
|     class PickpocketItemModel : public ProxyItemModel | ||||
|     { | ||||
|     public: | ||||
|         PickpocketItemModel (const MWWorld::Ptr& thief, ItemModel* sourceModel); | ||||
|         virtual ItemStack getItem (ModelIndex index); | ||||
|         virtual size_t getItemCount(); | ||||
|         virtual void update(); | ||||
|         virtual void removeItem (const ItemStack& item, size_t count); | ||||
| 
 | ||||
|     private: | ||||
|         std::vector<ItemStack> mHiddenItems; | ||||
|         std::vector<ItemStack> mItems; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -120,13 +120,12 @@ namespace MWGui | |||
|     { | ||||
|         if (!mItemSelectionDialog ) | ||||
|         { | ||||
|             mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All); | ||||
|             mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}"); | ||||
|             mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem); | ||||
|             mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItemCancel); | ||||
|         } | ||||
|         mItemSelectionDialog->setVisible(true); | ||||
|         mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); | ||||
|         mItemSelectionDialog->drawItems (); | ||||
| 
 | ||||
|         mAssignDialog->setVisible (false); | ||||
|     } | ||||
|  | @ -303,7 +302,7 @@ namespace MWGui | |||
|             MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false); | ||||
| 
 | ||||
|             // since we changed equipping status, update the inventory window
 | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); | ||||
|         } | ||||
|         else if (type == Type_MagicItem) | ||||
|         { | ||||
|  | @ -337,7 +336,7 @@ namespace MWGui | |||
|                 action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); | ||||
| 
 | ||||
|                 // since we changed equipping status, update the inventory window
 | ||||
|                 MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); | ||||
|                 MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); | ||||
|             } | ||||
| 
 | ||||
|             store.setSelectedEnchantItem(it); | ||||
|  |  | |||
							
								
								
									
										170
									
								
								apps/openmw/mwgui/sortfilteritemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								apps/openmw/mwgui/sortfilteritemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,170 @@ | |||
| #include "sortfilteritemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     bool compareType(const std::string& type1, const std::string& type2) | ||||
|     { | ||||
|         // this defines the sorting order of types. types that are first in the vector appear before other types.
 | ||||
|         std::vector<std::string> mapping; | ||||
|         mapping.push_back( typeid(ESM::Weapon).name() ); | ||||
|         mapping.push_back( typeid(ESM::Armor).name() ); | ||||
|         mapping.push_back( typeid(ESM::Clothing).name() ); | ||||
|         mapping.push_back( typeid(ESM::Potion).name() ); | ||||
|         mapping.push_back( typeid(ESM::Ingredient).name() ); | ||||
|         mapping.push_back( typeid(ESM::Apparatus).name() ); | ||||
|         mapping.push_back( typeid(ESM::Book).name() ); | ||||
|         mapping.push_back( typeid(ESM::Light).name() ); | ||||
|         mapping.push_back( typeid(ESM::Miscellaneous).name() ); | ||||
|         mapping.push_back( typeid(ESM::Lockpick).name() ); | ||||
|         mapping.push_back( typeid(ESM::Repair).name() ); | ||||
|         mapping.push_back( typeid(ESM::Probe).name() ); | ||||
| 
 | ||||
|         assert( std::find(mapping.begin(), mapping.end(), type1) != mapping.end() ); | ||||
|         assert( std::find(mapping.begin(), mapping.end(), type2) != mapping.end() ); | ||||
| 
 | ||||
|         return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2); | ||||
|     } | ||||
| 
 | ||||
|     bool compare (const MWGui::ItemStack& left, const MWGui::ItemStack& right) | ||||
|     { | ||||
|         if (left.mType != right.mType) | ||||
|             return left.mType < right.mType; | ||||
| 
 | ||||
|         if (left.mBase.getTypeName() == right.mBase.getTypeName()) | ||||
|         { | ||||
|             int cmp = MWWorld::Class::get(left.mBase).getName(left.mBase).compare( | ||||
|                         MWWorld::Class::get(right.mBase).getName(right.mBase)); | ||||
|             return cmp < 0; | ||||
|         } | ||||
|         else | ||||
|             return compareType(left.mBase.getTypeName(), right.mBase.getTypeName()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel) | ||||
|         : mCategory(Category_All) | ||||
|         , mShowEquipped(true) | ||||
|         , mFilter(0) | ||||
|     { | ||||
|         mSourceModel = sourceModel; | ||||
|     } | ||||
| 
 | ||||
|     void SortFilterItemModel::addDragItem (const MWWorld::Ptr& dragItem, size_t count) | ||||
|     { | ||||
|         mDragItems.push_back(std::make_pair(dragItem, count)); | ||||
|     } | ||||
| 
 | ||||
|     void SortFilterItemModel::clearDragItems() | ||||
|     { | ||||
|         mDragItems.clear(); | ||||
|     } | ||||
| 
 | ||||
|     bool SortFilterItemModel::filterAccepts (const ItemStack& item) | ||||
|     { | ||||
|         MWWorld::Ptr base = item.mBase; | ||||
| 
 | ||||
|         if (item.mType == ItemStack::Type_Equipped && !mShowEquipped) | ||||
|             return false; | ||||
| 
 | ||||
|         int category; | ||||
|         if (base.getTypeName() == typeid(ESM::Armor).name() | ||||
|                 || base.getTypeName() == typeid(ESM::Clothing).name()) | ||||
|             category = Category_Apparel; | ||||
|         else if (base.getTypeName() == typeid(ESM::Weapon).name()) | ||||
|             category = Category_Weapon; | ||||
|         else if (base.getTypeName() == typeid(ESM::Ingredient).name() | ||||
|                      || base.getTypeName() == typeid(ESM::Potion).name()) | ||||
|             category = Category_Magic; | ||||
|         else if (base.getTypeName() == typeid(ESM::Miscellaneous).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Ingredient).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Repair).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Lockpick).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Light).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Apparatus).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Book).name() | ||||
|                  || base.getTypeName() == typeid(ESM::Probe).name()) | ||||
|             category = Category_Misc; | ||||
| 
 | ||||
|         if (item.mFlags & ItemStack::Flag_Enchanted) | ||||
|             category |= Category_Magic; | ||||
| 
 | ||||
|         if (!(category & mCategory)) | ||||
|             return false; | ||||
| 
 | ||||
|         if ((mFilter & Filter_OnlyIngredients) && base.getTypeName() != typeid(ESM::Ingredient).name()) | ||||
|             return false; | ||||
|         if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted)) | ||||
|             return false; | ||||
|         if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name() | ||||
|                                                      || base.getCellRef().mSoul == "")) | ||||
|             return false; | ||||
|         if ((mFilter & Filter_OnlyEnchantable) && (item.mFlags & ItemStack::Flag_Enchanted | ||||
|                                                || (base.getTypeName() != typeid(ESM::Armor).name() | ||||
|                                                    && base.getTypeName() != typeid(ESM::Clothing).name() | ||||
|                                                    && base.getTypeName() != typeid(ESM::Book).name()))) | ||||
|             return false; | ||||
|         if ((mFilter & Filter_OnlyEnchantable) && base.getTypeName() == typeid(ESM::Book).name() | ||||
|                 && !base.get<ESM::Book>()->mBase->mData.mIsScroll) | ||||
|             return false; | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     ItemStack SortFilterItemModel::getItem (ModelIndex index) | ||||
|     { | ||||
|         if (index < 0) | ||||
|             throw std::runtime_error("Invalid index supplied"); | ||||
|         if (mItems.size() <= static_cast<size_t>(index)) | ||||
|             throw std::runtime_error("Item index out of range"); | ||||
|         return mItems[index]; | ||||
|     } | ||||
| 
 | ||||
|     size_t SortFilterItemModel::getItemCount() | ||||
|     { | ||||
|         return mItems.size(); | ||||
|     } | ||||
| 
 | ||||
|     void SortFilterItemModel::setCategory (int category) | ||||
|     { | ||||
|         mCategory = category; | ||||
|     } | ||||
| 
 | ||||
|     void SortFilterItemModel::setFilter (int filter) | ||||
|     { | ||||
|         mFilter = filter; | ||||
|     } | ||||
| 
 | ||||
|     void SortFilterItemModel::update() | ||||
|     { | ||||
|         mSourceModel->update(); | ||||
| 
 | ||||
|         size_t count = mSourceModel->getItemCount(); | ||||
| 
 | ||||
|         mItems.clear(); | ||||
|         for (size_t i=0; i<count; ++i) | ||||
|         { | ||||
|             ItemStack item = mSourceModel->getItem(i); | ||||
| 
 | ||||
|             for (std::vector<std::pair<MWWorld::Ptr, size_t> >::iterator it = mDragItems.begin(); it != mDragItems.end(); ++it) | ||||
|             { | ||||
|                 if (item.mBase == it->first) | ||||
|                 { | ||||
|                     if (item.mCount < it->second) | ||||
|                         throw std::runtime_error("Dragging more than present in the model"); | ||||
|                     item.mCount -= it->second; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (item.mCount > 0 && filterAccepts(item)) | ||||
|                 mItems.push_back(item); | ||||
|         } | ||||
| 
 | ||||
|         std::sort(mItems.begin(), mItems.end(), compare); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										53
									
								
								apps/openmw/mwgui/sortfilteritemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								apps/openmw/mwgui/sortfilteritemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| #ifndef MWGUI_SORT_FILTER_ITEM_MODEL_H | ||||
| #define MWGUI_SORT_FILTER_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     class SortFilterItemModel : public ProxyItemModel | ||||
|     { | ||||
|     public: | ||||
|         SortFilterItemModel (ItemModel* sourceModel); | ||||
| 
 | ||||
|         virtual void update(); | ||||
| 
 | ||||
|         bool filterAccepts (const ItemStack& item); | ||||
| 
 | ||||
|         virtual ItemStack getItem (ModelIndex index); | ||||
|         virtual size_t getItemCount(); | ||||
| 
 | ||||
|         /// Dragged items are not displayed.
 | ||||
|         void addDragItem (const MWWorld::Ptr& dragItem, size_t count); | ||||
|         void clearDragItems(); | ||||
| 
 | ||||
|         void setCategory (int category); | ||||
|         void setFilter (int filter); | ||||
|         void setShowEquipped (bool show) { mShowEquipped = show; } | ||||
| 
 | ||||
|         static const int Category_Weapon = (1<<1); | ||||
|         static const int Category_Apparel = (1<<2); | ||||
|         static const int Category_Misc = (1<<3); | ||||
|         static const int Category_Magic = (1<<4); | ||||
|         static const int Category_All = 255; | ||||
| 
 | ||||
|         static const int Filter_OnlyIngredients = (1<<0); | ||||
|         static const int Filter_OnlyEnchanted = (1<<1); | ||||
|         static const int Filter_OnlyEnchantable = (1<<2); | ||||
|         static const int Filter_OnlyChargedSoulstones = (1<<3); | ||||
| 
 | ||||
| 
 | ||||
|     private: | ||||
|         std::vector<ItemStack> mItems; | ||||
| 
 | ||||
|         std::vector<std::pair<MWWorld::Ptr, size_t> > mDragItems; | ||||
| 
 | ||||
|         int mCategory; | ||||
|         int mFilter; | ||||
|         bool mShowEquipped; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -9,6 +9,7 @@ | |||
| #include "../mwbase/mechanicsmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "../mwmechanics/creaturestats.hpp" | ||||
| 
 | ||||
|  |  | |||
|  | @ -369,7 +369,7 @@ namespace MWGui | |||
|             action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); | ||||
| 
 | ||||
|             // since we changed equipping status, update the inventory window
 | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); | ||||
|         } | ||||
| 
 | ||||
|         store.setSelectedEnchantItem(it); | ||||
|  |  | |||
|  | @ -6,9 +6,13 @@ | |||
| #include "../mwbase/environment.hpp" | ||||
| #include "../mwbase/windowmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "mapwindow.hpp" | ||||
| #include "inventorywindow.hpp" | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|  | @ -176,6 +180,16 @@ namespace MWGui | |||
|                     mFocusObject = *focus->getUserData<MWWorld::Ptr>(); | ||||
|                     tooltipSize = getToolTipViaPtr(false); | ||||
|                 } | ||||
|                 else if (type == "ItemModelIndex") | ||||
|                 { | ||||
|                     std::pair<ItemModel::ModelIndex, ItemModel*> pair = *focus->getUserData<std::pair<ItemModel::ModelIndex, ItemModel*> >(); | ||||
|                     mFocusObject = pair.second->getItem(pair.first).mBase; | ||||
|                     // HACK: To get the correct count for multiple item stack sources
 | ||||
|                     int oldCount = mFocusObject.getRefData().getCount(); | ||||
|                     mFocusObject.getRefData().setCount(pair.second->getItem(pair.first).mCount); | ||||
|                     tooltipSize = getToolTipViaPtr(false); | ||||
|                     mFocusObject.getRefData().setCount(oldCount); | ||||
|                 } | ||||
|                 else if (type == "ToolTipInfo") | ||||
|                 { | ||||
|                     tooltipSize = createToolTip(*focus->getUserData<MWGui::ToolTipInfo>()); | ||||
|  |  | |||
							
								
								
									
										198
									
								
								apps/openmw/mwgui/tradeitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								apps/openmw/mwgui/tradeitemmodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,198 @@ | |||
| #include "tradeitemmodel.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| #include "../mwworld/inventorystore.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     TradeItemModel::TradeItemModel(ItemModel *sourceModel, const MWWorld::Ptr& merchant) | ||||
|         : mMerchant(merchant) | ||||
|     { | ||||
|         mSourceModel = sourceModel; | ||||
|     } | ||||
| 
 | ||||
|     ItemStack TradeItemModel::getItem (ModelIndex index) | ||||
|     { | ||||
|         if (index < 0) | ||||
|             throw std::runtime_error("Invalid index supplied"); | ||||
|         if (mItems.size() <= static_cast<size_t>(index)) | ||||
|             throw std::runtime_error("Item index out of range"); | ||||
|         return mItems[index]; | ||||
|     } | ||||
| 
 | ||||
|     size_t TradeItemModel::getItemCount() | ||||
|     { | ||||
|         return mItems.size(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::borrowImpl(const ItemStack &item, std::vector<ItemStack> &out) | ||||
|     { | ||||
|         std::vector<ItemStack>::iterator it = out.begin(); | ||||
|         bool found = false; | ||||
|         for (; it != out.end(); ++it) | ||||
|         { | ||||
|             if (it->stacks(item)) | ||||
|             { | ||||
|                 it->mCount += item.mCount; | ||||
|                 found = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         if (!found) | ||||
|             out.push_back(item); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::unborrowImpl(const ItemStack &item, size_t count, std::vector<ItemStack> &out) | ||||
|     { | ||||
|         std::vector<ItemStack>::iterator it = out.begin(); | ||||
|         bool found = false; | ||||
|         for (; it != out.end(); ++it) | ||||
|         { | ||||
|             if (it->stacks(item)) | ||||
|             { | ||||
|                 if (it->mCount < count) | ||||
|                     throw std::runtime_error("Not enough borrowed items to return"); | ||||
|                 it->mCount -= count; | ||||
|                 if (it->mCount == 0) | ||||
|                     out.erase(it); | ||||
|                 found = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         if (!found) | ||||
|             throw std::runtime_error("Can't find borrowed item to return"); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::borrowItemFromUs (ModelIndex itemIndex, size_t count) | ||||
|     { | ||||
|         ItemStack item = getItem(itemIndex); | ||||
|         item.mCount = count; | ||||
|         borrowImpl(item, mBorrowedFromUs); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::borrowItemToUs (ModelIndex itemIndex, ItemModel* source, size_t count) | ||||
|     { | ||||
|         ItemStack item = source->getItem(itemIndex); | ||||
|         item.mCount = count; | ||||
|         borrowImpl(item, mBorrowedToUs); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::returnItemBorrowedToUs (ModelIndex itemIndex, size_t count) | ||||
|     { | ||||
|         ItemStack item = getItem(itemIndex); | ||||
|         unborrowImpl(item, count, mBorrowedToUs); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::returnItemBorrowedFromUs (ModelIndex itemIndex, ItemModel* source, size_t count) | ||||
|     { | ||||
|         ItemStack item = source->getItem(itemIndex); | ||||
|         unborrowImpl(item, count, mBorrowedFromUs); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::abort() | ||||
|     { | ||||
|         mBorrowedFromUs.clear(); | ||||
|         mBorrowedToUs.clear(); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<ItemStack> TradeItemModel::getItemsBorrowedToUs() | ||||
|     { | ||||
|         return mBorrowedToUs; | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::transferItems() | ||||
|     { | ||||
|         std::vector<ItemStack>::iterator it = mBorrowedToUs.begin(); | ||||
|         for (; it != mBorrowedToUs.end(); ++it) | ||||
|         { | ||||
|             // get index in the source model
 | ||||
|             ItemModel* sourceModel = it->mCreator; | ||||
|             size_t i=0; | ||||
|             for (; i<sourceModel->getItemCount(); ++i) | ||||
|             { | ||||
|                 if (it->stacks(sourceModel->getItem(i))) | ||||
|                     break; | ||||
|             } | ||||
|             if (i == sourceModel->getItemCount()) | ||||
|                 throw std::runtime_error("The borrowed item disappeared"); | ||||
| 
 | ||||
|             // reset owner before copying
 | ||||
|             const ItemStack& item = sourceModel->getItem(i); | ||||
|             std::string owner = item.mBase.getCellRef().mOwner; | ||||
|             if (mMerchant.isEmpty()) // only for items bought by player
 | ||||
|                 item.mBase.getCellRef().mOwner = ""; | ||||
|             // copy the borrowed items to our model
 | ||||
|             copyItem(item, it->mCount); | ||||
|             item.mBase.getCellRef().mOwner = owner; | ||||
|             // then remove them from the source model
 | ||||
|             sourceModel->removeItem(item, it->mCount); | ||||
|         } | ||||
|         mBorrowedToUs.clear(); | ||||
|         mBorrowedFromUs.clear(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeItemModel::update() | ||||
|     { | ||||
|         mSourceModel->update(); | ||||
| 
 | ||||
|         int services = 0; | ||||
|         if (!mMerchant.isEmpty()) | ||||
|             services = MWWorld::Class::get(mMerchant).getServices(mMerchant); | ||||
| 
 | ||||
|         mItems.clear(); | ||||
|         // add regular items
 | ||||
|         for (size_t i=0; i<mSourceModel->getItemCount(); ++i) | ||||
|         { | ||||
|             ItemStack item = mSourceModel->getItem(i); | ||||
|             MWWorld::Ptr base = item.mBase; | ||||
|             if (!mMerchant.isEmpty() && Misc::StringUtils::ciEqual(base.getCellRef().mRefID, "gold_001")) | ||||
|                 continue; | ||||
|             if (!mMerchant.isEmpty() && !MWWorld::Class::get(base).canSell(base, services)) | ||||
|                 continue; | ||||
| 
 | ||||
|             // don't show equipped items
 | ||||
|             if (mMerchant.getTypeName() == typeid(ESM::NPC).name()) | ||||
|             { | ||||
|                 bool isEquipped = false; | ||||
|                 MWWorld::InventoryStore& store = MWWorld::Class::get(mMerchant).getInventoryStore(mMerchant); | ||||
|                 for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot) | ||||
|                 { | ||||
|                     MWWorld::ContainerStoreIterator equipped = store.getSlot(slot); | ||||
|                     if (equipped == store.end()) | ||||
|                         continue; | ||||
|                     if (*equipped == base) | ||||
|                         isEquipped = true; | ||||
|                 } | ||||
|                 if (isEquipped) | ||||
|                     continue; | ||||
|             } | ||||
| 
 | ||||
|             // don't show items that we borrowed to someone else
 | ||||
|             std::vector<ItemStack>::iterator it = mBorrowedFromUs.begin(); | ||||
|             for (; it != mBorrowedFromUs.end(); ++it) | ||||
|             { | ||||
|                 if (it->stacks(item)) | ||||
|                 { | ||||
|                     if (item.mCount < it->mCount) | ||||
|                         throw std::runtime_error("Lent more items than present"); | ||||
|                     item.mCount -= it->mCount; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (item.mCount > 0) | ||||
|                 mItems.push_back(item); | ||||
|         } | ||||
| 
 | ||||
|         // add items borrowed to us
 | ||||
|         std::vector<ItemStack>::iterator it = mBorrowedToUs.begin(); | ||||
|         for (; it != mBorrowedToUs.end(); ++it) | ||||
|         { | ||||
|             ItemStack item = *it; | ||||
|             item.mType = ItemStack::Type_Barter; | ||||
|             mItems.push_back(item); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										53
									
								
								apps/openmw/mwgui/tradeitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								apps/openmw/mwgui/tradeitemmodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| #ifndef MWGUI_TRADE_ITEM_MODEL_H | ||||
| #define MWGUI_TRADE_ITEM_MODEL_H | ||||
| 
 | ||||
| #include "itemmodel.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
| 
 | ||||
|     class ItemModel; | ||||
| 
 | ||||
|     /// @brief An item model that allows 'borrowing' items from another item model. Used for previewing barter offers.
 | ||||
|     /// Also filters items that the merchant does not sell.
 | ||||
|     class TradeItemModel : public ProxyItemModel | ||||
|     { | ||||
|     public: | ||||
|         TradeItemModel (ItemModel* sourceModel, const MWWorld::Ptr& merchant); | ||||
| 
 | ||||
|         virtual ItemStack getItem (ModelIndex index); | ||||
|         virtual size_t getItemCount(); | ||||
| 
 | ||||
|         virtual void update(); | ||||
| 
 | ||||
|         void borrowItemFromUs (ModelIndex itemIndex, size_t count); | ||||
| 
 | ||||
|         void borrowItemToUs (ModelIndex itemIndex, ItemModel* source, size_t count); | ||||
|         ///< @note itemIndex points to an item in \a source
 | ||||
| 
 | ||||
|         void returnItemBorrowedToUs (ModelIndex itemIndex, size_t count); | ||||
| 
 | ||||
|         void returnItemBorrowedFromUs (ModelIndex itemIndex, ItemModel* source, size_t count); | ||||
| 
 | ||||
|         /// Permanently transfers items that were borrowed to us from another model to this model
 | ||||
|         void transferItems (); | ||||
|         /// Aborts trade
 | ||||
|         void abort(); | ||||
| 
 | ||||
|         std::vector<ItemStack> getItemsBorrowedToUs(); | ||||
| 
 | ||||
|     private: | ||||
|         void borrowImpl(const ItemStack& item, std::vector<ItemStack>& out); | ||||
|         void unborrowImpl(const ItemStack& item, size_t count, std::vector<ItemStack>& out); | ||||
| 
 | ||||
|         std::vector<ItemStack> mItems; | ||||
| 
 | ||||
|         std::vector<ItemStack> mBorrowedToUs; | ||||
|         std::vector<ItemStack> mBorrowedFromUs; | ||||
| 
 | ||||
|         MWWorld::Ptr mMerchant; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -10,6 +10,8 @@ | |||
| #include "../mwbase/dialoguemanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/manualref.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| #include "../mwworld/containerstore.hpp" | ||||
| 
 | ||||
| #include "../mwmechanics/creaturestats.hpp" | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
|  | @ -17,28 +19,24 @@ | |||
| #include "../mwworld/player.hpp" | ||||
| 
 | ||||
| #include "inventorywindow.hpp" | ||||
| #include "itemview.hpp" | ||||
| #include "sortfilteritemmodel.hpp" | ||||
| #include "containeritemmodel.hpp" | ||||
| #include "tradeitemmodel.hpp" | ||||
| #include "countdialog.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     const float TradeWindow::sBalanceChangeInitialPause = 0.5; | ||||
|     const float TradeWindow::sBalanceChangeInterval = 0.1; | ||||
| 
 | ||||
|     TradeWindow::TradeWindow() : | ||||
|         WindowBase("openmw_trade_window.layout") | ||||
|         , ContainerBase(NULL) // no drag&drop
 | ||||
|     TradeWindow::TradeWindow() | ||||
|         : WindowBase("openmw_trade_window.layout") | ||||
|         , mCurrentBalance(0) | ||||
|         , mBalanceButtonsState(BBS_None) | ||||
|         , mBalanceChangePause(0.0) | ||||
|         , mItemToSell(-1) | ||||
|     { | ||||
|         // items the NPC is wearing should not be for trade
 | ||||
|         mDisplayEquippedItems = false; | ||||
| 
 | ||||
|         MyGUI::ScrollView* itemView; | ||||
|         MyGUI::Widget* containerWidget; | ||||
|         getWidget(containerWidget, "Items"); | ||||
|         getWidget(itemView, "ItemView"); | ||||
|         setWidgets(containerWidget, itemView); | ||||
| 
 | ||||
|         getWidget(mFilterAll, "AllButton"); | ||||
|         getWidget(mFilterWeapon, "WeaponButton"); | ||||
|         getWidget(mFilterApparel, "ApparelButton"); | ||||
|  | @ -56,6 +54,9 @@ namespace MWGui | |||
|         getWidget(mTotalBalanceLabel, "TotalBalanceLabel"); | ||||
|         getWidget(mBottomPane, "BottomPane"); | ||||
| 
 | ||||
|         getWidget(mItemView, "ItemView"); | ||||
|         mItemView->eventItemClicked += MyGUI::newDelegate(this, &TradeWindow::onItemSelected); | ||||
| 
 | ||||
|         mFilterAll->setStateSelected(true); | ||||
| 
 | ||||
|         mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); | ||||
|  | @ -73,40 +74,40 @@ namespace MWGui | |||
|         mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased); | ||||
| 
 | ||||
|         setCoord(400, 0, 400, 300); | ||||
| 
 | ||||
|         static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &TradeWindow::onWindowResize); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::startTrade(MWWorld::Ptr actor) | ||||
|     void TradeWindow::startTrade(const MWWorld::Ptr& actor) | ||||
|     { | ||||
|         mPtr = actor; | ||||
|         setTitle(MWWorld::Class::get(actor).getName(actor)); | ||||
| 
 | ||||
|         mCurrentBalance = 0; | ||||
|         mCurrentMerchantOffer = 0; | ||||
| 
 | ||||
|         MWBase::Environment::get().getWindowManager()->getInventoryWindow()->startTrade(); | ||||
|         std::vector<MWWorld::Ptr> itemSources; | ||||
|         MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); | ||||
|         // Important: actor goes last, so that items purchased by the merchant go into his inventory
 | ||||
|         itemSources.push_back(actor); | ||||
| 
 | ||||
|         mBoughtItems.clear(); | ||||
| 
 | ||||
|         ContainerBase::openContainer(actor); | ||||
|         mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources), mPtr); | ||||
|         mSortModel = new SortFilterItemModel(mTradeModel); | ||||
|         mItemView->setModel (mSortModel); | ||||
| 
 | ||||
|         updateLabels(); | ||||
| 
 | ||||
|         drawItems(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         if (_sender == mFilterAll) | ||||
|             setFilter(ContainerBase::Filter_All); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_All); | ||||
|         else if (_sender == mFilterWeapon) | ||||
|             setFilter(ContainerBase::Filter_Weapon); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Weapon); | ||||
|         else if (_sender == mFilterApparel) | ||||
|             setFilter(ContainerBase::Filter_Apparel); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Apparel); | ||||
|         else if (_sender == mFilterMagic) | ||||
|             setFilter(ContainerBase::Filter_Magic); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Magic); | ||||
|         else if (_sender == mFilterMisc) | ||||
|             setFilter(ContainerBase::Filter_Misc); | ||||
|             mSortModel->setCategory(SortFilterItemModel::Category_Misc); | ||||
| 
 | ||||
|         mFilterAll->setStateSelected(false); | ||||
|         mFilterWeapon->setStateSelected(false); | ||||
|  | @ -115,18 +116,91 @@ namespace MWGui | |||
|         mFilterMisc->setStateSelected(false); | ||||
| 
 | ||||
|         static_cast<MyGUI::Button*>(_sender)->setStateSelected(true); | ||||
| 
 | ||||
|         mItemView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::onWindowResize(MyGUI::Window* _sender) | ||||
|     int TradeWindow::getMerchantServices() | ||||
|     { | ||||
|         drawItems(); | ||||
|         return MWWorld::Class::get(mPtr).getServices(mPtr); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::onItemSelected (int index) | ||||
|     { | ||||
|         const ItemStack& item = mSortModel->getItem(index); | ||||
| 
 | ||||
|         MWWorld::Ptr object = item.mBase; | ||||
|         int count = item.mCount; | ||||
|         bool shift = MyGUI::InputManager::getInstance().isShiftPressed(); | ||||
|         if (MyGUI::InputManager::getInstance().isControlPressed()) | ||||
|             count = 1; | ||||
| 
 | ||||
|         if (count > 1 && !shift) | ||||
|         { | ||||
|             CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); | ||||
|             std::string message = "#{sQuanityMenuMessage02}"; | ||||
|             dialog->open(MWWorld::Class::get(object).getName(object), message, count); | ||||
|             dialog->eventOkClicked.clear(); | ||||
|             dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::sellItem); | ||||
|             mItemToSell = mSortModel->mapToSource(index); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             mItemToSell = mSortModel->mapToSource(index); | ||||
|             sellItem (NULL, count); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::sellItem(MyGUI::Widget* sender, int count) | ||||
|     { | ||||
|         const ItemStack& item = mTradeModel->getItem(mItemToSell); | ||||
|         std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); | ||||
|         MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); | ||||
| 
 | ||||
|         TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel(); | ||||
| 
 | ||||
|         if (item.mType == ItemStack::Type_Barter) | ||||
|         { | ||||
|             // this was an item borrowed to us by the player
 | ||||
|             mTradeModel->returnItemBorrowedToUs(mItemToSell, count); | ||||
|             playerTradeModel->returnItemBorrowedFromUs(mItemToSell, mTradeModel, count); | ||||
|             buyFromNpc(item.mBase, count, true); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // borrow item to player
 | ||||
|             playerTradeModel->borrowItemToUs(mItemToSell, mTradeModel, count); | ||||
|             mTradeModel->borrowItemFromUs(mItemToSell, count); | ||||
|             buyFromNpc(item.mBase, count, false); | ||||
|         } | ||||
| 
 | ||||
|         MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); | ||||
|         mItemView->update(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::borrowItem (int index, size_t count) | ||||
|     { | ||||
|         TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel(); | ||||
|         mTradeModel->borrowItemToUs(index, playerTradeModel, count); | ||||
|         mItemView->update(); | ||||
|         sellToNpc(playerTradeModel->getItem(index).mBase, count, false); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::returnItem (int index, size_t count) | ||||
|     { | ||||
|         TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel(); | ||||
|         const ItemStack& item = playerTradeModel->getItem(index); | ||||
|         mTradeModel->returnItemBorrowedFromUs(index, playerTradeModel, count); | ||||
|         mItemView->update(); | ||||
|         sellToNpc(item.mBase, count, true); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::addOrRemoveGold(int amount) | ||||
|     { | ||||
|         bool goldFound = false; | ||||
|         MWWorld::Ptr gold; | ||||
|         MWWorld::ContainerStore& playerStore = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getContainerStore(); | ||||
|         MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); | ||||
|         MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); | ||||
| 
 | ||||
|         for (MWWorld::ContainerStoreIterator it = playerStore.begin(); | ||||
|                 it != playerStore.end(); ++it) | ||||
|  | @ -167,13 +241,15 @@ namespace MWGui | |||
| 
 | ||||
|     void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         TradeItemModel* playerItemModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel(); | ||||
| 
 | ||||
|         const MWWorld::Store<ESM::GameSetting> &gmst = | ||||
|             MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); | ||||
| 
 | ||||
|         // were there any items traded at all?
 | ||||
|         MWWorld::ContainerStore& playerBought = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getBoughtItems(); | ||||
|         MWWorld::ContainerStore& merchantBought = getBoughtItems(); | ||||
|         if (playerBought.begin() == playerBought.end() && merchantBought.begin() == merchantBought.end()) | ||||
|         std::vector<ItemStack> playerBought = playerItemModel->getItemsBorrowedToUs(); | ||||
|         std::vector<ItemStack> merchantBought = mTradeModel->getItemsBorrowedToUs(); | ||||
|         if (!playerBought.size() && !merchantBought.size()) | ||||
|         { | ||||
|             // user notification
 | ||||
|             MWBase::Environment::get().getWindowManager()-> | ||||
|  | @ -250,21 +326,14 @@ namespace MWGui | |||
| 
 | ||||
|             //skill use!
 | ||||
|             MWWorld::Class::get(playerPtr).skillUsageSucceeded(playerPtr, ESM::Skill::Mercantile, 0); | ||||
|     } | ||||
|         } | ||||
| 
 | ||||
|         int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt(); | ||||
|         MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition); | ||||
| 
 | ||||
|         // success! make the item transfer.
 | ||||
|         MWWorld::ContainerStore& playerBoughtItems = | ||||
|             MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getBoughtItems(); | ||||
|         for (MWWorld::ContainerStoreIterator it = playerBoughtItems.begin(); it != playerBoughtItems.end(); ++it) | ||||
|         { | ||||
|             if (Misc::StringUtils::ciEqual(it->getCellRef().mOwner, MWWorld::Class::get(mPtr).getId(mPtr))) | ||||
|                 it->getCellRef().mOwner = ""; | ||||
|         } | ||||
|         transferBoughtItems(); | ||||
|         MWBase::Environment::get().getWindowManager()->getInventoryWindow()->transferBoughtItems(); | ||||
|         // make the item transfer
 | ||||
|         mTradeModel->transferItems(); | ||||
|         playerItemModel->transferItems(); | ||||
| 
 | ||||
|         // add or remove gold from the player.
 | ||||
|         if (mCurrentBalance != 0) | ||||
|  | @ -278,11 +347,8 @@ namespace MWGui | |||
| 
 | ||||
|     void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) | ||||
|     { | ||||
|         // i give you back your stuff!
 | ||||
|         returnBoughtItems(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getContainerStore()); | ||||
|         // now gimme back my stuff!
 | ||||
|         MWBase::Environment::get().getWindowManager()->getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); | ||||
| 
 | ||||
|         mTradeModel->abort(); | ||||
|         MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel()->abort(); | ||||
|         MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); | ||||
|     } | ||||
| 
 | ||||
|  | @ -343,44 +409,7 @@ namespace MWGui | |||
|         mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast<std::string>(getMerchantGold())); | ||||
|     } | ||||
| 
 | ||||
|     bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) | ||||
|     { | ||||
|         if (Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")) | ||||
|             return false; | ||||
| 
 | ||||
|         int services = 0; | ||||
|         if (mPtr.getTypeName() == typeid(ESM::NPC).name()) | ||||
|         { | ||||
|             MWWorld::LiveCellRef<ESM::NPC>* ref = mPtr.get<ESM::NPC>(); | ||||
|             if (ref->mBase->mHasAI) | ||||
|                 services = ref->mBase->mAiData.mServices; | ||||
|         } | ||||
|         else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) | ||||
|         { | ||||
|             MWWorld::LiveCellRef<ESM::Creature>* ref = mPtr.get<ESM::Creature>(); | ||||
|             if (ref->mBase->mHasAI) | ||||
|                 services = ref->mBase->mAiData.mServices; | ||||
|         } | ||||
| 
 | ||||
|         return MWWorld::Class::get(item).canSell(item, services); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore() | ||||
|     { | ||||
|         std::vector<MWWorld::Ptr> items; | ||||
|         MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); | ||||
| 
 | ||||
|         for (MWWorld::ContainerStoreIterator it = invStore.begin(); | ||||
|                 it != invStore.end(); ++it) | ||||
|         { | ||||
|             if (!npcAcceptsItem(*it)) | ||||
|                 items.push_back(*it); | ||||
|         } | ||||
| 
 | ||||
|         return items; | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::sellToNpc(MWWorld::Ptr item, int count, bool boughtItem) | ||||
|     void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem) | ||||
|     { | ||||
|         int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, boughtItem); | ||||
| 
 | ||||
|  | @ -390,7 +419,7 @@ namespace MWGui | |||
|         updateLabels(); | ||||
|     } | ||||
| 
 | ||||
|     void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count, bool soldItem) | ||||
|     void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem) | ||||
|     { | ||||
|         int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, !soldItem); | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,23 +17,32 @@ namespace MWGui | |||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|     class TradeWindow : public ContainerBase, public WindowBase | ||||
|     class ItemView; | ||||
|     class SortFilterItemModel; | ||||
|     class TradeItemModel; | ||||
| 
 | ||||
|     class TradeWindow : public WindowBase, public ReferenceInterface | ||||
|     { | ||||
|         public: | ||||
|             TradeWindow(); | ||||
| 
 | ||||
|             void startTrade(MWWorld::Ptr actor); | ||||
| 
 | ||||
|             void sellToNpc(MWWorld::Ptr item, int count, bool boughtItem); ///< only used for adjusting the gold balance
 | ||||
|             void buyFromNpc(MWWorld::Ptr item, int count, bool soldItem); ///< only used for adjusting the gold balance
 | ||||
| 
 | ||||
|             bool npcAcceptsItem(MWWorld::Ptr item); | ||||
|             void startTrade(const MWWorld::Ptr& actor); | ||||
| 
 | ||||
|             void addOrRemoveGold(int gold); | ||||
| 
 | ||||
|             void onFrame(float frameDuration); | ||||
| 
 | ||||
|         protected: | ||||
|             void borrowItem (int index, size_t count); | ||||
|             void returnItem (int index, size_t count); | ||||
| 
 | ||||
|             int getMerchantServices(); | ||||
| 
 | ||||
| 
 | ||||
|         private: | ||||
|             ItemView* mItemView; | ||||
|             SortFilterItemModel* mSortModel; | ||||
|             TradeItemModel* mTradeModel; | ||||
| 
 | ||||
|             static const float sBalanceChangeInitialPause; // in seconds
 | ||||
|             static const float sBalanceChangeInterval; // in seconds
 | ||||
| 
 | ||||
|  | @ -56,6 +65,8 @@ namespace MWGui | |||
|             MyGUI::TextBox* mPlayerGold; | ||||
|             MyGUI::TextBox* mMerchantGold; | ||||
| 
 | ||||
|             int mItemToSell; | ||||
| 
 | ||||
|             int mCurrentBalance; | ||||
|             int mCurrentMerchantOffer; | ||||
| 
 | ||||
|  | @ -67,7 +78,12 @@ namespace MWGui | |||
|             /// pause before next balance change will trigger while user holds +/- button pressed
 | ||||
|             float mBalanceChangePause; | ||||
| 
 | ||||
|             void onWindowResize(MyGUI::Window* _sender); | ||||
|             void sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem); ///< only used for adjusting the gold balance
 | ||||
|             void buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem); ///< only used for adjusting the gold balance
 | ||||
| 
 | ||||
|             void onItemSelected (int index); | ||||
|             void sellItem (MyGUI::Widget* sender, int count); | ||||
| 
 | ||||
|             void onFilterChanged(MyGUI::Widget* _sender); | ||||
|             void onOfferButtonClicked(MyGUI::Widget* _sender); | ||||
|             void onCancelButtonClicked(MyGUI::Widget* _sender); | ||||
|  | @ -79,16 +95,10 @@ namespace MWGui | |||
|             void onIncreaseButtonTriggered(); | ||||
|             void onDecreaseButtonTriggered(); | ||||
| 
 | ||||
|             virtual bool isTrading() { return true; } | ||||
|             virtual bool isTradeWindow() { return true; } | ||||
| 
 | ||||
|             virtual std::vector<MWWorld::Ptr> itemsToIgnore(); | ||||
| 
 | ||||
|             void updateLabels(); | ||||
| 
 | ||||
|             virtual void onReferenceUnavailable(); | ||||
| 
 | ||||
|         private: | ||||
|             int getMerchantGold(); | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "../mwbase/mechanicsmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "../mwmechanics/npcstats.hpp" | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "../mwbase/mechanicsmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/player.hpp" | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "inventorywindow.hpp" | ||||
| #include "tradewindow.hpp" | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ | |||
| 
 | ||||
| #include "../mwbase/inputmanager.hpp" | ||||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "console.hpp" | ||||
| #include "journalwindow.hpp" | ||||
| #include "journalviewmodel.hpp" | ||||
|  | @ -39,6 +41,7 @@ | |||
| #include "companionwindow.hpp" | ||||
| #include "inventorywindow.hpp" | ||||
| #include "bookpage.hpp" | ||||
| #include "itemview.hpp" | ||||
| 
 | ||||
| namespace MWGui | ||||
| { | ||||
|  | @ -123,6 +126,7 @@ namespace MWGui | |||
|         MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget"); | ||||
|         MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollView>("Widget"); | ||||
|         BookPage::registerMyGUIComponents (); | ||||
|         ItemView::registerComponents(); | ||||
| 
 | ||||
|         MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); | ||||
|         MyGUI::ResourceManager::getInstance().load("core.xml"); | ||||
|  | @ -302,6 +306,7 @@ namespace MWGui | |||
|         mMerchantRepair->setVisible(false); | ||||
|         mRepair->setVisible(false); | ||||
|         mCompanionWindow->setVisible(false); | ||||
|         mInventoryWindow->setTrading(false); | ||||
| 
 | ||||
|         mHud->setVisible(mHudEnabled); | ||||
| 
 | ||||
|  | @ -411,6 +416,7 @@ namespace MWGui | |||
|                 break; | ||||
|             case GM_Barter: | ||||
|                 mInventoryWindow->setVisible(true); | ||||
|                 mInventoryWindow->setTrading(true); | ||||
|                 mTradeWindow->setVisible(true); | ||||
|                 break; | ||||
|             case GM_SpellBuying: | ||||
|  | @ -632,17 +638,6 @@ namespace MWGui | |||
|         return default_; | ||||
|     } | ||||
| 
 | ||||
|     void WindowManager::onDialogueWindowBye() | ||||
|     { | ||||
|         if (mDialogueWindow) | ||||
|         { | ||||
|             //FIXME set some state and stuff?
 | ||||
|             //removeDialog(dialogueWindow);
 | ||||
|             mDialogueWindow->setVisible(false); | ||||
|         } | ||||
|         removeGuiMode(GM_Dialogue); | ||||
|     } | ||||
| 
 | ||||
|     void WindowManager::onFrame (float frameDuration) | ||||
|     { | ||||
|         mMessageBoxManager->onFrame(frameDuration); | ||||
|  | @ -677,6 +672,7 @@ namespace MWGui | |||
|         mContainerWindow->checkReferenceAvailable(); | ||||
|         mCompanionWindow->checkReferenceAvailable(); | ||||
|         mConsole->checkReferenceAvailable(); | ||||
|         mCompanionWindow->onFrame(); | ||||
|     } | ||||
| 
 | ||||
|     void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) | ||||
|  |  | |||
|  | @ -327,8 +327,6 @@ namespace MWGui | |||
|     unsigned int mTriangleCount; | ||||
|     unsigned int mBatchCount; | ||||
| 
 | ||||
|     void onDialogueWindowBye(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, | ||||
|      * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result | ||||
|  |  | |||
|  | @ -52,6 +52,11 @@ namespace MWWorld | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     int Class::getServices(const Ptr &actor) const | ||||
|     { | ||||
|         throw std::runtime_error ("class does not have services"); | ||||
|     } | ||||
| 
 | ||||
|     MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const | ||||
|     { | ||||
|         throw std::runtime_error ("class does not have creature stats"); | ||||
|  | @ -172,6 +177,11 @@ namespace MWWorld | |||
|         throw std::runtime_error ("capacity not supported by this class"); | ||||
|     } | ||||
| 
 | ||||
|     float Class::getWeight(const Ptr &ptr) const | ||||
|     { | ||||
|         throw std::runtime_error ("weight not supported by this class"); | ||||
|     } | ||||
| 
 | ||||
|     float Class::getEncumbrance (const MWWorld::Ptr& ptr) const | ||||
|     { | ||||
|         throw std::runtime_error ("encumbrance not supported by class"); | ||||
|  |  | |||
|  | @ -241,6 +241,8 @@ namespace MWWorld | |||
|             virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; | ||||
|             ///< Determine whether or not \a item can be sold to an npc with the given \a npcServices
 | ||||
| 
 | ||||
|             virtual int getServices (const MWWorld::Ptr& actor) const; | ||||
| 
 | ||||
|             virtual std::string getModel(const MWWorld::Ptr &ptr) const; | ||||
| 
 | ||||
|             virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; | ||||
|  | @ -249,6 +251,8 @@ namespace MWWorld | |||
|             ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
 | ||||
|             ///  Second item in the pair specifies the error message
 | ||||
| 
 | ||||
|             virtual float getWeight (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual Ptr | ||||
|             copyToCell(const Ptr &ptr, CellStore &cell) const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -60,8 +60,8 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) | |||
| { | ||||
|     /// \todo add current enchantment charge here when it is implemented
 | ||||
|     if (  ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID | ||||
|         && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
 | ||||
|         && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
 | ||||
|           && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
 | ||||
|           && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
 | ||||
|         && ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner | ||||
|         && ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul | ||||
|           // item that is already partly used up never stacks
 | ||||
|  |  | |||
|  | @ -79,11 +79,10 @@ namespace MWWorld | |||
|             ContainerStoreIterator addImpl (const Ptr& ptr); | ||||
|             ///< Add the item to this container (no stacking)
 | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|             virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2); | ||||
|             ///< @return true if the two specified objects can stack with each other
 | ||||
|             /// @note ptr1 is the item that is already in this container
 | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|             void fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store); | ||||
|             ///< Insert items into *this.
 | ||||
|  |  | |||
|  | @ -276,6 +276,8 @@ bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) | |||
|     { | ||||
|         if (*iter != end() && ptr1 == **iter) | ||||
|             return false; | ||||
|         if (*iter != end() && ptr2 == **iter) | ||||
|             return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
|  |  | |||
|  | @ -90,8 +90,6 @@ namespace MWWorld | |||
|             ///< \attention This function is internal to the world model and should not be called from
 | ||||
|             /// outside.
 | ||||
| 
 | ||||
|         protected: | ||||
| 
 | ||||
|             virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2); | ||||
|             ///< @return true if the two specified objects can stack with each other
 | ||||
|             /// @note ptr1 is the item that is already in this container
 | ||||
|  |  | |||
|  | @ -1653,4 +1653,22 @@ namespace MWWorld | |||
|         else | ||||
|             return 0.f; | ||||
|     } | ||||
| 
 | ||||
|     void World::getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) | ||||
|     { | ||||
|         std::string refId = npc.getCellRef().mRefID; | ||||
| 
 | ||||
|         const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); | ||||
|         for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) | ||||
|         { | ||||
|             MWWorld::CellRefList<ESM::Container>& containers = (*cellIt)->mContainers; | ||||
|             CellRefList<ESM::Container>::List& refList = containers.mList; | ||||
|             for (CellRefList<ESM::Container>::List::iterator container = refList.begin(); container != refList.end(); ++container) | ||||
|             { | ||||
|                 MWWorld::Ptr ptr (&*container, *cellIt); | ||||
|                 if (Misc::StringUtils::ciEqual(ptr.getCellRef().mOwner, npc.getCellRef().mRefID)) | ||||
|                     out.push_back(ptr); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -390,6 +390,9 @@ namespace MWWorld | |||
|             virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object
 | ||||
|             virtual float getWindSpeed(); | ||||
| 
 | ||||
|             virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out); | ||||
|             ///< get all containers in active cells owned by this Npc
 | ||||
| 
 | ||||
|             virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); | ||||
| 
 | ||||
|             virtual int canRest(); | ||||
|  |  | |||
|  | @ -59,11 +59,7 @@ | |||
|         </Widget> | ||||
| 
 | ||||
|         <!-- Available ingredients --> | ||||
|         <Widget type="Widget" skin="MW_Box" position="8 126 247 238" name="box" align="Left Top Stretch"> | ||||
|             <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 239 230" name="ItemView" align="Left Top Stretch"> | ||||
|                 <Property key="CanvasAlign" value="Left Top"/> | ||||
|                 <Widget type="Button" skin="" name="Items" position="0 0 239 230" name="Items" align="Left Top Stretch"/> | ||||
|             </Widget> | ||||
|         <Widget type="ItemView" skin="MW_ItemView" position="8 126 247 238" name="ItemView" align="Left Top Stretch"> | ||||
|         </Widget> | ||||
| 
 | ||||
|         <!-- Created effects --> | ||||
|  |  | |||
|  | @ -4,11 +4,7 @@ | |||
|     <Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 600 300" name="_Main"> | ||||
| 
 | ||||
|         <!-- Items --> | ||||
|         <Widget type="Widget" skin="MW_Box" position="5 5 575 225" name="box" align="Left Top Stretch"> | ||||
|             <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 567 217" name="ItemView" align="Left Top Stretch"> | ||||
|                 <Property key="CanvasAlign" value="Left Top"/> | ||||
|                 <Widget type="Button" skin="" name="Items" position="0 0 567 217" name="Items" align="Left Top Stretch"/> | ||||
|             </Widget> | ||||
|         <Widget type="ItemView" skin="MW_ItemView" position="5 5 575 225" name="ItemView" align="Left Top Stretch"> | ||||
|         </Widget> | ||||
| 
 | ||||
|         <Widget type="HBox" position="5 235 575 24" align="Bottom HStretch"> | ||||
|  |  | |||
|  | @ -4,11 +4,7 @@ | |||
|     <Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 600 300" name="_Main"> | ||||
| 
 | ||||
|         <!-- Items --> | ||||
|         <Widget type="Widget" skin="MW_Box" position="5 5 575 225" name="box" align="Left Top Stretch"> | ||||
|             <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 567 217" name="ItemView" align="Left Top Stretch"> | ||||
|                 <Property key="CanvasAlign" value="Left Top"/> | ||||
|                 <Widget type="Button" skin="" name="Items" position="0 0 567 217" name="Items" align="Left Top Stretch"/> | ||||
|             </Widget> | ||||
|         <Widget type="ItemView" skin="MW_ItemView" position="5 5 575 225" name="ItemView" align="Left Top Stretch"> | ||||
|         </Widget> | ||||
| 
 | ||||
|         <Widget type="HBox" position="0 235 580 24" align="Right Bottom"> | ||||
|  |  | |||
|  | @ -25,11 +25,7 @@ | |||
|         <Widget type="Widget" skin="" position="228 0 350 223" align="Left Top" name="RightPane"> | ||||
| 
 | ||||
|             <!-- Items in inventory --> | ||||
|             <Widget type="Widget" skin="MW_Box" position="0 38 350 185" name="box" align="Left Top Stretch"> | ||||
|                 <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 342 177" align="Left Top Stretch" name="ItemView"> | ||||
|                     <Property key="CanvasAlign" value="Left Top"/> | ||||
|                     <Widget type="Button" skin="" name="Items" position="0 0 342 177" name="Items" align="Left Top Stretch"/> | ||||
|                 </Widget> | ||||
|             <Widget type="ItemView" skin="MW_ItemView" position="0 38 350 185" name="ItemView" align="Left Top Stretch"> | ||||
|             </Widget> | ||||
| 
 | ||||
|             <!-- Categories --> | ||||
|  |  | |||
|  | @ -4,11 +4,7 @@ | |||
| 
 | ||||
|         <Widget type="TextBox" skin="SandText" position="8 8 300 18" name="Label"/> | ||||
| 
 | ||||
|         <Widget type="Widget" skin="MW_Box" position="8 34 355 70" name="box" align="Left Top Stretch"> | ||||
|             <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 347 62" name="ItemView" align="Left Top Stretch"> | ||||
|                 <Property key="CanvasAlign" value="Left Top"/> | ||||
|                 <Widget type="Button" skin="" name="Items" position="0 0 347 62" name="Items" align="Left Top Stretch"/> | ||||
|             </Widget> | ||||
|         <Widget type="ItemView" skin="MW_ItemView" position="8 34 355 70" name="ItemView" align="Left Top Stretch"> | ||||
|         </Widget> | ||||
| 
 | ||||
|         <Widget type="AutoSizedButton" skin="MW_Button" position="340 110 24 24" name="CancelButton"> | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
|     <Layer name="Console" overlapped="false" peek="true"/> | ||||
|     <Layer name="Notification" overlapped="false" peek="false"/> | ||||
|     <Layer name="Popup" overlapped="true" peek="true"/> | ||||
|     <Layer name="DragAndDrop" overlapped="false" peek="true"/> | ||||
|     <Layer name="DragAndDrop" overlapped="false" peek="false"/> | ||||
|     <Layer name="LoadingScreen" overlapped="false" peek="true"/> | ||||
|     <Layer name="Pointer" overlapped="false" peek="false"/> | ||||
| </MyGUI> | ||||
|  |  | |||
|  | @ -126,6 +126,15 @@ | |||
| 
 | ||||
|     </Skin> | ||||
| 
 | ||||
|     <Skin name="MW_ItemView" size="516 516" align="ALIGN_LEFT ALIGN_TOP"> | ||||
|         <Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="ALIGN_STRETCH"/> | ||||
| 
 | ||||
|         <Child type="ScrollView" skin="MW_ScrollViewH" offset="3 3 509 509" align="ALIGN_STRETCH" name="ScrollView"> | ||||
|             <Property key="CanvasAlign" value="Left Top"/> | ||||
|             <Property key="NeedMouse" value="true"/> | ||||
|         </Child> | ||||
|     </Skin> | ||||
| 
 | ||||
|     <Skin name="MW_SimpleList" size="516 516" align="ALIGN_LEFT ALIGN_TOP"> | ||||
| 
 | ||||
|         <Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="ALIGN_STRETCH"/> | ||||
|  |  | |||
|  | @ -24,11 +24,7 @@ | |||
|         </Widget> | ||||
| 
 | ||||
|         <!-- Items --> | ||||
|         <Widget type="Widget" skin="MW_Box" position="8 38 566 185" name="box" align="Left Top Stretch"> | ||||
|             <Widget type="ScrollView" skin="MW_ScrollViewH" position="4 4 558 181" align="Left Top Stretch" name="ItemView"> | ||||
|                 <Property key="CanvasAlign" value="Left Top"/> | ||||
|                 <Widget type="Button" skin="" name="Items" position="0 0 558 181" name="Items" align="Left Top Stretch"/> | ||||
|             </Widget> | ||||
|         <Widget type="ItemView" skin="MW_ItemView" position="8 38 566 185" name="ItemView" align="Left Top Stretch"> | ||||
|         </Widget> | ||||
| 
 | ||||
|         <Widget type="Widget" skin="" position="8 231 566 92" name="BottomPane" align="Left Bottom HStretch"> | ||||
|  |  | |||
|  | @ -612,10 +612,13 @@ namespace Physic | |||
| 
 | ||||
|         float d1 = 10000.; | ||||
|         btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); | ||||
|         if(raycastingObjectOnly) resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; | ||||
|         else resultCallback1.m_collisionFilterMask = CollisionType_World; | ||||
|         if(raycastingObjectOnly) | ||||
|             resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; | ||||
|         else | ||||
|             resultCallback1.m_collisionFilterMask = CollisionType_World; | ||||
| 
 | ||||
|         if(!ignoreHeightMap) resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask|| CollisionType_HeightMap; | ||||
|         if(!ignoreHeightMap) | ||||
|             resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap; | ||||
|         dynamicsWorld->rayTest(from, to, resultCallback1); | ||||
|         if (resultCallback1.hasHit()) | ||||
|         { | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue