From 6eb15f7680be9c48409cc5c0eeb1e7e413fe6b1d Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 15:24:33 +0200 Subject: [PATCH] auto-select the alchemy tools with highest quality --- apps/openmw/mwgui/alchemywindow.cpp | 173 ++++++++++++++++++++++++++ apps/openmw/mwgui/alchemywindow.hpp | 21 +++- apps/openmw/mwgui/container.cpp | 10 +- apps/openmw/mwgui/container.hpp | 6 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/window_base.cpp | 9 ++ apps/openmw/mwgui/window_base.hpp | 1 + apps/openmw/mwgui/window_manager.cpp | 3 - 9 files changed, 218 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 90326c3d7..60ad123a5 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,15 +1,46 @@ #include "alchemywindow.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" + #include "window_manager.hpp" +namespace +{ + std::string getIconPath(MWWorld::Ptr ptr) + { + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(ptr).getInventoryIcon(ptr); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + return path; + } +} + namespace MWGui { AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager) : WindowBase("openmw_alchemy_window_layout.xml", parWindowManager) + , ContainerBase(0) { getWidget(mCreateButton, "CreateButton"); getWidget(mCancelButton, "CancelButton"); + getWidget(mIngredient1, "Ingredient1"); + getWidget(mIngredient2, "Ingredient2"); + getWidget(mIngredient3, "Ingredient3"); + getWidget(mIngredient4, "Ingredient4"); + getWidget(mApparatus1, "Apparatus1"); + getWidget(mApparatus2, "Apparatus2"); + getWidget(mApparatus3, "Apparatus3"); + getWidget(mApparatus4, "Apparatus4"); + mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); MyGUI::Widget* buttonBox = mCancelButton->getParent(); int cancelButtonWidth = mCancelButton->getTextSize().width + 24; @@ -22,6 +53,12 @@ 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(); } @@ -34,4 +71,140 @@ namespace MWGui void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) { } + + void AlchemyWindow::open() + { + openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + setFilter(ContainerBase::Filter_Ingredients); + + // pick the best available apparatus + MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + MWWorld::Ptr bestAlbemic; + MWWorld::Ptr bestMortarPestle; + MWWorld::Ptr bestCalcinator; + MWWorld::Ptr bestRetort; + + for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus)); + it != store.end(); ++it) + { + ESMS::LiveCellRef* ref = it->get(); + if (ref->base->data.type == ESM::Apparatus::Albemic + && (bestAlbemic.isEmpty() || ref->base->data.quality > bestAlbemic.get()->base->data.quality)) + bestAlbemic = *it; + else if (ref->base->data.type == ESM::Apparatus::MortarPestle + && (bestMortarPestle.isEmpty() || ref->base->data.quality > bestMortarPestle.get()->base->data.quality)) + bestMortarPestle = *it; + else if (ref->base->data.type == ESM::Apparatus::Calcinator + && (bestCalcinator.isEmpty() || ref->base->data.quality > bestCalcinator.get()->base->data.quality)) + bestCalcinator = *it; + else if (ref->base->data.type == ESM::Apparatus::Retort + && (bestRetort.isEmpty() || ref->base->data.quality > bestRetort.get()->base->data.quality)) + bestRetort = *it; + } + + if (!bestMortarPestle.isEmpty()) + { + mApparatus1->setUserString("ToolTipType", "ItemPtr"); + mApparatus1->setUserData(bestMortarPestle); + mApparatus1->setImageTexture(getIconPath(bestMortarPestle)); + } + if (!bestAlbemic.isEmpty()) + { + mApparatus2->setUserString("ToolTipType", "ItemPtr"); + mApparatus2->setUserData(bestAlbemic); + mApparatus2->setImageTexture(getIconPath(bestAlbemic)); + } + if (!bestCalcinator.isEmpty()) + { + mApparatus3->setUserString("ToolTipType", "ItemPtr"); + mApparatus3->setUserData(bestCalcinator); + mApparatus3->setImageTexture(getIconPath(bestCalcinator)); + } + if (!bestRetort.isEmpty()) + { + mApparatus4->setUserString("ToolTipType", "ItemPtr"); + mApparatus4->setUserData(bestRetort); + mApparatus4->setImageTexture(getIconPath(bestRetort)); + } + } + + void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) + { + _sender->clearUserStrings(); + static_cast(_sender)->setImageTexture(""); + if (_sender->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(_sender->getChildAt(0)); + drawItems(); + update(); + } + + void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item) + { + MyGUI::ImageBox* add = NULL; + + if (!mIngredient1->isUserString("ToolTipType")) + add = mIngredient1; + if (add == NULL && !mIngredient2->isUserString("ToolTipType")) + add = mIngredient2; + if (add == NULL && !mIngredient3->isUserString("ToolTipType")) + add = mIngredient3; + if (add == NULL && !mIngredient4->isUserString("ToolTipType")) + add = mIngredient4; + + if (add != NULL) + { + add->setUserString("ToolTipType", "ItemPtr"); + add->setUserData(item); + add->setImageTexture(getIconPath(item)); + drawItems(); + update(); + } + } + + std::vector AlchemyWindow::itemsToIgnore() + { + std::vector ignore; + // don't show ingredients that are currently selected in the "available ingredients" box. + if (mIngredient1->isUserString("ToolTipType")) + ignore.push_back(*mIngredient1->getUserData()); + if (mIngredient2->isUserString("ToolTipType")) + ignore.push_back(*mIngredient2->getUserData()); + if (mIngredient3->isUserString("ToolTipType")) + ignore.push_back(*mIngredient3->getUserData()); + if (mIngredient4->isUserString("ToolTipType")) + ignore.push_back(*mIngredient4->getUserData()); + + return ignore; + } + + void AlchemyWindow::update() + { + // update ingredient count labels + for (int i=0; i<4; ++i) + { + MyGUI::ImageBox* ingredient; + if (i==0) + ingredient = mIngredient1; + else if (i==1) + ingredient = mIngredient2; + else if (i==2) + ingredient = mIngredient3; + else if (i==3) + ingredient = mIngredient4; + + if (!ingredient->isUserString("ToolTipType")) + continue; + + if (ingredient->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); + + MyGUI::TextBox* text = ingredient->createWidget("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(ingredient->getUserData()->getRefData().getCount())); + } + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index d43bb6d33..365ad9642 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -2,20 +2,39 @@ #define MWGUI_ALCHEMY_H #include "window_base.hpp" +#include "container.hpp" namespace MWGui { - class AlchemyWindow : public WindowBase + class AlchemyWindow : public WindowBase, public ContainerBase { public: AlchemyWindow(WindowManager& parWindowManager); + virtual void open(); + protected: MyGUI::Button* mCreateButton; MyGUI::Button* mCancelButton; + MyGUI::ImageBox* mIngredient1; + MyGUI::ImageBox* mIngredient2; + MyGUI::ImageBox* mIngredient3; + MyGUI::ImageBox* mIngredient4; + + MyGUI::ImageBox* mApparatus1; + MyGUI::ImageBox* mApparatus2; + MyGUI::ImageBox* mApparatus3; + MyGUI::ImageBox* mApparatus4; + void onCancelButtonClicked(MyGUI::Widget* _sender); void onCreateButtonClicked(MyGUI::Widget* _sender); + void onIngredientSelected(MyGUI::Widget* _sender); + + virtual void onSelectedItemImpl(MWWorld::Ptr item); + virtual std::vector itemsToIgnore(); + + void update(); }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8ac876c07..6aabeb2c6 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -119,7 +119,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) else onContainerClicked(mContainerWidget); } - else + else if (isTrading()) { MWWorld::Ptr object = (*_sender->getUserData()); int count = object.getRefData().getCount(); @@ -179,6 +179,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) } } } + else + { + onSelectedItemImpl(*_sender->getUserData()); + } } void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) @@ -383,6 +387,8 @@ void ContainerBase::drawItems() + MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light + MWWorld::ContainerStore::Type_Apparatus; } + else if (mFilter == Filter_Ingredients) + categories = MWWorld::ContainerStore::Type_Ingredient; /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them @@ -514,6 +520,7 @@ void ContainerBase::drawItems() text->setNeedMouseFocus(false); text->setTextShadow(true); text->setTextShadowColour(MyGUI::Colour(0,0,0)); + text->setCaption(getCountString(displayCount)); y += 42; if (y > maxHeight) @@ -522,7 +529,6 @@ void ContainerBase::drawItems() y = 0; } - text->setCaption(getCountString(displayCount)); } } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 66cac82ce..26e78149a 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -55,7 +55,9 @@ namespace MWGui Filter_Weapon = 0x02, Filter_Apparel = 0x03, Filter_Magic = 0x04, - Filter_Misc = 0x05 + Filter_Misc = 0x05, + + Filter_Ingredients = 0x06 }; enum ItemState @@ -116,6 +118,8 @@ namespace MWGui virtual bool isTrading() { return false; } + virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; } + virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } }; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 59be6a495..04a30b69b 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -97,7 +97,7 @@ namespace MWGui openContainer(player); } - void InventoryWindow::openInventory() + void InventoryWindow::open() { updateEncumbranceBar(); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index fdb443829..86f7ee3c7 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -11,7 +11,7 @@ namespace MWGui public: InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); - void openInventory(); + virtual void open(); /// start trading, disables item drag&drop void startTrade(); diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp index 1eb126a74..45206214b 100644 --- a/apps/openmw/mwgui/window_base.cpp +++ b/apps/openmw/mwgui/window_base.cpp @@ -13,6 +13,15 @@ void WindowBase::open() { } +void WindowBase::setVisible(bool visible) +{ + bool wasVisible = mMainWidget->getVisible(); + mMainWidget->setVisible(visible); + + if (!wasVisible && visible) + open(); +} + void WindowBase::center() { // Centre dialog diff --git a/apps/openmw/mwgui/window_base.hpp b/apps/openmw/mwgui/window_base.hpp index 99ddbe918..9cfdbe261 100644 --- a/apps/openmw/mwgui/window_base.hpp +++ b/apps/openmw/mwgui/window_base.hpp @@ -16,6 +16,7 @@ namespace MWGui typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; virtual void open(); + virtual void setVisible(bool visible); // calls open() if visible is true and was false before void center(); /** Event : Dialog finished, OK button clicked.\n diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a29dd96a6..96469d105 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -269,20 +269,17 @@ void WindowManager::updateVisible() map -> setVisible( (eff & GW_Map) != 0 ); mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); break; } case GM_Container: mContainerWindow->setVisible(true); mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); break; case GM_Dialogue: mDialogueWindow->setVisible(true); break; case GM_Barter: mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); mTradeWindow->setVisible(true); break; case GM_InterMessageBox: