From e80636f0cafa090b05015f249eb770b5c901722f Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 6 Nov 2016 11:01:46 +0100 Subject: [PATCH] Improve performance of repairing/recharging (Fixes #2493) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/itemchargeview.cpp | 212 ++++++++++++++++++++++ apps/openmw/mwgui/itemchargeview.hpp | 78 ++++++++ apps/openmw/mwgui/recharge.cpp | 92 +++------- apps/openmw/mwgui/recharge.hpp | 6 +- apps/openmw/mwgui/repair.cpp | 99 +++------- apps/openmw/mwgui/repair.hpp | 9 +- apps/openmw/mwgui/sortfilteritemmodel.cpp | 32 ++++ apps/openmw/mwgui/sortfilteritemmodel.hpp | 2 + apps/openmw/mwgui/windowmanagerimp.cpp | 2 + files/mygui/openmw_list.skin.xml | 9 + files/mygui/openmw_recharge_dialog.layout | 32 ++-- files/mygui/openmw_repair.layout | 37 ++-- 13 files changed, 436 insertions(+), 176 deletions(-) create mode 100644 apps/openmw/mwgui/itemchargeview.cpp create mode 100644 apps/openmw/mwgui/itemchargeview.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 332a6f0ac..277acea2d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -42,7 +42,7 @@ add_openmw_dir (mwgui itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview - draganddrop timeadvancer jailscreen + draganddrop timeadvancer jailscreen itemchargeview ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/itemchargeview.cpp b/apps/openmw/mwgui/itemchargeview.cpp new file mode 100644 index 000000000..83517e353 --- /dev/null +++ b/apps/openmw/mwgui/itemchargeview.cpp @@ -0,0 +1,212 @@ +#include "itemchargeview.hpp" + +#include + +#include +#include +#include +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" + +#include "itemmodel.hpp" +#include "itemwidget.hpp" + +namespace MWGui +{ + ItemChargeView::ItemChargeView() + : mScrollView(NULL), + mDisplayMode(DisplayMode_Health) + { + } + + void ItemChargeView::registerComponents() + { + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + } + + void ItemChargeView::initialiseOverride() + { + Base::initialiseOverride(); + + assignWidget(mScrollView, "ScrollView"); + if (mScrollView == NULL) + throw std::runtime_error("Item charge view needs a scroll view"); + + mScrollView->setCanvasAlign(MyGUI::Align::Left | MyGUI::Align::Top); + } + + void ItemChargeView::setModel(ItemModel* model) + { + mModel.reset(model); + } + + void ItemChargeView::setDisplayMode(ItemChargeView::DisplayMode type) + { + mDisplayMode = type; + update(); + } + + void ItemChargeView::update() + { + if (!mModel.get()) + { + layoutWidgets(); + return; + } + + mModel->update(); + + Lines lines; + std::set visitedLines; + + for (size_t i = 0; i < mModel->getItemCount(); ++i) + { + ItemStack stack = mModel->getItem(static_cast(i)); + + bool found = false; + for (Lines::const_iterator iter = mLines.begin(); iter != mLines.end(); ++iter) + { + if (iter->mItemPtr == stack.mBase) + { + found = true; + visitedLines.insert(iter); + + // update line widgets + updateLine(*iter); + lines.push_back(*iter); + break; + } + } + + if (!found) + { + // add line widgets + Line line; + line.mItemPtr = stack.mBase; + + line.mText = mScrollView->createWidget("SandText", MyGUI::IntCoord(), MyGUI::Align::Default); + line.mText->setNeedMouseFocus(false); + + line.mIcon = mScrollView->createWidget("MW_ItemIconSmall", MyGUI::IntCoord(), MyGUI::Align::Default); + line.mIcon->setItem(line.mItemPtr); + line.mIcon->setUserString("ToolTipType", "ItemPtr"); + line.mIcon->setUserData(line.mItemPtr); + line.mIcon->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemChargeView::onIconClicked); + line.mIcon->eventMouseWheel += MyGUI::newDelegate(this, &ItemChargeView::onMouseWheel); + + line.mCharge = mScrollView->createWidget("MW_ChargeBar", MyGUI::IntCoord(), MyGUI::Align::Default); + line.mCharge->setNeedMouseFocus(false); + + updateLine(line); + + lines.push_back(line); + } + } + + for (Lines::iterator iter = mLines.begin(); iter != mLines.end(); ++iter) + { + if (visitedLines.count(iter)) + continue; + + // remove line widgets + MyGUI::Gui::getInstance().destroyWidget(iter->mText); + MyGUI::Gui::getInstance().destroyWidget(iter->mIcon); + MyGUI::Gui::getInstance().destroyWidget(iter->mCharge); + } + + mLines.swap(lines); + + layoutWidgets(); + } + + void ItemChargeView::layoutWidgets() + { + int currentY = 0; + + for (Lines::const_iterator iter = mLines.begin(); iter != mLines.end(); ++iter) + { + iter->mText->setCoord(8, currentY, mScrollView->getWidth()-8, 18); + currentY += 19; + + iter->mIcon->setCoord(16, currentY, 32, 32); + iter->mCharge->setCoord(72, currentY+2, std::max(199, mScrollView->getWidth()-72-38), 20); + currentY += 32 + 4; + } + + // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden + mScrollView->setVisibleVScroll(false); + mScrollView->setCanvasSize(MyGUI::IntSize(mScrollView->getWidth(), std::max(mScrollView->getHeight(), currentY))); + mScrollView->setVisibleVScroll(true); + } + + void ItemChargeView::resetScrollbars() + { + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + } + + void ItemChargeView::setSize(const MyGUI::IntSize& value) + { + bool changed = (value.width != getWidth() || value.height != getHeight()); + Base::setSize(value); + if (changed) + layoutWidgets(); + } + + void ItemChargeView::setCoord(const MyGUI::IntCoord& value) + { + bool changed = (value.width != getWidth() || value.height != getHeight()); + Base::setCoord(value); + if (changed) + layoutWidgets(); + } + + void ItemChargeView::updateLine(const ItemChargeView::Line& line) + { + line.mText->setCaption(line.mItemPtr.getClass().getName(line.mItemPtr)); + + line.mCharge->setVisible(false); + switch (mDisplayMode) + { + case DisplayMode_Health: + if (!line.mItemPtr.getClass().hasItemHealth(line.mItemPtr)) + break; + + line.mCharge->setVisible(true); + line.mCharge->setValue(line.mItemPtr.getClass().getItemHealth(line.mItemPtr), + line.mItemPtr.getClass().getItemMaxHealth(line.mItemPtr)); + break; + case DisplayMode_EnchantmentCharge: + std::string enchId = line.mItemPtr.getClass().getEnchantment(line.mItemPtr); + if (enchId.empty()) + break; + const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get().search(enchId); + if (!ench) + break; + + line.mCharge->setVisible(true); + line.mCharge->setValue(static_cast(line.mItemPtr.getCellRef().getEnchantmentCharge()), + ench->mData.mCharge); + break; + } + } + + void ItemChargeView::onIconClicked(MyGUI::Widget* sender) + { + eventItemClicked(this, *sender->getUserData()); + } + + void ItemChargeView::onMouseWheel(MyGUI::Widget* /*sender*/, int rel) + { + if (mScrollView->getViewOffset().top + rel*0.3f > 0) + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast(mScrollView->getViewOffset().top + rel*0.3f))); + } +} diff --git a/apps/openmw/mwgui/itemchargeview.hpp b/apps/openmw/mwgui/itemchargeview.hpp new file mode 100644 index 000000000..1ff077ef2 --- /dev/null +++ b/apps/openmw/mwgui/itemchargeview.hpp @@ -0,0 +1,78 @@ +#ifndef MWGUI_ITEMCHARGEVIEW_H +#define MWGUI_ITEMCHARGEVIEW_H + +#include +#include + +#include + +#include "../mwworld/ptr.hpp" + +#include "widgets.hpp" + +namespace MyGUI +{ + class TextBox; + class ScrollView; +} + +namespace MWGui +{ + class ItemModel; + class ItemWidget; + + class ItemChargeView : public MyGUI::Widget + { + MYGUI_RTTI_DERIVED(ItemChargeView) + public: + enum DisplayMode + { + DisplayMode_Health, + DisplayMode_EnchantmentCharge + }; + + ItemChargeView(); + + /// Register needed components with MyGUI's factory manager + static void registerComponents(); + + virtual void initialiseOverride(); + + /// Takes ownership of \a model + void setModel(ItemModel* model); + + void setDisplayMode(DisplayMode type); + + void update(); + void layoutWidgets(); + void resetScrollbars(); + + virtual void setSize(const MyGUI::IntSize& value); + virtual void setCoord(const MyGUI::IntCoord& value); + + MyGUI::delegates::CMultiDelegate2 eventItemClicked; + + private: + struct Line + { + MWWorld::Ptr mItemPtr; + MyGUI::TextBox* mText; + ItemWidget* mIcon; + Widgets::MWDynamicStatPtr mCharge; + }; + + void updateLine(const Line& line); + + void onIconClicked(MyGUI::Widget* sender); + void onMouseWheel(MyGUI::Widget* sender, int rel); + + typedef std::vector Lines; + Lines mLines; + + std::auto_ptr mModel; + MyGUI::ScrollView* mScrollView; + DisplayMode mDisplayMode; + }; +} + +#endif diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 1dac7138f..66d29bd59 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include "../mwbase/world.hpp" @@ -21,6 +23,9 @@ #include "widgets.hpp" #include "itemwidget.hpp" +#include "itemchargeview.hpp" +#include "sortfilteritemmodel.hpp" +#include "inventoryitemmodel.hpp" namespace MWGui { @@ -29,13 +34,15 @@ Recharge::Recharge() : WindowBase("openmw_recharge_dialog.layout") { getWidget(mBox, "Box"); - getWidget(mView, "View"); getWidget(mGemBox, "GemBox"); getWidget(mGemIcon, "GemIcon"); getWidget(mChargeLabel, "ChargeLabel"); getWidget(mCancelButton, "CancelButton"); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onCancel); + mBox->eventItemClicked += MyGUI::newDelegate(this, &Recharge::onItemClicked); + + mBox->setDisplayMode(ItemChargeView::DisplayMode_EnchantmentCharge); setVisible(false); } @@ -43,8 +50,13 @@ Recharge::Recharge() void Recharge::open() { center(); + + SortFilterItemModel * model = new SortFilterItemModel(new InventoryItemModel(MWMechanics::getPlayer())); + model->setFilter(SortFilterItemModel::Filter_OnlyRechargable); + mBox->setModel(model); + // Reset scrollbars - mView->setViewOffset(MyGUI::IntPoint(0, 0)); + mBox->resetScrollbars(); } void Recharge::exit() @@ -72,66 +84,16 @@ void Recharge::updateView() bool toolBoxVisible = (gem.getRefData().getCount() != 0); mGemBox->setVisible(toolBoxVisible); + mGemBox->setUserString("Hidden", toolBoxVisible ? "false" : "true"); - bool toolBoxWasVisible = (mBox->getPosition().top != mGemBox->getPosition().top); - - if (toolBoxVisible && !toolBoxWasVisible) - { - // shrink - mBox->setPosition(mBox->getPosition() + MyGUI::IntPoint(0, mGemBox->getSize().height)); - mBox->setSize(mBox->getSize() - MyGUI::IntSize(0,mGemBox->getSize().height)); - } - else if (!toolBoxVisible && toolBoxWasVisible) - { - // expand - mBox->setPosition(MyGUI::IntPoint (mBox->getPosition().left, mGemBox->getPosition().top)); - mBox->setSize(mBox->getSize() + MyGUI::IntSize(0,mGemBox->getSize().height)); - } - - while (mView->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mView->getChildAt(0)); + mBox->update(); - int currentY = 0; + Gui::Box* box = dynamic_cast(mMainWidget); + if (box == NULL) + throw std::runtime_error("main widget must be a box"); - MWWorld::Ptr player = MWMechanics::getPlayer(); - MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); - for (MWWorld::ContainerStoreIterator iter (store.begin()); - iter!=store.end(); ++iter) - { - std::string enchantmentName = iter->getClass().getEnchantment(*iter); - if (enchantmentName.empty()) - continue; - const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find(enchantmentName); - if (iter->getCellRef().getEnchantmentCharge() >= enchantment->mData.mCharge - || iter->getCellRef().getEnchantmentCharge() == -1) - continue; - - MyGUI::TextBox* text = mView->createWidget ( - "SandText", MyGUI::IntCoord(8, currentY, mView->getWidth()-8, 18), MyGUI::Align::Default); - text->setCaption(iter->getClass().getName(*iter)); - text->setNeedMouseFocus(false); - currentY += 19; - - ItemWidget* icon = mView->createWidget ( - "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); - icon->setItem(*iter); - icon->setUserString("ToolTipType", "ItemPtr"); - icon->setUserData(*iter); - icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked); - icon->eventMouseWheel += MyGUI::newDelegate(this, &Recharge::onMouseWheel); - - Widgets::MWDynamicStatPtr chargeWidget = mView->createWidget - ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default); - chargeWidget->setValue(static_cast(iter->getCellRef().getEnchantmentCharge()), enchantment->mData.mCharge); - chargeWidget->setNeedMouseFocus(false); - - currentY += 32 + 4; - } - - // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden - mView->setVisibleVScroll(false); - mView->setCanvasSize (MyGUI::IntSize(mView->getWidth(), std::max(mView->getHeight(), currentY))); - mView->setVisibleVScroll(true); + box->notifyChildrenSizeChanged(); + center(); } void Recharge::onCancel(MyGUI::Widget *sender) @@ -139,15 +101,13 @@ void Recharge::onCancel(MyGUI::Widget *sender) exit(); } -void Recharge::onItemClicked(MyGUI::Widget *sender) +void Recharge::onItemClicked(MyGUI::Widget *sender, const MWWorld::Ptr& item) { MWWorld::Ptr gem = *mGemIcon->getUserData(); if (!gem.getRefData().getCount()) return; - MWWorld::Ptr item = *sender->getUserData(); - MWWorld::Ptr player = MWMechanics::getPlayer(); MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player); @@ -198,12 +158,4 @@ void Recharge::onItemClicked(MyGUI::Widget *sender) updateView(); } -void Recharge::onMouseWheel(MyGUI::Widget* _sender, int _rel) -{ - if (mView->getViewOffset().top + _rel*0.3f > 0) - mView->setViewOffset(MyGUI::IntPoint(0, 0)); - else - mView->setViewOffset(MyGUI::IntPoint(0, static_cast(mView->getViewOffset().top + _rel*0.3f))); -} - } diff --git a/apps/openmw/mwgui/recharge.hpp b/apps/openmw/mwgui/recharge.hpp index 3e8e1269e..bbcf994dd 100644 --- a/apps/openmw/mwgui/recharge.hpp +++ b/apps/openmw/mwgui/recharge.hpp @@ -12,6 +12,7 @@ namespace MWGui { class ItemWidget; +class ItemChargeView; class Recharge : public WindowBase { @@ -25,8 +26,7 @@ public: void start (const MWWorld::Ptr& gem); protected: - MyGUI::Widget* mBox; - MyGUI::ScrollView* mView; + ItemChargeView* mBox; MyGUI::Widget* mGemBox; @@ -38,7 +38,7 @@ protected: void updateView(); - void onItemClicked (MyGUI::Widget* sender); + void onItemClicked (MyGUI::Widget* sender, const MWWorld::Ptr& item); void onCancel (MyGUI::Widget* sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index 49d5735a4..07fd6520c 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -4,6 +4,9 @@ #include #include +#include + +#include #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -17,6 +20,9 @@ #include "widgets.hpp" #include "itemwidget.hpp" +#include "itemchargeview.hpp" +#include "sortfilteritemmodel.hpp" +#include "inventoryitemmodel.hpp" namespace MWGui { @@ -25,7 +31,6 @@ Repair::Repair() : WindowBase("openmw_repair.layout") { getWidget(mRepairBox, "RepairBox"); - getWidget(mRepairView, "RepairView"); getWidget(mToolBox, "ToolBox"); getWidget(mToolIcon, "ToolIcon"); getWidget(mUsesLabel, "UsesLabel"); @@ -33,13 +38,21 @@ Repair::Repair() getWidget(mCancelButton, "CancelButton"); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onCancel); + mRepairBox->eventItemClicked += MyGUI::newDelegate(this, &Repair::onRepairItem); + + mRepairBox->setDisplayMode(ItemChargeView::DisplayMode_Health); } void Repair::open() { center(); + + SortFilterItemModel * model = new SortFilterItemModel(new InventoryItemModel(MWMechanics::getPlayer())); + model->setFilter(SortFilterItemModel::Filter_OnlyRepairable); + mRepairBox->setModel(model); + // Reset scrollbars - mRepairView->setViewOffset(MyGUI::IntPoint(0, 0)); + mRepairBox->resetScrollbars(); } void Repair::exit() @@ -75,89 +88,31 @@ void Repair::updateRepairView() bool toolBoxVisible = (mRepair.getTool().getRefData().getCount() != 0); mToolBox->setVisible(toolBoxVisible); + mToolBox->setUserString("Hidden", toolBoxVisible ? "false" : "true"); + + mRepairBox->update(); - bool toolBoxWasVisible = (mRepairBox->getPosition().top != mToolBox->getPosition().top); - - if (toolBoxVisible && !toolBoxWasVisible) - { - // shrink - mRepairBox->setPosition(mRepairBox->getPosition() + MyGUI::IntPoint(0,mToolBox->getSize().height)); - mRepairBox->setSize(mRepairBox->getSize() - MyGUI::IntSize(0,mToolBox->getSize().height)); - } - else if (!toolBoxVisible && toolBoxWasVisible) - { - // expand - mRepairBox->setPosition(MyGUI::IntPoint (mRepairBox->getPosition().left, mToolBox->getPosition().top)); - mRepairBox->setSize(mRepairBox->getSize() + MyGUI::IntSize(0,mToolBox->getSize().height)); - } - - while (mRepairView->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mRepairView->getChildAt(0)); - - int currentY = 0; - - MWWorld::Ptr player = MWMechanics::getPlayer(); - MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); - int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor; - for (MWWorld::ContainerStoreIterator iter (store.begin(categories)); - iter!=store.end(); ++iter) - { - if (iter->getClass().hasItemHealth(*iter)) - { - int maxDurability = iter->getClass().getItemMaxHealth(*iter); - int durability = iter->getClass().getItemHealth(*iter); - if (maxDurability == durability) - continue; - - MyGUI::TextBox* text = mRepairView->createWidget ( - "SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default); - text->setCaption(iter->getClass().getName(*iter)); - text->setNeedMouseFocus(false); - currentY += 19; - - ItemWidget* icon = mRepairView->createWidget ( - "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); - icon->setItem(*iter); - icon->setUserString("ToolTipType", "ItemPtr"); - icon->setUserData(*iter); - icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem); - icon->eventMouseWheel += MyGUI::newDelegate(this, &Repair::onMouseWheel); - - Widgets::MWDynamicStatPtr chargeWidget = mRepairView->createWidget - ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default); - chargeWidget->setValue(durability, maxDurability); - chargeWidget->setNeedMouseFocus(false); - - currentY += 32 + 4; - } - } - // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden - mRepairView->setVisibleVScroll(false); - mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY))); - mRepairView->setVisibleVScroll(true); + Gui::Box* box = dynamic_cast(mMainWidget); + if (box == NULL) + throw std::runtime_error("main widget must be a box"); + + box->notifyChildrenSizeChanged(); + center(); } -void Repair::onCancel(MyGUI::Widget *sender) +void Repair::onCancel(MyGUI::Widget* /*sender*/) { exit(); } -void Repair::onRepairItem(MyGUI::Widget *sender) +void Repair::onRepairItem(MyGUI::Widget* /*sender*/, const MWWorld::Ptr& ptr) { if (!mRepair.getTool().getRefData().getCount()) return; - mRepair.repair(*sender->getUserData()); + mRepair.repair(ptr); updateRepairView(); } -void Repair::onMouseWheel(MyGUI::Widget* _sender, int _rel) -{ - if (mRepairView->getViewOffset().top + _rel*0.3f > 0) - mRepairView->setViewOffset(MyGUI::IntPoint(0, 0)); - else - mRepairView->setViewOffset(MyGUI::IntPoint(0, static_cast(mRepairView->getViewOffset().top + _rel*0.3f))); -} - } diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index 439ee1169..8746f7dc4 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -9,6 +9,7 @@ namespace MWGui { class ItemWidget; +class ItemChargeView; class Repair : public WindowBase { @@ -22,8 +23,7 @@ public: void startRepairItem (const MWWorld::Ptr& item); protected: - MyGUI::Widget* mRepairBox; - MyGUI::ScrollView* mRepairView; + ItemChargeView* mRepairBox; MyGUI::Widget* mToolBox; @@ -38,9 +38,8 @@ protected: void updateRepairView(); - void onRepairItem (MyGUI::Widget* sender); - void onCancel (MyGUI::Widget* sender); - void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onRepairItem(MyGUI::Widget* sender, const MWWorld::Ptr& ptr); + void onCancel(MyGUI::Widget* sender); }; diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 9c73db340..0d7053404 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -1,5 +1,7 @@ #include "sortfilteritemmodel.hpp" +#include + #include #include @@ -14,9 +16,14 @@ #include #include #include +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/esmstore.hpp" namespace { @@ -139,6 +146,31 @@ namespace MWGui return false; } + if ((mFilter & Filter_OnlyRepairable) && ( + !base.getClass().hasItemHealth(base) + || (base.getClass().getItemHealth(base) == base.getClass().getItemMaxHealth(base)) + || (base.getTypeName() != typeid(ESM::Weapon).name() + && base.getTypeName() != typeid(ESM::Armor).name()))) + return false; + + if (mFilter & Filter_OnlyRechargable) + { + if (!(item.mFlags & ItemStack::Flag_Enchanted)) + return false; + + std::string enchId = base.getClass().getEnchantment(base); + const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get().search(enchId); + if (!ench) + { + std::cerr << "Can't find enchantment '" << enchId << "' on item " << base.getCellRef().getRefId() << std::endl; + return false; + } + + if (base.getCellRef().getEnchantmentCharge() >= ench->mData.mCharge + || base.getCellRef().getEnchantmentCharge() == -1) + return false; + } + return true; } diff --git a/apps/openmw/mwgui/sortfilteritemmodel.hpp b/apps/openmw/mwgui/sortfilteritemmodel.hpp index 064f62e77..3d5396e2a 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.hpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.hpp @@ -39,6 +39,8 @@ namespace MWGui static const int Filter_OnlyEnchantable = (1<<2); static const int Filter_OnlyChargedSoulstones = (1<<3); static const int Filter_OnlyUsableItems = (1<<4); // Only items with a Use action + static const int Filter_OnlyRepairable = (1<<5); + static const int Filter_OnlyRechargable = (1<<6); private: diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 09b72ad3d..5c41fd55b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -109,6 +109,7 @@ #include "container.hpp" #include "controllers.hpp" #include "jailscreen.hpp" +#include "itemchargeview.hpp" namespace MWGui { @@ -223,6 +224,7 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Layer"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); + ItemChargeView::registerComponents(); ItemWidget::registerComponents(); SpellView::registerComponents(); Gui::registerAllWidgets(); diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index ce8209e3d..c1e8114e9 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -157,6 +157,15 @@ + + + + + + + + + diff --git a/files/mygui/openmw_recharge_dialog.layout b/files/mygui/openmw_recharge_dialog.layout index 1b2ad947b..1bf7d9038 100644 --- a/files/mygui/openmw_recharge_dialog.layout +++ b/files/mygui/openmw_recharge_dialog.layout @@ -1,27 +1,37 @@ - + + + - - + + - + + + + + - - - - + + + - - - + + + + + + + + diff --git a/files/mygui/openmw_repair.layout b/files/mygui/openmw_repair.layout index 09a372440..9706a2b92 100644 --- a/files/mygui/openmw_repair.layout +++ b/files/mygui/openmw_repair.layout @@ -1,31 +1,40 @@ - + + + - - + + - + + + - - + + + + - - - - - + + + - - - + + + + + + + +