diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index ff7bb889e..6bf6a589e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -81,6 +81,8 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget); MWWorld::Ptr object = *mSelectedItem->getUserData(); + _unequipItem(object); + int originalCount = object.getRefData().getCount(); object.getRefData().setCount(count); mDragAndDrop->mStore.add(object); @@ -90,6 +92,7 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); mDragAndDrop->mDraggedWidget = mSelectedItem; + static_cast(mSelectedItem)->setImageTexture(""); // remove the background texture (not visible during drag) static_cast(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); @@ -181,9 +184,46 @@ void ContainerBase::drawItems() /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them + std::vector< std::pair > items; + + std::vector equippedItems = getEquippedItems(); + + // filter out the equipped items of categories we don't want + std::vector unwantedItems = equippedItems; for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) + { + std::vector::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::iterator it=unwantedItems.begin(); + it != unwantedItems.end(); ++it) + { + equippedItems.erase(std::find(unwantedItems.begin(), unwantedItems.end(), *it)); + } + // and add the items that are left (= have the correct category) + for (std::vector::const_iterator it=equippedItems.begin(); + it != equippedItems.end(); ++it) + { + items.push_back( std::make_pair(*it, ItemState_Equipped) ); + } + + // now add the regular items + for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) + { + /// \todo sorting + if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()) + items.push_back( std::make_pair(*iter, ItemState_Normal) ); + } + + for (std::vector< std::pair >::const_iterator it=items.begin(); + it != items.end(); ++it) { index++; + const MWWorld::Ptr* iter = &((*it).first); if(iter->getRefData().getCount() > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); @@ -194,7 +234,22 @@ void ContainerBase::drawItems() MyGUI::ImageBox* backgroundWidget = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); backgroundWidget->setUserString("ToolTipType", "ItemPtr"); backgroundWidget->setUserData(*iter); - backgroundWidget->setImageTexture( isMagic ? "textures\\menu_icon_magic.dds" : ""); + + 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"; + } + backgroundTex += ".dds"; + + backgroundWidget->setImageTexture(backgroundTex); backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem); backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 8a1307967..9f994be16 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -63,6 +63,15 @@ namespace MWGui Filter_Misc = 0x05 }; + enum ItemState + { + ItemState_Normal = 0x01, + ItemState_Equipped = 0x02, + + // unimplemented + ItemState_Barter = 0x03 + }; + void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once void openContainer(MWWorld::Ptr container); @@ -87,7 +96,10 @@ namespace MWGui std::string getCountString(const int count); + // to be reimplemented by InventoryWindow virtual bool isInventory() { return false; } + virtual std::vector getEquippedItems() { return std::vector(); } + virtual void _unequipItem(MWWorld::Ptr item) { ; } void drawItems(); }; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 956961b63..e466c34d1 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -151,6 +151,8 @@ namespace MWGui // can't be equipped, try to use instead boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + std::cout << "Item can't be equipped" << std::endl; + // execute action and script MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); @@ -172,19 +174,31 @@ namespace MWGui { // put back in inventory MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - invStore.add(ptr); - // get a ContainerStoreIterator to the item we just re-added into the inventory - MWWorld::ContainerStoreIterator it = invStore.begin(); - MWWorld::ContainerStoreIterator nextIt = ++it; - while (nextIt != invStore.end()) + MWWorld::ContainerStoreIterator it = invStore.add(ptr); + + // retrieve iterator to the item we just re-added (if stacking didn't happen). + // if stacking happened, the iterator was already returned by the add() call + /// \todo this does not work! + if (it == invStore.end()) { - ++it; - ++nextIt; + std::cout << "stacking didn't happen" << std::endl; + for (MWWorld::ContainerStoreIterator it2 = invStore.begin(); + it2 != invStore.end(); ++it2) + { + if (*it2 == ptr) + { + std::cout << "found iterator" << std::endl; + it = it2; + return; + } + } } // equip the item in the first available slot invStore.equip(slots.first.front(), it); + + std::cout << "Equipped item in slot " << slots.first.front() << std::endl; } drawItems(); @@ -197,4 +211,42 @@ namespace MWGui } } + std::vector InventoryWindow::getEquippedItems() + { + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + + std::vector items; + + for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + if (it != invStore.end()) + { + std::cout << "slot " << slot << " is equipped" << std::endl; + items.push_back(*it); + } + else + { + std::cout << "slot " << slot << " is empty " << std::endl; + } + + } + + return items; + } + + void InventoryWindow::_unequipItem(MWWorld::Ptr item) + { + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + + for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + if (it != invStore.end() && *it == item) + { + invStore._freeSlot(slot); + return; + } + } + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index b09ff8521..18dc913fc 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -51,6 +51,8 @@ namespace MWGui void onPinToggled(); virtual bool isInventory() { return true; } + virtual std::vector getEquippedItems(); + virtual void _unequipItem(MWWorld::Ptr item); }; } #endif // Inventory_H diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index ee1b620cd..2e69de9c3 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -58,7 +58,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) return false; } -void MWWorld::ContainerStore::add (const Ptr& ptr) +MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) { int type = getType(ptr); @@ -71,12 +71,13 @@ void MWWorld::ContainerStore::add (const Ptr& ptr) iter->getRefData().setCount( iter->getRefData().getCount() + ptr.getRefData().getCount() ); flagAsModified(); - return; + return iter; } } // if we got here, this means no stacking addImpl(ptr); + return end(); } void MWWorld::ContainerStore::addImpl (const Ptr& ptr) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 3cb3f3bdc..26c9f55a3 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -66,13 +66,15 @@ namespace MWWorld ContainerStoreIterator end(); - void add (const Ptr& ptr); + ContainerStoreIterator add (const Ptr& ptr); ///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed) /// /// \note The item pointed to is not required to exist beyond this function call. /// /// \attention Do not add items to an existing stack by increasing the count instead of /// calling this function! + /// + /// @return if stacking happened, return iterator to the item that was stacked against, otherwise end() iterator protected: void addImpl (const Ptr& ptr); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 3e535793c..b38167d70 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -97,6 +97,13 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); } +void MWWorld::InventoryStore::_freeSlot(int slot) +{ + mSlots[slot] = end(); + + flagAsModified(); +} + MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) { if (slot<0 || slot>=static_cast (mSlots.size())) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 05fc651ee..303604f4d 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -60,6 +60,9 @@ namespace MWWorld void equip (int slot, const ContainerStoreIterator& iterator); ///< \note \a iteartor can be an end-iterator + void _freeSlot(int slot); + ///< this method is dangerous, as it doesn't do re-stacking items - you probably want to use equip() + ContainerStoreIterator getSlot (int slot); void autoEquip (const MWMechanics::NpcStats& stats);