From b309d245c5db4fa12832292572033fc092d98b1c Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 15 Apr 2012 17:52:39 +0200 Subject: [PATCH 001/289] cleaning up hircine work --- apps/openmw/CMakeLists.txt | 4 +- apps/openmw/mwclass/apparatus.cpp | 10 + apps/openmw/mwclass/apparatus.hpp | 3 + apps/openmw/mwclass/armor.cpp | 8 + apps/openmw/mwclass/armor.hpp | 3 + apps/openmw/mwclass/book.cpp | 8 + apps/openmw/mwclass/book.hpp | 3 + apps/openmw/mwclass/clothing.cpp | 8 + apps/openmw/mwclass/clothing.hpp | 3 + apps/openmw/mwclass/container.cpp | 7 +- apps/openmw/mwclass/ingredient.cpp | 8 + apps/openmw/mwclass/ingredient.hpp | 3 + apps/openmw/mwclass/light.cpp | 8 + apps/openmw/mwclass/light.hpp | 3 + apps/openmw/mwclass/lockpick.cpp | 8 + apps/openmw/mwclass/lockpick.hpp | 3 + apps/openmw/mwclass/misc.cpp | 8 + apps/openmw/mwclass/misc.hpp | 3 + apps/openmw/mwclass/potion.cpp | 9 + apps/openmw/mwclass/potion.hpp | 3 + apps/openmw/mwclass/probe.cpp | 8 + apps/openmw/mwclass/probe.hpp | 3 + apps/openmw/mwclass/repair.cpp | 8 + apps/openmw/mwclass/repair.hpp | 3 + apps/openmw/mwclass/weapon.cpp | 9 + apps/openmw/mwclass/weapon.hpp | 5 + apps/openmw/mwgui/container.cpp | 191 ++++++++++++++++++ apps/openmw/mwgui/container.hpp | 62 ++++++ apps/openmw/mwgui/window_manager.cpp | 4 +- apps/openmw/mwgui/window_manager.hpp | 6 +- apps/openmw/mwworld/actionopen.cpp | 21 ++ apps/openmw/mwworld/actionopen.hpp | 22 ++ apps/openmw/mwworld/containerstore.cpp | 30 +++ apps/openmw/mwworld/containerstore.hpp | 2 + files/mygui/CMakeLists.txt | 1 + .../mygui/openmw_container_window_layout.xml | 24 +++ 36 files changed, 506 insertions(+), 6 deletions(-) create mode 100644 apps/openmw/mwgui/container.cpp create mode 100644 apps/openmw/mwgui/container.hpp create mode 100644 apps/openmw/mwworld/actionopen.cpp create mode 100644 apps/openmw/mwworld/actionopen.hpp create mode 100644 files/mygui/openmw_container_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 2630098f5..6fb8a24c3 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -24,7 +24,7 @@ add_openmw_dir (mwinput add_openmw_dir (mwgui layouts text_input widgets race class birth review window_manager console dialogue - dialogue_history window_base stats_window messagebox journalwindow charactercreation + dialogue_history window_base stats_window messagebox journalwindow charactercreation container ) add_openmw_dir (mwdialogue @@ -45,7 +45,7 @@ add_openmw_dir (mwsound add_openmw_dir (mwworld refdata world physicssystem scene environment globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors - cells localscripts customdata weather inventorystore ptr + cells localscripts customdata weather inventorystore ptr actionopen ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index e95fb572f..8ac589db6 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -86,4 +86,14 @@ namespace MWClass { return std::string("Item Apparatus Down"); } + + + std::string Apparatus::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } + } diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index c0849e1fe..2d1175951 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index e1c2734f0..597094a45 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -188,4 +188,12 @@ namespace MWClass else return std::string("Item Armor Heavy Down"); } + + std::string Armor::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 2b66ff828..aada97eec 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -47,6 +47,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 0a81ebafb..f22191f26 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -88,4 +88,12 @@ namespace MWClass { return std::string("Item Book Down"); } + std::string Book::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } + } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index ccbbfb4b2..2d37bffea 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 4fe19ada4..176ab26dc 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -153,4 +153,12 @@ namespace MWClass } return std::string("Item Clothes Down"); } + + std::string Clothing::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 171b06246..b7084a4d5 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -41,6 +41,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index c58a25c03..dd5f3add3 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -12,6 +12,7 @@ #include "../mwworld/environment.hpp" #include "../mwrender/objects.hpp" +#include "../mwworld/actionopen.hpp" #include "../mwsound/soundmanager.hpp" @@ -81,6 +82,7 @@ namespace MWClass const std::string lockedSound = "LockedChest"; const std::string trapActivationSound = "Disarm Trap Fail"; + if (ptr.getCellRef().lockLevel>0) { // TODO check for key @@ -94,7 +96,8 @@ namespace MWClass if(ptr.getCellRef().trap.empty()) { // Not trapped, Inventory GUI goes here - return boost::shared_ptr (new MWWorld::NullAction); + //return boost::shared_ptr (new MWWorld::NullAction); + return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); } else { @@ -137,4 +140,6 @@ namespace MWClass registerClass (typeid (ESM::Container).name(), instance); } + + } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 1a7edf632..7b96817e9 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -84,4 +84,12 @@ namespace MWClass { return std::string("Item Ingredient Down"); } + + std::string Ingredient::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 9463dcf8d..f79534868 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index e2e63a89b..50fc39023 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -126,4 +126,12 @@ namespace MWClass { return std::string("Item Misc Down"); } + + std::string Light::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 46a4d60ba..bd04401ce 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -41,6 +41,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 3dda2f4af..49300eb09 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -97,4 +97,12 @@ namespace MWClass { return std::string("Item Lockpick Down"); } + + std::string Lockpick::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 0c9189c54..4d5938a69 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -36,6 +36,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 864fc1e38..cd06d1073 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -100,4 +100,12 @@ namespace MWClass } return std::string("Item Misc Down"); } + + std::string Miscellaneous::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index b07964f99..39d771dc9 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 4ab374590..a50d19736 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -86,4 +86,13 @@ namespace MWClass { return std::string("Item Potion Down"); } + + + std::string Potion::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index be9e713fb..5eb9a3e46 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 4b4d79a73..3f8dc2a44 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -96,4 +96,12 @@ namespace MWClass { return std::string("Item Probe Down"); } + + std::string Probe::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 1507d65aa..1d9ce7d86 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -36,6 +36,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 758bf4079..bafb84bca 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -86,4 +86,12 @@ namespace MWClass { return std::string("Item Repair Down"); } + + std::string Repair::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 17b606f4c..3b8260f9d 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -32,6 +32,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 20db0cf38..9d3d40646 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -237,4 +237,13 @@ namespace MWClass return std::string("Item Misc Down"); } + + + std::string Weapon::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->icon; + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index f863c0bfe..31fee9b4b 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -47,6 +47,11 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the put down sound Id + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. + + }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp new file mode 100644 index 000000000..c09a1bf58 --- /dev/null +++ b/apps/openmw/mwgui/container.cpp @@ -0,0 +1,191 @@ +#include "container.hpp" + +#include +#include +#include "window_manager.hpp" +#include "widgets.hpp" + +#include "../mwworld/environment.hpp" +#include "../mwworld/manualref.hpp" +#include +#include +#include + +#include +#include +#include "../mwclass/container.hpp" +#include "../mwworld/containerstore.hpp" +#include + + +using namespace MWGui; +using namespace Widgets; + + +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment) + : WindowBase("openmw_container_window_layout.xml", parWindowManager), + mEnvironment(environment) +{ + setText("_Main", "Name of Container"); + setVisible(false); + + getWidget(containerWidget, "Items"); + getWidget(takeButton, "TakeButton"); + getWidget(closeButton, "CloseButton"); + + setText("CloseButton","Close"); + setText("TakeButton","Take All"); + + //ctor +} + +ContainerWindow::~ContainerWindow() +{ + //dtor + + + + +} + +void ContainerWindow::setName(std::string contName) +{ + setText("_Main", contName); +} + + + +void ContainerWindow::open(MWWorld::Ptr& container) +{ + setName(MWWorld::Class::get(container).getName(container)); + //MWWorld::ContainerStore* containerStore = container.getContainerStore(); + + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(container).getContainerStore(container); + + + MWWorld::ManualRef furRef (mWindowManager.getStore(), "fur_cuirass"); + furRef.getPtr().getRefData().setCount (5); + MWWorld::ManualRef bukkitRef (mWindowManager.getStore(), "misc_com_bucket_01"); + MWWorld::ManualRef broomRef (mWindowManager.getStore(), "misc_com_broom_01"); + MWWorld::ManualRef goldRef (mWindowManager.getStore(), "gold_100"); + + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(goldRef.getPtr()); + + + + // ESMS::LiveCellRef *ref = iter->get(); + + + int x = 4; + int y = 4; + int count = 0; + + for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) + { + std::string path = std::string("icons\\"); + + + path += iter.getInventoryIcon(); +// switch (iter.getType()) +// { +// +// case MWWorld::ContainerStore::Type_Potion: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Apparatus: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Armor: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Book: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Clothing: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Ingredient: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Light: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Lockpick: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Miscellaneous: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Probe: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Repair: +// path += iter->get()->base->icon; +// break; +// case MWWorld::ContainerStore::Type_Weapon: +// path += iter->get()->base->icon; +// break; +// +// +// } + count++; + + if(count % 8 == 0) + { + y += 36; + x = 4; + count = 0; + } + x += 36; + + + MyGUI::ImageBox* image = containerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); + MyGUI::TextBox* text = containerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + + if(iter->getRefData().getCount() > 1) + text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + + + containerWidgets.push_back(image); + + + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + + //std::cout << path << std::endl; + image->setImageTexture(path); + } + + + setVisible(true); +} + +void Update() +{ + +} + diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp new file mode 100644 index 000000000..e027f48fe --- /dev/null +++ b/apps/openmw/mwgui/container.hpp @@ -0,0 +1,62 @@ +#ifndef MGUI_CONTAINER_H +#define MGUI_CONTAINER_H + +#include +#include "../mwclass/container.hpp" +#include +#include +#include +#include +#include "window_base.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/containerstore.hpp" + +namespace MWWorld +{ + class Environment; +} + +namespace MyGUI +{ + class Gui; + class Widget; +} + +namespace MWGui +{ + class WindowManager; +} + + +namespace MWGui +{ + + + class ContainerWindow : public WindowBase + { + public: + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + + + void open(MWWorld::Ptr& container); + void setName(std::string contName); + void Update(); + + virtual ~ContainerWindow(); + protected: + private: + MWWorld::Environment& mEnvironment; + std::vector containerWidgets; + MyGUI::WidgetPtr containerWidget; + + MyGUI::ButtonPtr takeButton; + MyGUI::ButtonPtr closeButton; + + + + + + //MWWorld::Ptr& mContainer; + }; +} +#endif // CONTAINER_H diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index fa6dedc77..741066896 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -6,6 +6,7 @@ #include "dialogue_history.hpp" #include "stats_window.hpp" #include "messagebox.hpp" +#include "container.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -52,6 +53,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); dialogueWindow = new DialogueWindow(*this,environment); + containerWindow = new ContainerWindow(*this,environment); // The HUD is always on hud->setVisible(true); @@ -90,7 +92,7 @@ WindowManager::~WindowManager() delete stats; delete mJournal; delete dialogueWindow; - + delete containerWindow; delete mCharGen; cleanupGarbage(); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 582f438e8..cbe0edad9 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -62,7 +62,7 @@ namespace MWGui class Console; class JournalWindow; class CharacterCreation; - + class ContainerWindow; class TextInputDialog; class InfoBoxDialog; class DialogueWindow; @@ -127,6 +127,8 @@ namespace MWGui MWGui::DialogueWindow* getDialogueWindow() {return dialogueWindow;} + MWGui::ContainerWindow* getContainerWindow() {return containerWindow;} + MyGUI::Gui* getGui() const { return gui; } void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount) @@ -191,7 +193,7 @@ namespace MWGui Console *console; JournalWindow* mJournal; DialogueWindow *dialogueWindow; - + ContainerWindow *containerWindow; CharacterCreation* mCharGen; // Various stats about player as needed by window manager diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp new file mode 100644 index 000000000..c7b066d8e --- /dev/null +++ b/apps/openmw/mwworld/actionopen.cpp @@ -0,0 +1,21 @@ +#include "actionopen.hpp" + +#include "environment.hpp" +#include "class.hpp" +#include "world.hpp" +#include "containerstore.hpp" +#include "../mwclass/container.hpp" +#include "../mwgui/window_manager.hpp" +#include "../mwgui/container.hpp" + +namespace MWWorld +{ + ActionOpen::ActionOpen (const MWWorld::Ptr& container) : mContainer (container) { + mContainer = container; + } + + void ActionOpen::execute (Environment& environment) + { + environment.mWindowManager->getContainerWindow()->open(mContainer); + } +} diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp new file mode 100644 index 000000000..7c660e4c9 --- /dev/null +++ b/apps/openmw/mwworld/actionopen.hpp @@ -0,0 +1,22 @@ + +#ifndef GAME_MWWORLD_ACTIONOPEN_H +#define GAME_MWWORLD_ACTIONOPEN_H + +#include "action.hpp" +#include "ptr.hpp" + + +namespace MWWorld +{ + class ActionOpen : public Action + { + Ptr mContainer; + + public: + ActionOpen (const Ptr& container); + ///< \param The Container the Player has activated. + virtual void execute (Environment& environment); + }; +} + +#endif // ACTIONOPEN_H diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 2800b6f3c..16de93332 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -457,3 +457,33 @@ bool MWWorld::operator!= (const ContainerStoreIterator& left, const ContainerSto { return !(left==right); } + + +std::string MWWorld::ContainerStoreIterator::getInventoryIcon() +{ + Ptr ptr; + + switch (mType) + { + case ContainerStore::Type_Potion: ptr = MWWorld::Ptr (&*mPotion, 0); break; + case ContainerStore::Type_Apparatus: ptr = MWWorld::Ptr (&*mApparatus, 0); break; + case ContainerStore::Type_Armor: ptr = MWWorld::Ptr (&*mArmor, 0); break; + case ContainerStore::Type_Book: ptr = MWWorld::Ptr (&*mBook, 0); break; + case ContainerStore::Type_Clothing: ptr = MWWorld::Ptr (&*mClothing, 0); break; + case ContainerStore::Type_Ingredient: ptr = MWWorld::Ptr (&*mIngredient, 0); break; + case ContainerStore::Type_Light: ptr = MWWorld::Ptr (&*mLight, 0); break; + case ContainerStore::Type_Lockpick: ptr = MWWorld::Ptr (&*mLockpick, 0); break; + case ContainerStore::Type_Miscellaneous: ptr = MWWorld::Ptr (&*mMiscellaneous, 0); break; + case ContainerStore::Type_Probe: ptr = MWWorld::Ptr (&*mProbe, 0); break; + case ContainerStore::Type_Repair: ptr = MWWorld::Ptr (&*mRepair, 0); break; + case ContainerStore::Type_Weapon: ptr = MWWorld::Ptr (&*mWeapon, 0); break; + } + + if (ptr.isEmpty()) + throw std::runtime_error ("invalid iterator"); + + + std::string s = ptr.getInventoryIcon(); + + return s; +} diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index da5424fe0..fc6283442 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -161,6 +161,8 @@ namespace MWWorld const ContainerStore *getContainerStore() const; + std::string getInventoryIcon(); + friend class ContainerStore; }; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 9a6cde7ba..c24bd59f4 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -38,6 +38,7 @@ configure_file("${SDIR}/openmw_chargen_review_layout.xml" "${DDIR}/openmw_charge configure_file("${SDIR}/openmw_dialogue_window_layout.xml" "${DDIR}/openmw_dialogue_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_dialogue_window_skin.xml" "${DDIR}/openmw_dialogue_window_skin.xml" COPYONLY) configure_file("${SDIR}/openmw_inventory_window_layout.xml" "${DDIR}/openmw_inventory_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_container_window_layout.xml" "${DDIR}/openmw_container_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY) configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_mainmenu_skin.xml" "${DDIR}/openmw_mainmenu_skin.xml" COPYONLY) diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml new file mode 100644 index 000000000..a9de14880 --- /dev/null +++ b/files/mygui/openmw_container_window_layout.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + From 78c8a22cd16bef3ca0efc1479b8ceb777aac77af Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 15 Apr 2012 19:32:41 +0200 Subject: [PATCH 002/289] more clean up. The container GUI shows up now --- apps/openmw/mwgui/container.cpp | 95 ++++++++++++-------------- apps/openmw/mwgui/mode.hpp | 1 + apps/openmw/mwgui/window_manager.cpp | 5 ++ apps/openmw/mwworld/actionopen.cpp | 1 + apps/openmw/mwworld/containerstore.cpp | 2 +- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index c09a1bf58..7a3d5b240 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -27,7 +27,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro mEnvironment(environment) { setText("_Main", "Name of Container"); - setVisible(false); + center(); getWidget(containerWidget, "Items"); getWidget(takeButton, "TakeButton"); @@ -35,17 +35,10 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("CloseButton","Close"); setText("TakeButton","Take All"); - - //ctor } ContainerWindow::~ContainerWindow() { - //dtor - - - - } void ContainerWindow::setName(std::string contName) @@ -108,49 +101,49 @@ void ContainerWindow::open(MWWorld::Ptr& container) std::string path = std::string("icons\\"); - path += iter.getInventoryIcon(); -// switch (iter.getType()) -// { -// -// case MWWorld::ContainerStore::Type_Potion: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Apparatus: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Armor: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Book: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Clothing: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Ingredient: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Light: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Lockpick: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Miscellaneous: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Probe: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Repair: -// path += iter->get()->base->icon; -// break; -// case MWWorld::ContainerStore::Type_Weapon: -// path += iter->get()->base->icon; -// break; -// -// -// } + //path += iter.getInventoryIcon(); + switch (iter.getType()) + { + + case MWWorld::ContainerStore::Type_Potion: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Apparatus: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Armor: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Book: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Clothing: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Ingredient: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Light: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Lockpick: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Miscellaneous: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Probe: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Repair: + path += iter->get()->base->icon; + break; + case MWWorld::ContainerStore::Type_Weapon: + path += iter->get()->base->icon; + break; + + + } count++; if(count % 8 == 0) diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 55f0952ce..48670e9a5 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -7,6 +7,7 @@ namespace MWGui { GM_Game, // Game mode, only HUD GM_Inventory, // Inventory mode + GM_Container, GM_MainMenu, // Main menu mode GM_Console, // Console mode diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 06bbb3a30..34048c935 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -181,6 +181,7 @@ void WindowManager::updateVisible() console->disable(); mJournal->setVisible(false); dialogueWindow->setVisible(false); + containerWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -216,8 +217,12 @@ void WindowManager::updateVisible() // Show the windows we want map -> setVisible( (eff & GW_Map) != 0 ); stats -> setVisible( (eff & GW_Stats) != 0 ); + break; } + case GM_Container: + containerWindow->setVisible(true); + break; case GM_Dialogue: dialogueWindow->open(); break; diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index c7b066d8e..aa4a67b2b 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,6 +16,7 @@ namespace MWWorld void ActionOpen::execute (Environment& environment) { + environment.mWindowManager->setGuiMode(MWGui::GuiMode::GM_Container); environment.mWindowManager->getContainerWindow()->open(mContainer); } } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 16de93332..3f1b7ea2c 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -483,7 +483,7 @@ std::string MWWorld::ContainerStoreIterator::getInventoryIcon() throw std::runtime_error ("invalid iterator"); - std::string s = ptr.getInventoryIcon(); + std::string s = "";//ptr.getInventoryIcon(); return s; } From 58d05fa503f9117ae7ddc6288cbeb421c73b83cc Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 15 Apr 2012 20:56:45 +0200 Subject: [PATCH 003/289] more clean-up. Container window shows up! But there is no working close button. --- apps/openmw/mwgui/container.cpp | 45 ++------------------------ apps/openmw/mwworld/class.cpp | 5 +++ apps/openmw/mwworld/class.hpp | 3 ++ apps/openmw/mwworld/containerstore.cpp | 32 +----------------- apps/openmw/mwworld/containerstore.hpp | 2 -- files/mygui/core.xml | 1 + 6 files changed, 12 insertions(+), 76 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 7a3d5b240..2defad207 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -16,6 +16,7 @@ #include "../mwclass/container.hpp" #include "../mwworld/containerstore.hpp" #include +#include "../mwworld/class.hpp" using namespace MWGui; @@ -101,49 +102,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) std::string path = std::string("icons\\"); - //path += iter.getInventoryIcon(); - switch (iter.getType()) - { - - case MWWorld::ContainerStore::Type_Potion: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Apparatus: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Armor: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Book: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Clothing: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Ingredient: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Light: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Lockpick: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Miscellaneous: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Probe: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Repair: - path += iter->get()->base->icon; - break; - case MWWorld::ContainerStore::Type_Weapon: - path += iter->get()->base->icon; - break; - - - } + path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); count++; if(count % 8 == 0) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index d49b98d0f..2dd8aee1e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -173,4 +173,9 @@ namespace MWWorld { throw std::runtime_error ("class does not have an down sound"); } + + std::string Class::getInventoryIcon (const MWWorld::Ptr& ptr) const + { + throw std::runtime_error ("class does not have any inventory icon"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index e474e9b92..eaa0d5f6f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -174,6 +174,9 @@ namespace MWWorld virtual std::string getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const; ///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) + + virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; + ///< Return name of inventory icon. }; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 3f1b7ea2c..86ee15e58 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -456,34 +456,4 @@ bool MWWorld::operator== (const ContainerStoreIterator& left, const ContainerSto bool MWWorld::operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right) { return !(left==right); -} - - -std::string MWWorld::ContainerStoreIterator::getInventoryIcon() -{ - Ptr ptr; - - switch (mType) - { - case ContainerStore::Type_Potion: ptr = MWWorld::Ptr (&*mPotion, 0); break; - case ContainerStore::Type_Apparatus: ptr = MWWorld::Ptr (&*mApparatus, 0); break; - case ContainerStore::Type_Armor: ptr = MWWorld::Ptr (&*mArmor, 0); break; - case ContainerStore::Type_Book: ptr = MWWorld::Ptr (&*mBook, 0); break; - case ContainerStore::Type_Clothing: ptr = MWWorld::Ptr (&*mClothing, 0); break; - case ContainerStore::Type_Ingredient: ptr = MWWorld::Ptr (&*mIngredient, 0); break; - case ContainerStore::Type_Light: ptr = MWWorld::Ptr (&*mLight, 0); break; - case ContainerStore::Type_Lockpick: ptr = MWWorld::Ptr (&*mLockpick, 0); break; - case ContainerStore::Type_Miscellaneous: ptr = MWWorld::Ptr (&*mMiscellaneous, 0); break; - case ContainerStore::Type_Probe: ptr = MWWorld::Ptr (&*mProbe, 0); break; - case ContainerStore::Type_Repair: ptr = MWWorld::Ptr (&*mRepair, 0); break; - case ContainerStore::Type_Weapon: ptr = MWWorld::Ptr (&*mWeapon, 0); break; - } - - if (ptr.isEmpty()) - throw std::runtime_error ("invalid iterator"); - - - std::string s = "";//ptr.getInventoryIcon(); - - return s; -} +} \ No newline at end of file diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index fc6283442..da5424fe0 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -161,8 +161,6 @@ namespace MWWorld const ContainerStore *getContainerStore() const; - std::string getInventoryIcon(); - friend class ContainerStore; }; diff --git a/files/mygui/core.xml b/files/mygui/core.xml index 7417328cf..8e256ca9c 100644 --- a/files/mygui/core.xml +++ b/files/mygui/core.xml @@ -20,6 +20,7 @@ + From 489261a6ae514dafe2aea679bbca17c1c52cf46b Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 15 Apr 2012 21:02:54 +0200 Subject: [PATCH 004/289] Close button works. --- apps/openmw/mwgui/container.cpp | 10 +++++++++- apps/openmw/mwgui/container.hpp | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 2defad207..3f27351a9 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -29,11 +29,14 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro { setText("_Main", "Name of Container"); center(); + adjustWindowCaption(); getWidget(containerWidget, "Items"); getWidget(takeButton, "TakeButton"); getWidget(closeButton, "CloseButton"); + closeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onByeClicked); + setText("CloseButton","Close"); setText("TakeButton","Take All"); } @@ -136,8 +139,13 @@ void ContainerWindow::open(MWWorld::Ptr& container) setVisible(true); } -void Update() +void ContainerWindow::Update() { } +void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) +{ + mEnvironment.mWindowManager->setGuiMode(MWGui::GuiMode::GM_Game); +} + diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index e027f48fe..76905a681 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -53,7 +53,7 @@ namespace MWGui MyGUI::ButtonPtr closeButton; - + void onByeClicked(MyGUI::Widget* _sender); //MWWorld::Ptr& mContainer; From f902c8fa6f154db5dd5383878781cc817c2dd01f Mon Sep 17 00:00:00 2001 From: pchan3 Date: Wed, 18 Apr 2012 22:35:35 +1000 Subject: [PATCH 005/289] Fixes on Namespace issue & more. --- apps/openmw/mwgui/container.cpp | 73 ++++++++++++++++++++++++------ apps/openmw/mwworld/actionopen.cpp | 2 +- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 3f27351a9..094b958db 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -28,7 +28,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro mEnvironment(environment) { setText("_Main", "Name of Container"); - center(); + //center(); adjustWindowCaption(); getWidget(containerWidget, "Items"); @@ -90,7 +90,54 @@ void ContainerWindow::open(MWWorld::Ptr& container) containerStore.add(bukkitRef.getPtr()); containerStore.add(bukkitRef.getPtr()); containerStore.add(goldRef.getPtr()); - + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(goldRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(furRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(broomRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(bukkitRef.getPtr()); + containerStore.add(goldRef.getPtr()); // ESMS::LiveCellRef *ref = iter->get(); @@ -103,39 +150,35 @@ void ContainerWindow::open(MWWorld::Ptr& container) for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) { std::string path = std::string("icons\\"); - - path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); count++; - if(count % 8 == 0) + MyGUI::ImageBox* image = containerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); + MyGUI::TextBox* text = containerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + + x += 36; + if(count % 20 == 0) { y += 36; x = 4; count = 0; } - x += 36; - - - MyGUI::ImageBox* image = containerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = containerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); if(iter->getRefData().getCount() > 1) text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - containerWidgets.push_back(image); - int pos = path.rfind("."); path.erase(pos); path.append(".dds"); - //std::cout << path << std::endl; image->setImageTexture(path); } + + setVisible(true); } @@ -146,6 +189,8 @@ void ContainerWindow::Update() void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) { - mEnvironment.mWindowManager->setGuiMode(MWGui::GuiMode::GM_Game); + mEnvironment.mWindowManager->setGuiMode(GM_Game); + + setVisible(false); } diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index aa4a67b2b..e245989d7 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,7 +16,7 @@ namespace MWWorld void ActionOpen::execute (Environment& environment) { - environment.mWindowManager->setGuiMode(MWGui::GuiMode::GM_Container); + environment.mWindowManager->setGuiMode(MWGui::GM_Container); environment.mWindowManager->getContainerWindow()->open(mContainer); } } From 215d4e1739a016b094e6ccb5dda3e06e175df4ae Mon Sep 17 00:00:00 2001 From: pchan3 Date: Wed, 18 Apr 2012 23:09:13 +1000 Subject: [PATCH 006/289] Made adjustments to keep container window within the viewscreen. --- apps/openmw/mwgui/container.cpp | 4 ++++ files/mygui/openmw_container_window_layout.xml | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 094b958db..7c63f95d0 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -28,6 +28,10 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro mEnvironment(environment) { setText("_Main", "Name of Container"); + + int w = MyGUI::RenderManager::getInstance().getViewSize().width; + int h = MyGUI::RenderManager::getInstance().getViewSize().height; + setCoord(w-600,h-300,600,300); //center(); adjustWindowCaption(); diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index a9de14880..7fce9e187 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -1,13 +1,13 @@ - + - - + - --> + From 1e8d894e1c9562010847fe4a5632055bab1093b3 Mon Sep 17 00:00:00 2001 From: gugus Date: Sat, 21 Apr 2012 10:51:01 +0200 Subject: [PATCH 007/289] Starting inventory window --- apps/openmw/mwgui/container.cpp | 21 +++++++++++++++++-- apps/openmw/mwgui/container.hpp | 1 + apps/openmw/mwgui/inventorywindow.cpp | 11 ++++++++++ apps/openmw/mwgui/inventorywindow.hpp | 30 +++++++++++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 7 ++++++- apps/openmw/mwgui/window_manager.hpp | 2 ++ 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 apps/openmw/mwgui/inventorywindow.cpp create mode 100644 apps/openmw/mwgui/inventorywindow.hpp diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 3f27351a9..bc3bcf475 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -41,6 +41,23 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("TakeButton","Take All"); } +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile) + : WindowBase(guiFile, parWindowManager), + mEnvironment(environment) +{ + setText("_Main", "Name of Container"); + //center(); + adjustWindowCaption(); + + getWidget(containerWidget, "Items"); + //getWidget(takeButton, "TakeButton"); + //getWidget(closeButton, "CloseButton"); + + //closeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onByeClicked); + + //setText("CloseButton","Close"); + //setText("TakeButton","Take All"); +} ContainerWindow::~ContainerWindow() { } @@ -60,7 +77,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) MWWorld::ContainerStore& containerStore = MWWorld::Class::get(container).getContainerStore(container); - MWWorld::ManualRef furRef (mWindowManager.getStore(), "fur_cuirass"); + /*MWWorld::ManualRef furRef (mWindowManager.getStore(), "fur_cuirass"); furRef.getPtr().getRefData().setCount (5); MWWorld::ManualRef bukkitRef (mWindowManager.getStore(), "misc_com_bucket_01"); MWWorld::ManualRef broomRef (mWindowManager.getStore(), "misc_com_broom_01"); @@ -89,7 +106,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) containerStore.add(bukkitRef.getPtr()); containerStore.add(bukkitRef.getPtr()); containerStore.add(bukkitRef.getPtr()); - containerStore.add(goldRef.getPtr()); + containerStore.add(goldRef.getPtr());*/ diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 76905a681..3802d21af 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -36,6 +36,7 @@ namespace MWGui { public: ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile); void open(MWWorld::Ptr& container); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp new file mode 100644 index 000000000..7f3884bc1 --- /dev/null +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -0,0 +1,11 @@ +#include "inventorywindow.hpp" + +namespace MWGui +{ + + InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment) + :ContainerWindow(parWindowManager,environment,"openmw_inventory_window_layout.xml") + { + } + +} \ No newline at end of file diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp new file mode 100644 index 000000000..ce177014a --- /dev/null +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -0,0 +1,30 @@ +#ifndef MGUI_Inventory_H +#define MGUI_Inventory_H + +#include "container.hpp" +namespace MWWorld +{ + class Environment; +} + +namespace MyGUI +{ + class Gui; + class Widget; +} + +namespace MWGui +{ + class WindowManager; +} + + +namespace MWGui +{ + class InventoryWindow : public MWGui::ContainerWindow + { + public: + InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + }; +} +#endif // Inventory_H diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 34048c935..065141963 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -8,6 +8,7 @@ #include "stats_window.hpp" #include "messagebox.hpp" #include "container.hpp" +#include "inventorywindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -82,6 +83,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, mMessageBoxManager = new MessageBoxManager(this); dialogueWindow = new DialogueWindow(*this,environment); containerWindow = new ContainerWindow(*this,environment); + mInventoryWindow = new InventoryWindow(*this,environment); // The HUD is always on hud->setVisible(true); @@ -121,6 +123,7 @@ WindowManager::~WindowManager() delete mJournal; delete dialogueWindow; delete containerWindow; + delete mInventoryWindow; delete mCharGen; cleanupGarbage(); @@ -182,6 +185,7 @@ void WindowManager::updateVisible() mJournal->setVisible(false); dialogueWindow->setVisible(false); containerWindow->setVisible(false); + mInventoryWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -217,11 +221,12 @@ void WindowManager::updateVisible() // Show the windows we want map -> setVisible( (eff & GW_Map) != 0 ); stats -> setVisible( (eff & GW_Stats) != 0 ); - + mInventoryWindow->setVisible(true); break; } case GM_Container: containerWindow->setVisible(true); + mInventoryWindow->setVisible(true); break; case GM_Dialogue: dialogueWindow->open(); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 4f54b41b8..438a99a0e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -63,6 +63,7 @@ namespace MWGui class JournalWindow; class CharacterCreation; class ContainerWindow; + class InventoryWindow; class TextInputDialog; class InfoBoxDialog; class DialogueWindow; @@ -204,6 +205,7 @@ namespace MWGui JournalWindow* mJournal; DialogueWindow *dialogueWindow; ContainerWindow *containerWindow; + InventoryWindow *mInventoryWindow; CharacterCreation* mCharGen; // Various stats about player as needed by window manager From 33654535c19b22f103bcf547dc337620d6ac5feb Mon Sep 17 00:00:00 2001 From: gugus Date: Sat, 21 Apr 2012 11:05:30 +0200 Subject: [PATCH 008/289] The inventory window now display the inventory of the player --- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 23 +++++++++++++++++++++++ apps/openmw/mwgui/inventorywindow.hpp | 2 ++ apps/openmw/mwgui/window_manager.cpp | 2 ++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 3802d21af..5bb019233 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -44,8 +44,8 @@ namespace MWGui void Update(); virtual ~ContainerWindow(); + protected: - private: MWWorld::Environment& mEnvironment; std::vector containerWidgets; MyGUI::WidgetPtr containerWidget; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7f3884bc1..188cc3796 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -1,5 +1,23 @@ #include "inventorywindow.hpp" +#include +#include +#include "window_manager.hpp" +#include "widgets.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/manualref.hpp" +#include +#include +#include + +#include +#include +#include "../mwclass/container.hpp" +#include "../mwworld/containerstore.hpp" +#include +#include "../mwworld/class.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" namespace MWGui { @@ -8,4 +26,9 @@ namespace MWGui { } + void InventoryWindow::openInventory() + { + open(mEnvironment.mWorld->getPlayer().getPlayer()); + } + } \ No newline at end of file diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index ce177014a..bf9be4375 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -25,6 +25,8 @@ namespace MWGui { public: InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + + void openInventory(); }; } #endif // Inventory_H diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 065141963..c15f7077d 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -222,11 +222,13 @@ void WindowManager::updateVisible() map -> setVisible( (eff & GW_Map) != 0 ); stats -> setVisible( (eff & GW_Stats) != 0 ); mInventoryWindow->setVisible(true); + mInventoryWindow->openInventory(); break; } case GM_Container: containerWindow->setVisible(true); mInventoryWindow->setVisible(true); + mInventoryWindow->openInventory(); break; case GM_Dialogue: dialogueWindow->open(); From d4e9b62436dd691380f1ba78fdc161843503a4c5 Mon Sep 17 00:00:00 2001 From: gugus Date: Sat, 21 Apr 2012 11:11:40 +0200 Subject: [PATCH 009/289] oups forgot to modify CMake --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 769bcc6c3..f37f8dae4 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -25,7 +25,7 @@ add_openmw_dir (mwinput add_openmw_dir (mwgui layouts text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation container - map_window window_pinnable_base cursorreplace + map_window window_pinnable_base cursorreplace inventorywindow ) add_openmw_dir (mwdialogue From 25432d97d2d325639fe280d8530e1933d1206cdd Mon Sep 17 00:00:00 2001 From: gugus Date: Sat, 21 Apr 2012 20:35:45 +0200 Subject: [PATCH 010/289] trying to get selected item. Doesn't work. --- apps/openmw/mwgui/container.cpp | 17 +++++++++++------ apps/openmw/mwgui/container.hpp | 6 +++--- files/mygui/openmw_container_window_layout.xml | 10 +++++----- files/mygui/openmw_inventory_window_layout.xml | 2 +- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 2c09d6b29..9071c9b35 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -35,7 +35,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro //center(); adjustWindowCaption(); - getWidget(containerWidget, "Items"); + getWidget(mContainerWidget, "Items"); getWidget(takeButton, "TakeButton"); getWidget(closeButton, "CloseButton"); @@ -43,6 +43,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("CloseButton","Close"); setText("TakeButton","Take All"); + mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile) @@ -52,8 +53,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("_Main", "Name of Container"); //center(); adjustWindowCaption(); - - getWidget(containerWidget, "Items"); + getWidget(mContainerWidget, "Items"); //getWidget(takeButton, "TakeButton"); //getWidget(closeButton, "CloseButton"); @@ -61,6 +61,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro //setText("CloseButton","Close"); //setText("TakeButton","Take All"); + mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } ContainerWindow::~ContainerWindow() { @@ -126,8 +127,8 @@ void ContainerWindow::open(MWWorld::Ptr& container) path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); count++; - MyGUI::ImageBox* image = containerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = containerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + MyGUI::ImageBox* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); + MyGUI::TextBox* text = mContainerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); x += 36; if(count % 20 == 0) @@ -140,7 +141,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) if(iter->getRefData().getCount() > 1) text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - containerWidgets.push_back(image); + mContainerWidgets.push_back(image); int pos = path.rfind("."); path.erase(pos); @@ -167,3 +168,7 @@ void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) setVisible(false); } +void ContainerWindow::onSelectedItem(MyGUI::ItemBox* _sender, size_t _index) +{ + std::cout << "selected!"; +} \ No newline at end of file diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 5bb019233..0e68baf02 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -47,15 +47,15 @@ namespace MWGui protected: MWWorld::Environment& mEnvironment; - std::vector containerWidgets; - MyGUI::WidgetPtr containerWidget; + std::vector mContainerWidgets; + MyGUI::ItemBoxPtr mContainerWidget; MyGUI::ButtonPtr takeButton; MyGUI::ButtonPtr closeButton; void onByeClicked(MyGUI::Widget* _sender); - + void onSelectedItem(MyGUI::ItemBox* _sender, size_t _index); //MWWorld::Ptr& mContainer; }; diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 7fce9e187..31b036468 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -1,19 +1,19 @@ - + - + - + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index c69b6d8fe..766cacdb1 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -14,7 +14,7 @@ - + From 1b02b503a231dde098c7318b466db583e1da106c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 22 Apr 2012 21:06:08 +0200 Subject: [PATCH 011/289] gcc compile fix --- apps/openmw/mwgui/container.cpp | 4 ++-- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 9071c9b35..ac9330fdc 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -74,7 +74,7 @@ void ContainerWindow::setName(std::string contName) -void ContainerWindow::open(MWWorld::Ptr& container) +void ContainerWindow::open(MWWorld::Ptr container) { setName(MWWorld::Class::get(container).getName(container)); //MWWorld::ContainerStore* containerStore = container.getContainerStore(); @@ -171,4 +171,4 @@ void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) void ContainerWindow::onSelectedItem(MyGUI::ItemBox* _sender, size_t _index) { std::cout << "selected!"; -} \ No newline at end of file +} diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 0e68baf02..a7787b373 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -39,7 +39,7 @@ namespace MWGui ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile); - void open(MWWorld::Ptr& container); + void open(MWWorld::Ptr container); void setName(std::string contName); void Update(); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 188cc3796..81a190290 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -31,4 +31,4 @@ namespace MWGui open(mEnvironment.mWorld->getPlayer().getPlayer()); } -} \ No newline at end of file +} From a6419c3596a123584df3ed8a25e4650a9a3e655b Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 26 Apr 2012 19:35:45 +0200 Subject: [PATCH 012/289] Clicking on an item is now detected. Trying to have items follow the mouse position, but it doesn't work yet. --- apps/openmw/mwgui/container.cpp | 25 +++++++++++++++++++------ apps/openmw/mwgui/container.hpp | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 9071c9b35..e3d7574f3 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -43,7 +43,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("CloseButton","Close"); setText("TakeButton","Take All"); - mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); + //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile) @@ -61,7 +61,7 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro //setText("CloseButton","Close"); //setText("TakeButton","Take All"); - mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); + //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } ContainerWindow::~ContainerWindow() { @@ -128,8 +128,9 @@ void ContainerWindow::open(MWWorld::Ptr& container) count++; MyGUI::ImageBox* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = mContainerWidget->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); - + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); + image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); x += 36; if(count % 20 == 0) { @@ -141,7 +142,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) if(iter->getRefData().getCount() > 1) text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - mContainerWidgets.push_back(image); + //mContainerWidgets.push_back(image); int pos = path.rfind("."); path.erase(pos); @@ -168,7 +169,19 @@ void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) setVisible(false); } -void ContainerWindow::onSelectedItem(MyGUI::ItemBox* _sender, size_t _index) +void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) { + _sender->detachFromWidget(); + _sender->attachToWidget(mContainerWidget->getParent()->getParent()); + std::cout << mContainerWidget->getParent()->getParent()->getName(); + _sender->setUserString("drag","on"); std::cout << "selected!"; +} + +void ContainerWindow::onMouseMove(MyGUI::Widget* _sender, int _left, int _top) +{ + if(_sender->getUserString("drag") == "on") + { + _sender->setPosition(_left,_top); + } } \ No newline at end of file diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 0e68baf02..6ac9a814f 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -55,7 +55,8 @@ namespace MWGui void onByeClicked(MyGUI::Widget* _sender); - void onSelectedItem(MyGUI::ItemBox* _sender, size_t _index); + void onSelectedItem(MyGUI::Widget* _sender); + void onMouseMove(MyGUI::Widget* _sender, int _left, int _top); //MWWorld::Ptr& mContainer; }; From 5603cb312cd6f00f06fe88597e5d2e202d53e292 Mon Sep 17 00:00:00 2001 From: gugus Date: Fri, 27 Apr 2012 20:54:39 +0200 Subject: [PATCH 013/289] Objects can now be selected and follow mouse movements. --- apps/openmw/mwgui/container.cpp | 37 +++++++++++++++++++-------- apps/openmw/mwgui/container.hpp | 9 ++++--- apps/openmw/mwgui/inventorywindow.cpp | 4 +-- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/window_manager.cpp | 11 +++++--- files/mygui/openmw_layers.xml | 1 + 6 files changed, 45 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index e3d7574f3..b3fe7adfb 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -17,15 +17,17 @@ #include "../mwworld/containerstore.hpp" #include #include "../mwworld/class.hpp" +#include "../mwinput/inputmanager.hpp" using namespace MWGui; using namespace Widgets; -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget) : WindowBase("openmw_container_window_layout.xml", parWindowManager), - mEnvironment(environment) + mEnvironment(environment), + mDragAndDropWidget(dragAndDropWidget) { setText("_Main", "Name of Container"); @@ -43,17 +45,24 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro setText("CloseButton","Close"); setText("TakeButton","Take All"); + + mIsOnDragAndDrop = false; + mDraggedWidget = 0; //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget,std::string guiFile) : WindowBase(guiFile, parWindowManager), - mEnvironment(environment) + mEnvironment(environment), + mDragAndDropWidget(dragAndDropWidget) { setText("_Main", "Name of Container"); //center(); adjustWindowCaption(); getWidget(mContainerWidget, "Items"); + + mIsOnDragAndDrop = false; + mDraggedWidget = 0; //getWidget(takeButton, "TakeButton"); //getWidget(closeButton, "CloseButton"); @@ -130,7 +139,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) MyGUI::ImageBox* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); - image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); + //image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); x += 36; if(count % 20 == 0) { @@ -159,7 +168,12 @@ void ContainerWindow::open(MWWorld::Ptr& container) void ContainerWindow::Update() { - + if(mIsOnDragAndDrop) + { + if(mDraggedWidget) + mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); + else mIsOnDragAndDrop = false; //If this happens, there is a bug. + } } void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) @@ -171,17 +185,20 @@ void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) { + mIsOnDragAndDrop = true; _sender->detachFromWidget(); - _sender->attachToWidget(mContainerWidget->getParent()->getParent()); - std::cout << mContainerWidget->getParent()->getParent()->getName(); + _sender->attachToWidget(mDragAndDropWidget); + //std::cout << mContainerWidget->getParent()->getParent()->getName(); _sender->setUserString("drag","on"); + mDraggedWidget = _sender; std::cout << "selected!"; } void ContainerWindow::onMouseMove(MyGUI::Widget* _sender, int _left, int _top) { - if(_sender->getUserString("drag") == "on") + /*if(_sender->getUserString("drag") == "on") { _sender->setPosition(_left,_top); - } + + }*/ } \ No newline at end of file diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 6ac9a814f..2d1aa3ac0 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -35,8 +35,9 @@ namespace MWGui class ContainerWindow : public WindowBase { public: - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,std::string guiFile); + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget); + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget, + std::string guiFile); void open(MWWorld::Ptr& container); @@ -52,7 +53,9 @@ namespace MWGui MyGUI::ButtonPtr takeButton; MyGUI::ButtonPtr closeButton; - + MyGUI::Widget* mDragAndDropWidget; + bool mIsOnDragAndDrop; + MyGUI::Widget* mDraggedWidget; void onByeClicked(MyGUI::Widget* _sender); void onSelectedItem(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 188cc3796..efc9106e9 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -21,8 +21,8 @@ namespace MWGui { - InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment) - :ContainerWindow(parWindowManager,environment,"openmw_inventory_window_layout.xml") + InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget) + :ContainerWindow(parWindowManager,environment,dragAndDropWidget,"openmw_inventory_window_layout.xml") { } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index bf9be4375..c60889d73 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -24,7 +24,7 @@ namespace MWGui class InventoryWindow : public MWGui::ContainerWindow { public: - InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment); + InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget); void openInventory(); }; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index c15f7077d..f2adfe1e1 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -65,7 +65,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath); gui = mGuiManager->getGui(); - + //Register own widgets with MyGUI MyGUI::FactoryManager::getInstance().registerFactory("Widget"); @@ -74,6 +74,9 @@ WindowManager::WindowManager(MWWorld::Environment& environment, int w = MyGUI::RenderManager::getInstance().getViewSize().width; int h = MyGUI::RenderManager::getInstance().getViewSize().height; + MyGUI::Widget* dragAndDropWidget = gui->createWidgetT("Widget","",0,0,w,h,MyGUI::Align::Default,"DragAndDrop","DragAndDropWidget"); + dragAndDropWidget->setVisible(false); + hud = new HUD(w,h, showFPSLevel); menu = new MainMenu(w,h); map = new MapWindow(*this); @@ -82,8 +85,8 @@ WindowManager::WindowManager(MWWorld::Environment& environment, mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); dialogueWindow = new DialogueWindow(*this,environment); - containerWindow = new ContainerWindow(*this,environment); - mInventoryWindow = new InventoryWindow(*this,environment); + containerWindow = new ContainerWindow(*this,environment,dragAndDropWidget); + mInventoryWindow = new InventoryWindow(*this,environment,dragAndDropWidget); // The HUD is always on hud->setVisible(true); @@ -422,6 +425,8 @@ void WindowManager::onDialogueWindowBye() void WindowManager::onFrame (float frameDuration) { mMessageBoxManager->onFrame(frameDuration); + mInventoryWindow->Update(); + containerWindow->Update(); } const ESMS::ESMStore& WindowManager::getStore() const diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index a83eb970a..81cd99fea 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -10,4 +10,5 @@ + From 11ebae3be2d3d5750d532e56af511b2717b7c377 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 29 Apr 2012 03:33:10 +0200 Subject: [PATCH 014/289] toggleCompositors command useful for debugging --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwrender/renderingmanager.cpp | 45 ++++++++++++----------- apps/openmw/mwrender/renderingmanager.hpp | 6 +++ apps/openmw/mwrender/water.cpp | 20 ++++------ apps/openmw/mwrender/water.hpp | 4 +- apps/openmw/mwscript/docs/vmformat.txt | 3 +- apps/openmw/mwscript/miscextensions.cpp | 19 ++++++++++ apps/openmw/mwworld/world.hpp | 3 +- 8 files changed, 64 insertions(+), 37 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fb0e1db69..deb57cfec 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,6 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper + compositors ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a95a179c6..11d3dca6d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -18,6 +18,7 @@ #include "shaderhelper.hpp" #include "localmap.hpp" #include "water.hpp" +#include "compositors.hpp" using namespace MWRender; using namespace Ogre; @@ -29,6 +30,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const { mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); + mCompositors = new Compositors(mRendering.getViewport()); + mWater = 0; //The fog type must be set before any terrain objects are created as if the @@ -67,15 +70,15 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // note that the order is important here if (useMRT()) { - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbuffer"); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "Underwater"); - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbufferFinalizer"); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); + mCompositors->addCompositor("gbuffer", 0); + mCompositors->setCompositorEnabled("gbuffer", true); + mCompositors->addCompositor("Underwater", 1); + mCompositors->addCompositor("gbufferFinalizer", 2); + mCompositors->setCompositorEnabled("gbufferFinalizer", true); } else { - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "UnderwaterNoMRT"); + mCompositors->addCompositor("UnderwaterNoMRT", 0); } // Turn the entire scene (represented by the 'root' node) -90 @@ -120,6 +123,7 @@ RenderingManager::~RenderingManager () delete mTerrainManager; delete mLocalMap; delete mOcclusionQuery; + delete mCompositors; } MWRender::SkyManager* RenderingManager::getSkyManager() @@ -231,7 +235,7 @@ void RenderingManager::update (float duration){ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ if(store->cell->data.flags & store->cell->HasWater){ if(mWater == 0) - mWater = new MWRender::Water(mRendering.getCamera(), mSkyManager, store->cell); + mWater = new MWRender::Water(mRendering.getCamera(), this, store->cell); else mWater->changeCell(store->cell); mWater->setActive(true); @@ -292,35 +296,29 @@ void RenderingManager::skySetMoonColour (bool red){ bool RenderingManager::toggleRenderMode(int mode) { - if (mode != MWWorld::World::Render_Wireframe) + if (mode == MWWorld::World::Render_CollisionDebug || mode == MWWorld::World::Render_Pathgrid) return mDebugging->toggleRenderMode(mode); - else // if (mode == MWWorld::World::Render_Wireframe) + else if (mode == MWWorld::World::Render_Wireframe) { if (mRendering.getCamera()->getPolygonMode() == PM_SOLID) { - // disable compositors - if (useMRT()) - { - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", false); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", false); - } + mCompositors->setEnabled(false); mRendering.getCamera()->setPolygonMode(PM_WIREFRAME); return true; } else { - // re-enable compositors - if (useMRT()) - { - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); - } + mCompositors->setEnabled(true); mRendering.getCamera()->setPolygonMode(PM_SOLID); return false; } } + else //if (mode == MWWorld::World::Render_Compositors) + { + return mCompositors->toggle(); + } } void RenderingManager::configureFog(ESMS::CellStore &mCell) @@ -518,4 +516,9 @@ void RenderingManager::switchToExterior() mRendering.getScene()->setCameraRelativeRendering(true); } +Compositors* RenderingManager::getCompositors() +{ + return mCompositors; +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 0d11b3d57..4e3296598 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -47,6 +47,7 @@ namespace MWRender class ShaderHelper; class LocalMap; class Water; + class Compositors; class RenderingManager: private RenderingInterface { @@ -67,6 +68,7 @@ class RenderingManager: private RenderingInterface { /// to internal details of the rendering system anymore SkyManager* getSkyManager(); + Compositors* getCompositors(); void toggleLight(); bool toggleRenderMode(int mode); @@ -157,6 +159,8 @@ class RenderingManager: private RenderingInterface { bool mSunEnabled; + bool mCompositorsEnabled; + SkyManager* mSkyManager; OcclusionQuery* mOcclusionQuery; @@ -192,6 +196,8 @@ class RenderingManager: private RenderingInterface { MWRender::Shadows* mShadows; MWRender::ShaderHelper* mShaderHelper; + + MWRender::Compositors* mCompositors; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index c81f23f54..19716f751 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -2,24 +2,20 @@ #include #include "sky.hpp" #include "renderingmanager.hpp" +#include "compositors.hpp" using namespace Ogre; namespace MWRender { -Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) : +Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), - mReflectionRenderActive(false) + mReflectionRenderActive(false), mRendering(rend) { - mSky = sky; - - try - { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); - } catch(...) {} + mSky = rend->getSkyManager(); mTop = cell->water; @@ -147,8 +143,6 @@ Water::~Water() mWaterNode->detachObject(mWater); mSceneManager->destroyEntity(mWater); mSceneManager->destroySceneNode(mWaterNode); - - CompositorManager::getSingleton().removeCompositorChain(mViewport); } void Water::changeCell(const ESM::Cell* cell) @@ -178,13 +172,13 @@ void Water::checkUnderwater(float y) { if (!mActive) { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); return; } if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); // tell the shader we are not underwater Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); @@ -199,7 +193,7 @@ void Water::checkUnderwater(float y) if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) { if (mUnderwaterEffect) - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, true); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, true); // tell the shader we are underwater Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index c8b8d311e..25631b4af 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -9,6 +9,7 @@ namespace MWRender { class SkyManager; + class RenderingManager; /// Water rendering class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener @@ -40,6 +41,7 @@ namespace MWRender { void updateVisible(); + RenderingManager* mRendering; SkyManager* mSky; std::string mCompositorName; @@ -55,7 +57,7 @@ namespace MWRender { int mVisibilityFlags; public: - Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell); + Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell); ~Water(); void setActive(bool active); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 58960aac4..11df70bbc 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -144,4 +144,5 @@ op 0x200014d: ModDisposition op 0x200014e: ModDisposition, explicit reference op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference -opcodes 0x2000151-0x3ffffff unused +op 0x2000152: ToggleCompositors +opcodes 0x2000153-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 4ba523937..95129bd76 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -194,6 +194,22 @@ namespace MWScript } }; + class OpToggleCompositors : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode(MWWorld::World::Render_Compositors); + + context.report (enabled ? + "Compositors -> On" : "Compositors -> Off"); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -208,6 +224,7 @@ namespace MWScript const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; + const int opcodeToggleCompositors = 0x2000152; void registerExtensions (Compiler::Extensions& extensions) { @@ -229,6 +246,7 @@ namespace MWScript extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); + extensions.registerInstruction ("togglecompositors", "", opcodeToggleCompositors); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -247,6 +265,7 @@ namespace MWScript interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); + interpreter.installSegment5 (opcodeToggleCompositors, new OpToggleCompositors); } } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 77e5bcef6..583448e12 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -63,7 +63,8 @@ namespace MWWorld { Render_CollisionDebug, Render_Wireframe, - Render_Pathgrid + Render_Pathgrid, + Render_Compositors }; private: From 9cf6f27f9629904cadf07302ef760a7367f31149 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 29 Apr 2012 03:38:00 +0200 Subject: [PATCH 015/289] small fix --- apps/openmw/mwrender/compositors.cpp | 49 +++++++++++++++++++++ apps/openmw/mwrender/compositors.hpp | 53 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 2 - 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwrender/compositors.cpp create mode 100644 apps/openmw/mwrender/compositors.hpp diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp new file mode 100644 index 000000000..4c9f08b72 --- /dev/null +++ b/apps/openmw/mwrender/compositors.cpp @@ -0,0 +1,49 @@ +#include "compositors.hpp" + +#include +#include + +using namespace MWRender; + +Compositors::Compositors(Ogre::Viewport* vp) : + mViewport(vp) + , mEnabled(true) +{ +} + +Compositors::~Compositors() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); +} + +void Compositors::setEnabled (const bool enabled) +{ + for (CompositorMap::iterator it=mCompositors.begin(); + it != mCompositors.end(); ++it) + { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, it->first, enabled && it->second.first); + } + mEnabled = enabled; +} + +void Compositors::addCompositor (const std::string& name, const int priority) +{ + int id = 0; + + for (CompositorMap::iterator it=mCompositors.begin(); + it != mCompositors.end(); ++it) + { + if (it->second.second > priority) + break; + ++id; + } + Ogre::CompositorManager::getSingleton().addCompositor (mViewport, name, id); + + mCompositors[name] = std::make_pair(false, priority); +} + +void Compositors::setCompositorEnabled (const std::string& name, const bool enabled) +{ + mCompositors[name].first = enabled; + Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp new file mode 100644 index 000000000..50b53f84a --- /dev/null +++ b/apps/openmw/mwrender/compositors.hpp @@ -0,0 +1,53 @@ +#ifndef GAME_MWRENDER_COMPOSITORS_H +#define GAME_MWRENDER_COMPOSITORS_H + +#include +#include + +namespace Ogre +{ + class Viewport; +} + +namespace MWRender +{ + typedef std::map < std::string, std::pair > CompositorMap; + + /// \brief Manages a set of compositors for one viewport + class Compositors + { + public: + Compositors(Ogre::Viewport* vp); + virtual ~Compositors(); + + /** + * enable or disable all compositors globally + */ + void setEnabled (const bool enabled); + + bool toggle() { setEnabled(!mEnabled); return mEnabled; } + + /** + * enable or disable a specific compositor + * @note enable has no effect if all compositors are globally disabled + */ + void setCompositorEnabled (const std::string& name, const bool enabled); + + /** + * @param name of compositor + * @param priority, lower number will be first in the chain + */ + void addCompositor (const std::string& name, const int priority); + + protected: + /// maps compositor name to its "enabled" state + CompositorMap mCompositors; + + bool mEnabled; + + Ogre::Viewport* mViewport; + }; + +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 4e3296598..09aa1df6d 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -159,8 +159,6 @@ class RenderingManager: private RenderingInterface { bool mSunEnabled; - bool mCompositorsEnabled; - SkyManager* mSkyManager; OcclusionQuery* mOcclusionQuery; From 5f8c08b18b65443805dd5f73802497d0d4c87e5c Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 30 Apr 2012 13:01:18 +0200 Subject: [PATCH 016/289] some work for dropping objects. --- apps/openmw/mwgui/container.cpp | 69 ++++++++++++++++----------- apps/openmw/mwgui/container.hpp | 37 ++++++++------ apps/openmw/mwgui/inventorywindow.cpp | 4 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/window_manager.cpp | 33 ++++++++----- apps/openmw/mwgui/window_manager.hpp | 10 ++-- 6 files changed, 93 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b3fe7adfb..d5eb8cff7 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -24,10 +24,10 @@ using namespace MWGui; using namespace Widgets; -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window_layout.xml", parWindowManager), mEnvironment(environment), - mDragAndDropWidget(dragAndDropWidget) + mDragAndDrop(dragAndDrop) { setText("_Main", "Name of Container"); @@ -42,27 +42,23 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro getWidget(closeButton, "CloseButton"); closeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onByeClicked); - + mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); setText("CloseButton","Close"); setText("TakeButton","Take All"); - mIsOnDragAndDrop = false; - mDraggedWidget = 0; //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget,std::string guiFile) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), mEnvironment(environment), - mDragAndDropWidget(dragAndDropWidget) + mDragAndDrop(dragAndDrop) { setText("_Main", "Name of Container"); //center(); adjustWindowCaption(); getWidget(mContainerWidget, "Items"); - - mIsOnDragAndDrop = false; - mDraggedWidget = 0; + mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); //getWidget(takeButton, "TakeButton"); //getWidget(closeButton, "CloseButton"); @@ -151,7 +147,7 @@ void ContainerWindow::open(MWWorld::Ptr& container) if(iter->getRefData().getCount() > 1) text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - //mContainerWidgets.push_back(image); + //mContainerWidgets int pos = path.rfind("."); path.erase(pos); @@ -168,37 +164,56 @@ void ContainerWindow::open(MWWorld::Ptr& container) void ContainerWindow::Update() { - if(mIsOnDragAndDrop) + if(mDragAndDrop->mIsOnDragAndDrop) { - if(mDraggedWidget) - mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); - else mIsOnDragAndDrop = false; //If this happens, there is a bug. + if(mDragAndDrop->mDraggedWidget) + mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); + else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. } } void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) { - mEnvironment.mWindowManager->setGuiMode(GM_Game); - - setVisible(false); + if(!mDragAndDrop->mIsOnDragAndDrop) + { + mEnvironment.mWindowManager->setGuiMode(GM_Game); + setVisible(false); + } } void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) { - mIsOnDragAndDrop = true; - _sender->detachFromWidget(); - _sender->attachToWidget(mDragAndDropWidget); - //std::cout << mContainerWidget->getParent()->getParent()->getName(); - _sender->setUserString("drag","on"); - mDraggedWidget = _sender; - std::cout << "selected!"; + if(!mDragAndDrop->mIsOnDragAndDrop) + { + mDragAndDrop->mIsOnDragAndDrop = true; + _sender->detachFromWidget(); + _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); + //std::cout << mContainerWidget->getParent()->getParent()->getName(); + _sender->setUserString("drag","on"); + mDragAndDrop->mDraggedWidget = _sender; + mDragAndDrop->mContainerWindow = const_cast(this); + std::cout << "selected!"; + } } void ContainerWindow::onMouseMove(MyGUI::Widget* _sender, int _left, int _top) { /*if(_sender->getUserString("drag") == "on") { - _sender->setPosition(_left,_top); - + _sender->setPosition(_left,_top); + }*/ +} + +void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) +{ + std::cout << "container clicked"; + if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here + { + mDragAndDrop->mIsOnDragAndDrop = false; + mDragAndDrop->mDraggedWidget->detachFromWidget(); + mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); + mDragAndDrop->mDraggedWidget = 0; + mDragAndDrop->mContainerWindow = 0; + } } \ No newline at end of file diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 2d1aa3ac0..742bb06f0 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -18,47 +18,54 @@ namespace MWWorld namespace MyGUI { - class Gui; - class Widget; + class Gui; + class Widget; } namespace MWGui { class WindowManager; + class ContainerWindow; } namespace MWGui { - + class DragAndDrop + { + public: + bool mIsOnDragAndDrop; + ContainerWindow* mContainerWindow; + MyGUI::Widget* mDraggedWidget; + MyGUI::Widget* mDragAndDropWidget; + }; class ContainerWindow : public WindowBase { - public: - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget); - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget, - std::string guiFile); + public: + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop); + ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop, + std::string guiFile); - void open(MWWorld::Ptr& container); - void setName(std::string contName); - void Update(); + void open(MWWorld::Ptr& container); + void setName(std::string contName); + void Update(); - virtual ~ContainerWindow(); + virtual ~ContainerWindow(); - protected: + protected: MWWorld::Environment& mEnvironment; std::vector mContainerWidgets; MyGUI::ItemBoxPtr mContainerWidget; MyGUI::ButtonPtr takeButton; MyGUI::ButtonPtr closeButton; - MyGUI::Widget* mDragAndDropWidget; - bool mIsOnDragAndDrop; - MyGUI::Widget* mDraggedWidget; + DragAndDrop* mDragAndDrop; void onByeClicked(MyGUI::Widget* _sender); void onSelectedItem(MyGUI::Widget* _sender); + void onContainerClicked(MyGUI::Widget* _sender); void onMouseMove(MyGUI::Widget* _sender, int _left, int _top); //MWWorld::Ptr& mContainer; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index efc9106e9..cf2cfb537 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -21,8 +21,8 @@ namespace MWGui { - InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget) - :ContainerWindow(parWindowManager,environment,dragAndDropWidget,"openmw_inventory_window_layout.xml") + InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) + :ContainerWindow(parWindowManager,environment,dragAndDrop,"openmw_inventory_window_layout.xml") { } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index c60889d73..184cab183 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -24,7 +24,7 @@ namespace MWGui class InventoryWindow : public MWGui::ContainerWindow { public: - InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,MyGUI::Widget* dragAndDropWidget); + InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop); void openInventory(); }; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index f2adfe1e1..9db7892e2 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -36,7 +36,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, , mMessageBoxManager(NULL) , console(NULL) , mJournal(NULL) - , dialogueWindow(nullptr) + , mDialogueWindow(nullptr) , mCharGen(NULL) , playerClass() , playerName() @@ -77,6 +77,12 @@ WindowManager::WindowManager(MWWorld::Environment& environment, MyGUI::Widget* dragAndDropWidget = gui->createWidgetT("Widget","",0,0,w,h,MyGUI::Align::Default,"DragAndDrop","DragAndDropWidget"); dragAndDropWidget->setVisible(false); + DragAndDrop* mDragAndDrop = new DragAndDrop(); + mDragAndDrop->mIsOnDragAndDrop = false; + mDragAndDrop->mDraggedWidget = 0; + mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; + mDragAndDrop->mContainerWindow = 0; + hud = new HUD(w,h, showFPSLevel); menu = new MainMenu(w,h); map = new MapWindow(*this); @@ -84,9 +90,9 @@ WindowManager::WindowManager(MWWorld::Environment& environment, console = new Console(w,h, environment, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); - dialogueWindow = new DialogueWindow(*this,environment); - containerWindow = new ContainerWindow(*this,environment,dragAndDropWidget); - mInventoryWindow = new InventoryWindow(*this,environment,dragAndDropWidget); + mDialogueWindow = new DialogueWindow(*this,environment); + mContainerWindow = new ContainerWindow(*this,environment,mDragAndDrop); + mInventoryWindow = new InventoryWindow(*this,environment,mDragAndDrop); // The HUD is always on hud->setVisible(true); @@ -124,10 +130,11 @@ WindowManager::~WindowManager() delete menu; delete stats; delete mJournal; - delete dialogueWindow; - delete containerWindow; + delete mDialogueWindow; + delete mContainerWindow; delete mInventoryWindow; delete mCharGen; + delete mDragAndDrop; cleanupGarbage(); } @@ -186,8 +193,8 @@ void WindowManager::updateVisible() stats->setVisible(false); console->disable(); mJournal->setVisible(false); - dialogueWindow->setVisible(false); - containerWindow->setVisible(false); + mDialogueWindow->setVisible(false); + mContainerWindow->setVisible(false); mInventoryWindow->setVisible(false); // Mouse is visible whenever we're not in game mode @@ -229,12 +236,12 @@ void WindowManager::updateVisible() break; } case GM_Container: - containerWindow->setVisible(true); + mContainerWindow->setVisible(true); mInventoryWindow->setVisible(true); mInventoryWindow->openInventory(); break; case GM_Dialogue: - dialogueWindow->open(); + mDialogueWindow->open(); break; case GM_InterMessageBox: if(!mMessageBoxManager->isInteractiveMessageBox()) { @@ -413,11 +420,11 @@ const std::string &WindowManager::getGameSettingString(const std::string &id, co void WindowManager::onDialogueWindowBye() { - if (dialogueWindow) + if (mDialogueWindow) { //FIXME set some state and stuff? //removeDialog(dialogueWindow); - dialogueWindow->setVisible(false); + mDialogueWindow->setVisible(false); } setGuiMode(GM_Game); } @@ -426,7 +433,7 @@ void WindowManager::onFrame (float frameDuration) { mMessageBoxManager->onFrame(frameDuration); mInventoryWindow->Update(); - containerWindow->Update(); + mContainerWindow->Update(); } const ESMS::ESMStore& WindowManager::getStore() const diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 438a99a0e..a666b5854 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -63,6 +63,7 @@ namespace MWGui class JournalWindow; class CharacterCreation; class ContainerWindow; + class DragAndDrop; class InventoryWindow; class TextInputDialog; class InfoBoxDialog; @@ -126,9 +127,9 @@ namespace MWGui updateVisible(); } - MWGui::DialogueWindow* getDialogueWindow() {return dialogueWindow;} + MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} - MWGui::ContainerWindow* getContainerWindow() {return containerWindow;} + MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} MyGUI::Gui* getGui() const { return gui; } @@ -203,8 +204,9 @@ namespace MWGui MessageBoxManager *mMessageBoxManager; Console *console; JournalWindow* mJournal; - DialogueWindow *dialogueWindow; - ContainerWindow *containerWindow; + DialogueWindow *mDialogueWindow; + ContainerWindow *mContainerWindow; + DragAndDrop* mDragAndDrop; InventoryWindow *mInventoryWindow; CharacterCreation* mCharGen; From 9e6531a6c6faf077e402ed1955682026cecfc7d8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 30 Apr 2012 21:22:26 +0200 Subject: [PATCH 017/289] fix for dark corners bug on some cards --- apps/openmw/mwrender/shaderhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/shaderhelper.cpp b/apps/openmw/mwrender/shaderhelper.cpp index 1d29be2b8..59154a295 100644 --- a/apps/openmw/mwrender/shaderhelper.cpp +++ b/apps/openmw/mwrender/shaderhelper.cpp @@ -258,7 +258,7 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s outStream << " float3 lightingFinal = lightColour.xyz * diffuse.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n" " float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n" - " oColor.xyz = lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue); \n" + " oColor.xyz = saturate(lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue)); \n" // saturate output to prevent negative output colors - TODO: replace this once there is HDR-rendering " oColor.a = tex.a * diffuse.a * vertexColour.a; \n"; if (mrt) outStream << From 02dad448fe54cd99f3e672ba3ccfd94f35c37651 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 May 2012 05:38:43 +0200 Subject: [PATCH 018/289] make the wireframe mode not affect sky --- apps/openmw/mwrender/sky.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index da2e7446a..72f88c6c5 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -113,6 +113,7 @@ void BillboardObject::init(const String& textureName, p->setSelfIllumination(1.0,1.0,1.0); p->setDiffuse(0.0,0.0,0.0,1.0); p->setAmbient(0.0,0.0,0.0); + p->setPolygonModeOverrideable(false); p->createTextureUnitState(textureName); mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); @@ -520,6 +521,7 @@ void SkyManager::create() mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); + mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); mStarsMaterials[i] = mp; } @@ -535,6 +537,7 @@ void SkyManager::create() mAtmosphereDay = mRootNode->createChildSceneNode(); mAtmosphereDay->attachObject(atmosphere_ent); mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); // Atmosphere shader HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, @@ -598,6 +601,7 @@ void SkyManager::create() SceneNode* clouds_node = mRootNode->createChildSceneNode(); clouds_node->attachObject(clouds_ent); mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); + mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); clouds_ent->setCastShadows(false); // Clouds vertex shader From 60ad6f01d40af09443868ed9019173db460ea850 Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 6 May 2012 11:04:07 +0200 Subject: [PATCH 019/289] another step towards drand and drop. --- apps/openmw/mwgui/container.cpp | 104 ++++++++++++++++++++++---------- apps/openmw/mwgui/container.hpp | 8 +++ 2 files changed, 81 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index d5eb8cff7..083ce2f64 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -22,12 +22,29 @@ using namespace MWGui; using namespace Widgets; +class ItemWidget: public MyGUI::ImageBox +{ +public: + ItemWidget() + :ImageBox() + { + } + virtual ~ItemWidget() + { + } + + void setPtr(MWWorld::Ptr &ptr,int pos){mPtr = ptr;mPos = pos;} + + MWWorld::Ptr mPtr; + int mPos; +}; ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window_layout.xml", parWindowManager), mEnvironment(environment), - mDragAndDrop(dragAndDrop) + mDragAndDrop(dragAndDrop), + mContainer() { setText("_Main", "Name of Container"); @@ -52,7 +69,8 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), mEnvironment(environment), - mDragAndDrop(dragAndDrop) + mDragAndDrop(dragAndDrop), + mContainer() { setText("_Main", "Name of Container"); //center(); @@ -81,11 +99,18 @@ void ContainerWindow::setName(std::string contName) void ContainerWindow::open(MWWorld::Ptr& container) { + mContainer = container; setName(MWWorld::Class::get(container).getName(container)); //MWWorld::ContainerStore* containerStore = container.getContainerStore(); + drawItems(); + setVisible(true); +} - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(container).getContainerStore(container); - +void ContainerWindow::drawItems() +{ + MyGUI::Gui::getInstance().destroyWidgets(mContainerWidget->getEnumerator()); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + //mContainerWidget-> /*MWWorld::ManualRef furRef (mWindowManager.getStore(), "fur_cuirass"); furRef.getPtr().getRefData().setCount (5); @@ -121,45 +146,45 @@ void ContainerWindow::open(MWWorld::Ptr& container) // ESMS::LiveCellRef *ref = iter->get(); - int x = 4; int y = 4; int count = 0; + for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) { - std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); count++; - - MyGUI::ImageBox* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); - image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); - //image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); - x += 36; - if(count % 20 == 0) + if(iter->getRefData().getCount() > 0) { + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); + ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); + //image->setPtr(*iter,count); + image->mPos = count; + + //image->mPtr = *iter; + //image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); + /*x += 36; + if(count % 20 == 0) + { y += 36; x = 4; count = 0; + }*/ + + if(iter->getRefData().getCount() > 1) + text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + //mContainerWidgets + + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + //std::cout << path << std::endl; + image->setImageTexture(path); } - - if(iter->getRefData().getCount() > 1) - text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - - //mContainerWidgets - - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - //std::cout << path << std::endl; - image->setImageTexture(path); - } - - - - - setVisible(true); + } } void ContainerWindow::Update() @@ -188,10 +213,26 @@ void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) mDragAndDrop->mIsOnDragAndDrop = true; _sender->detachFromWidget(); _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); + + ItemWidget* item = static_cast(_sender); + + int count = 0; + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) + { + count++; + if(count == item->mPos) + { + iter->getRefData().setCount(0); + break; + } + } + //containerStore. //std::cout << mContainerWidget->getParent()->getParent()->getName(); _sender->setUserString("drag","on"); mDragAndDrop->mDraggedWidget = _sender; mDragAndDrop->mContainerWindow = const_cast(this); + drawItems(); std::cout << "selected!"; } } @@ -210,6 +251,7 @@ void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) std::cout << "container clicked"; if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { + //mContainer.getContainerStore()->add(mDragAndDrop->mDraggedWidget-> mDragAndDrop->mIsOnDragAndDrop = false; mDragAndDrop->mDraggedWidget->detachFromWidget(); mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 742bb06f0..b8f76a355 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -10,6 +10,7 @@ #include "window_base.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/containerstore.hpp" +#include namespace MWWorld { @@ -38,6 +39,8 @@ namespace MWGui ContainerWindow* mContainerWindow; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; + + MWWorld::Ptr mItem; }; class ContainerWindow : public WindowBase @@ -63,6 +66,11 @@ namespace MWGui MyGUI::ButtonPtr closeButton; DragAndDrop* mDragAndDrop; + MWWorld::Ptr mContainer; + bool mIsValid;//is in the right GUI Mode + + void drawItems(); + void onByeClicked(MyGUI::Widget* _sender); void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); From e9134717d62c95b6d16c2c8e515516a5a372c136 Mon Sep 17 00:00:00 2001 From: gugus Date: Tue, 8 May 2012 12:59:47 +0200 Subject: [PATCH 020/289] the GUI part of drag and drop is working --- apps/openmw/mwgui/container.cpp | 42 ++++++++++------------------ apps/openmw/mwgui/itemwidget.hpp | 18 ++++++++++++ apps/openmw/mwgui/window_manager.cpp | 2 ++ 3 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 apps/openmw/mwgui/itemwidget.hpp diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 083ce2f64..454dd05c3 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -18,26 +18,11 @@ #include #include "../mwworld/class.hpp" #include "../mwinput/inputmanager.hpp" +#include "itemwidget.hpp" using namespace MWGui; using namespace Widgets; -class ItemWidget: public MyGUI::ImageBox -{ -public: - ItemWidget() - :ImageBox() - { - } - virtual ~ItemWidget() - { - } - - void setPtr(MWWorld::Ptr &ptr,int pos){mPtr = ptr;mPos = pos;} - - MWWorld::Ptr mPtr; - int mPos; -}; ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) @@ -149,39 +134,36 @@ void ContainerWindow::drawItems() int x = 4; int y = 4; int count = 0; - + int index = 0; for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) { - count++; + index++; if(iter->getRefData().getCount() > 0) { + count++; std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); - //image->setPtr(*iter,count); - image->mPos = count; - - //image->mPtr = *iter; + image->mPos = index; + image->mPtr = *iter; //image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); - /*x += 36; + x += 36; if(count % 20 == 0) { y += 36; x = 4; count = 0; - }*/ + } if(iter->getRefData().getCount() > 1) text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - //mContainerWidgets int pos = path.rfind("."); path.erase(pos); path.append(".dds"); - //std::cout << path << std::endl; image->setImageTexture(path); } } @@ -251,7 +233,13 @@ void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) std::cout << "container clicked"; if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { - //mContainer.getContainerStore()->add(mDragAndDrop->mDraggedWidget-> + ItemWidget* item = static_cast(mDragAndDrop->mDraggedWidget); + std::cout << item->mPos << item->mPtr.getTypeName(); + if(item->mPtr.getContainerStore() == 0) std::cout << "nocontainer!"; + std::cout << item->mPtr.getContainerStore()->getType(item->mPtr); + MWWorld::Ptr ptr = item->mPtr; + //MWWorld::World + //mContainer.getContainerStore()->add(item->mPtr); mDragAndDrop->mIsOnDragAndDrop = false; mDragAndDrop->mDraggedWidget->detachFromWidget(); mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp new file mode 100644 index 000000000..ff65bfd4d --- /dev/null +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -0,0 +1,18 @@ +#ifndef MWGUI_ITEM_WIDGET_H +#define MWGUI_ITEM_WIDGET_H +#include +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + class ItemWidget: public MyGUI::ImageBox + { + MYGUI_RTTI_DERIVED( ItemWidget ) + public: + + MWWorld::Ptr mPtr; + int mPos; + }; +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 9db7892e2..e72f635bf 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -9,6 +9,7 @@ #include "messagebox.hpp" #include "container.hpp" #include "inventorywindow.hpp" +#include "itemwidget.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -68,6 +69,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment, //Register own widgets with MyGUI MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); // Get size info from the Gui object assert(gui); From 60affb5288f7d2abb53be16bf33a9b846bb2f96d Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 10 May 2012 12:47:15 +0200 Subject: [PATCH 021/289] removed include 2 --- apps/openmw/mwgui/formatting.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index c8f2c9e44..a1e115491 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -3,8 +3,6 @@ #include -#include - namespace MWGui { struct TextStyle From 65ccfba191318fd7b3bd4307ae62e08c9c6a26ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 08:15:22 +0200 Subject: [PATCH 022/289] resize both the left and the right pane of the stats window --- apps/openmw/mwgui/stats_window.cpp | 4 + apps/openmw/mwgui/stats_window.hpp | 3 + files/mygui/openmw_stats_window_layout.xml | 109 +++++++++++---------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 8b688984f..9e6e17391 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -60,6 +60,8 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) getWidget(skillAreaWidget, "Skills"); getWidget(skillClientWidget, "SkillClient"); getWidget(skillScrollerWidget, "SkillScroller"); + getWidget(mLeftPane, "LeftPane"); + getWidget(mRightPane, "RightPane"); skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition); updateScroller(); @@ -93,6 +95,8 @@ void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) void StatsWindow::onWindowResize(MyGUI::Window* window) { + mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); + mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) ); updateScroller(); } diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index ecbc82894..b201b3387 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -57,6 +57,9 @@ namespace MWGui static const int lineHeight; + MyGUI::Widget* mLeftPane; + MyGUI::Widget* mRightPane; + MyGUI::WidgetPtr skillAreaWidget, skillClientWidget; MyGUI::ScrollBar* skillScrollerWidget; int lastPos, clientHeight; diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 4f3f80e89..4056216ad 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -3,59 +3,68 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1f1edea6af072a49889c5fac07fe2ab01aece314 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 08:45:03 +0200 Subject: [PATCH 023/289] make it possible to use scroll wheel when mouse is over a skill in the stats window; set the correct track size for the scrollbar --- apps/openmw/mwgui/stats_window.cpp | 23 +++++++++++++++++++++- apps/openmw/mwgui/stats_window.hpp | 1 + files/mygui/openmw_stats_window_layout.xml | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 9e6e17391..2736270e1 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -63,6 +63,8 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) getWidget(mLeftPane, "LeftPane"); getWidget(mRightPane, "RightPane"); + skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition); updateScroller(); @@ -93,6 +95,18 @@ void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) } } +void StatsWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (skillScrollerWidget->getScrollPosition() - _rel*0.3 < 0) + skillScrollerWidget->setScrollPosition(0); + else if (skillScrollerWidget->getScrollPosition() - _rel*0.3 > skillScrollerWidget->getScrollRange()-1) + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollRange()-1); + else + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollPosition() - _rel*0.3); + + onScrollChangePosition(skillScrollerWidget, skillScrollerWidget->getScrollPosition()); +} + void StatsWindow::onWindowResize(MyGUI::Window* window) { mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); @@ -237,6 +251,7 @@ void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::ImageBox* separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + separator->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillWidgets.push_back(separator); coord1.top += separator->getHeight(); @@ -249,6 +264,7 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); groupWidget->setCaption(label); + groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillWidgets.push_back(groupWidget); coord1.top += lineHeight; @@ -263,12 +279,14 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st skillNameWidget->setCaption(text); skillNameWidget->setUserString("ToolTipType", "Text"); skillNameWidget->setUserString("ToolTipText", tooltip); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); skillValueWidget->setUserString("ToolTipType", "Text"); skillValueWidget->setUserString("ToolTipText", tooltip); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); + skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -285,6 +303,7 @@ void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillWidgets.push_back(skillNameWidget); @@ -370,7 +389,7 @@ void StatsWindow::updateSkillArea() if (!skillWidgets.empty()) addSeparator(coord1, coord2); - addGroup(mWindowManager.getGameSettingString("sSign", "Sign"), coord1, coord2); + addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); addItem(sign->name, coord1, coord2); } @@ -394,6 +413,8 @@ void StatsWindow::updateScroller() { skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); + if (clientHeight != 0) + skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillAreaWidget->getHeight() ); } void StatsWindow::onPinToggled() diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index b201b3387..08c5148ec 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -54,6 +54,7 @@ namespace MWGui void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onWindowResize(MyGUI::Window* window); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); static const int lineHeight; diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 4056216ad..9406fe6bd 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -60,7 +60,7 @@ - + From 83e434e2e91c8a21becb88fac8687271cf42d8c2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 09:35:18 +0200 Subject: [PATCH 024/289] small fix --- apps/openmw/mwgui/stats_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 2736270e1..186668222 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -414,7 +414,7 @@ void StatsWindow::updateScroller() skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); if (clientHeight != 0) - skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillAreaWidget->getHeight() ); + skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() ); } void StatsWindow::onPinToggled() From a99f74702ed26f9c3bacfca5ed9688816c618132 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 09:57:43 +0200 Subject: [PATCH 025/289] workaround for a white square that appears in menubook_next texture --- files/mygui/openmw_book_layout.xml | 2 +- files/mygui/openmw_journal_layout.xml | 2 +- files/mygui/openmw_resources.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_book_layout.xml b/files/mygui/openmw_book_layout.xml index 07ebf5030..6c708cdd3 100644 --- a/files/mygui/openmw_book_layout.xml +++ b/files/mygui/openmw_book_layout.xml @@ -7,7 +7,7 @@ - + diff --git a/files/mygui/openmw_journal_layout.xml b/files/mygui/openmw_journal_layout.xml index 75bb5eea1..e4c3c7e47 100644 --- a/files/mygui/openmw_journal_layout.xml +++ b/files/mygui/openmw_journal_layout.xml @@ -7,7 +7,7 @@ - + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index 455765aad..b2bd90d10 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -72,7 +72,7 @@ - + From 9dd65dce30b4910b11d1b89f66d2bed10c06d0c3 Mon Sep 17 00:00:00 2001 From: gugus Date: Fri, 11 May 2012 11:52:07 +0200 Subject: [PATCH 026/289] Finished merging. --- apps/openmw/mwgui/container.cpp | 10 ++++------ apps/openmw/mwgui/container.hpp | 5 ++--- apps/openmw/mwgui/inventorywindow.cpp | 8 ++++---- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 2 +- apps/openmw/mwgui/window_manager.cpp | 6 +++--- apps/openmw/mwrender/objects.cpp | 4 ++-- apps/openmw/mwworld/actionopen.cpp | 8 ++++---- apps/openmw/mwworld/actionopen.hpp | 2 +- 9 files changed, 22 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 454dd05c3..b4f38b4e1 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -5,7 +5,7 @@ #include "window_manager.hpp" #include "widgets.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" #include #include @@ -25,9 +25,8 @@ using namespace MWGui; using namespace Widgets; -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window_layout.xml", parWindowManager), - mEnvironment(environment), mDragAndDrop(dragAndDrop), mContainer() { @@ -51,9 +50,8 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Enviro //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop,std::string guiFile) +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), - mEnvironment(environment), mDragAndDrop(dragAndDrop), mContainer() { @@ -183,7 +181,7 @@ void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { - mEnvironment.mWindowManager->setGuiMode(GM_Game); + MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); setVisible(false); } } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index b8f76a355..08ac7eba2 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -46,8 +46,8 @@ namespace MWGui class ContainerWindow : public WindowBase { public: - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop); - ContainerWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop, + ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop, std::string guiFile); @@ -58,7 +58,6 @@ namespace MWGui virtual ~ContainerWindow(); protected: - MWWorld::Environment& mEnvironment; std::vector mContainerWidgets; MyGUI::ItemBoxPtr mContainerWidget; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index cf2cfb537..3ae2ee9eb 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -4,7 +4,7 @@ #include "window_manager.hpp" #include "widgets.hpp" -#include "../mwworld/environment.hpp" +#include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" #include #include @@ -21,14 +21,14 @@ namespace MWGui { - InventoryWindow::InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop) - :ContainerWindow(parWindowManager,environment,dragAndDrop,"openmw_inventory_window_layout.xml") + InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) + :ContainerWindow(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") { } void InventoryWindow::openInventory() { - open(mEnvironment.mWorld->getPlayer().getPlayer()); + open(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); } } \ No newline at end of file diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 184cab183..21f27b12f 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -24,7 +24,7 @@ namespace MWGui class InventoryWindow : public MWGui::ContainerWindow { public: - InventoryWindow(WindowManager& parWindowManager,MWWorld::Environment& environment,DragAndDrop* dragAndDrop); + InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); void openInventory(); }; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 9d7a7ee87..757563efa 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -165,7 +165,7 @@ void ToolTips::findImageExtension(std::string& image) } } -IntSize ToolTips::createToolTip(const ToolTipInfo& info) +IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) { std::string caption = info.caption; std::string image = info.icon; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index ccd51d9db..db5a51f0c 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -95,9 +95,9 @@ WindowManager::WindowManager( console = new Console(w,h, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); - mDialogueWindow = new DialogueWindow(*this,environment); - mContainerWindow = new ContainerWindow(*this,environment,mDragAndDrop); - mInventoryWindow = new InventoryWindow(*this,environment,mDragAndDrop); + mDialogueWindow = new DialogueWindow(*this); + mContainerWindow = new ContainerWindow(*this,mDragAndDrop); + mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); mToolTips = new ToolTips(this); // The HUD is always on diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 27c3f818e..b9efcd3f5 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -219,7 +219,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f info.type = LT_Normal; // random starting phase for the animation - info.time = Ogre::Math::RangeRandom(0, 2 * M_PI); + info.time = Ogre::Math::RangeRandom(0, 2 * Ogre::Math::PI); // adjust the lights depending if we're in an interior or exterior cell // quadratic means the light intensity falls off quite fast, resulting in a @@ -367,7 +367,7 @@ void Objects::update(const float dt) // Light animation (pulse & flicker) it->time += dt; - const float phase = std::fmod(static_cast (it->time), (32 * 2 * M_PI)) * 20; + const float phase = std::fmod(static_cast (it->time), static_cast(32 * 2 * Ogre::Math::PI)) * 20; float pulseConstant; // These formulas are just guesswork, but they work pretty well diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e245989d7..e450585e6 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -1,6 +1,6 @@ #include "actionopen.hpp" -#include "environment.hpp" +#include "../mwbase/environment.hpp" #include "class.hpp" #include "world.hpp" #include "containerstore.hpp" @@ -14,9 +14,9 @@ namespace MWWorld mContainer = container; } - void ActionOpen::execute (Environment& environment) + void ActionOpen::execute () { - environment.mWindowManager->setGuiMode(MWGui::GM_Container); - environment.mWindowManager->getContainerWindow()->open(mContainer); + MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Container); + MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(mContainer); } } diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp index 7c660e4c9..eff26c78c 100644 --- a/apps/openmw/mwworld/actionopen.hpp +++ b/apps/openmw/mwworld/actionopen.hpp @@ -15,7 +15,7 @@ namespace MWWorld public: ActionOpen (const Ptr& container); ///< \param The Container the Player has activated. - virtual void execute (Environment& environment); + virtual void execute (); }; } From cfb7aa4343e17fc810e0be72da1c965e72bd9673 Mon Sep 17 00:00:00 2001 From: gugus Date: Fri, 11 May 2012 12:50:30 +0200 Subject: [PATCH 027/289] Drag and drop works. There is a bug with item count when doing d&d. Clean-up time :p --- apps/openmw/mwgui/container.cpp | 11 ++++++----- apps/openmw/mwgui/container.hpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b4f38b4e1..fd69e1a65 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -203,6 +203,7 @@ void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) count++; if(count == item->mPos) { + mDragAndDrop->mStore.add(*iter); iter->getRefData().setCount(0); break; } @@ -232,16 +233,16 @@ void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { ItemWidget* item = static_cast(mDragAndDrop->mDraggedWidget); - std::cout << item->mPos << item->mPtr.getTypeName(); + std::cout << item->mPos << (*mDragAndDrop->mStore.begin()).getTypeName(); if(item->mPtr.getContainerStore() == 0) std::cout << "nocontainer!"; - std::cout << item->mPtr.getContainerStore()->getType(item->mPtr); - MWWorld::Ptr ptr = item->mPtr; - //MWWorld::World - //mContainer.getContainerStore()->add(item->mPtr); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + containerStore.add(*mDragAndDrop->mStore.begin()); + mDragAndDrop->mStore.clear(); mDragAndDrop->mIsOnDragAndDrop = false; mDragAndDrop->mDraggedWidget->detachFromWidget(); mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); mDragAndDrop->mDraggedWidget = 0; mDragAndDrop->mContainerWindow = 0; + drawItems(); } } \ No newline at end of file diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 08ac7eba2..0d047bacf 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -39,7 +39,7 @@ namespace MWGui ContainerWindow* mContainerWindow; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; - + MWWorld::ContainerStore mStore; MWWorld::Ptr mItem; }; From 007a202debacd911a918a96f6cc40bf03158abe3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 16:34:36 +0200 Subject: [PATCH 028/289] cleanup 1 --- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/container.hpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b040f9d7a..8c3625468 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -180,7 +180,7 @@ void ContainerWindow::Update() } } -void ContainerWindow::onByeClicked(MyGUI::Widget* _sender) +void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 33a12968b..607138f96 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -69,12 +69,10 @@ namespace MWGui void drawItems(); - void onByeClicked(MyGUI::Widget* _sender); + void onCloseButtonClicked(MyGUI::Widget* _sender); void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); void onMouseMove(MyGUI::Widget* _sender, int _left, int _top); - - //MWWorld::Ptr& mContainer; }; } #endif // CONTAINER_H From 3a6fde5039dcfc4dfc5c8525ebff075db93e94d3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 May 2012 16:58:07 +0200 Subject: [PATCH 029/289] cleanup 2 --- apps/openmw/mwgui/container.cpp | 58 ++++++++++--------- apps/openmw/mwgui/container.hpp | 1 + .../mygui/openmw_container_window_layout.xml | 16 +---- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 7daa28775..b46dfdf53 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -1,24 +1,24 @@ #include "container.hpp" -#include -#include #include "window_manager.hpp" #include "widgets.hpp" +#include "itemwidget.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/class.hpp" +#include "../mwclass/container.hpp" +#include "../mwinput/inputmanager.hpp" + #include #include #include - #include #include -#include "../mwclass/container.hpp" -#include "../mwworld/containerstore.hpp" + #include -#include "../mwworld/class.hpp" -#include "../mwinput/inputmanager.hpp" -#include "itemwidget.hpp" using namespace MWGui; @@ -32,22 +32,26 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dr { setText("_Main", "Name of Container"); - int w = MyGUI::RenderManager::getInstance().getViewSize().width; - int h = MyGUI::RenderManager::getInstance().getViewSize().height; - setCoord(w-600,h-300,600,300); - //center(); - adjustWindowCaption(); - getWidget(mContainerWidget, "Items"); getWidget(mTakeButton, "TakeButton"); getWidget(mCloseButton, "CloseButton"); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); + mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); - setText("CloseButton","Close"); - setText("TakeButton","Take All"); - //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); + setText("CloseButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sClose")->str); + setText("TakeButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTakeAll")->str); + + // adjust buttons size to fit text + int closeButtonWidth = mCloseButton->getTextSize().width+24; + int takeButtonWidth = mTakeButton->getTextSize().width+24; + mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height); + mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height); + + int w = MyGUI::RenderManager::getInstance().getViewSize().width; + int h = MyGUI::RenderManager::getInstance().getViewSize().height; + setCoord(w-600,h-300,600,300); } ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) @@ -56,18 +60,9 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dr mContainer() { setText("_Main", "Name of Container"); - //center(); adjustWindowCaption(); getWidget(mContainerWidget, "Items"); mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); - //getWidget(takeButton, "TakeButton"); - //getWidget(closeButton, "CloseButton"); - - //closeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onByeClicked); - - //setText("CloseButton","Close"); - //setText("TakeButton","Take All"); - //mContainerWidget->eventMouseItemActivate += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); } ContainerWindow::~ContainerWindow() { @@ -76,6 +71,7 @@ ContainerWindow::~ContainerWindow() void ContainerWindow::setName(std::string contName) { setText("_Main", contName); + adjustWindowCaption(); } @@ -189,6 +185,16 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) } } +void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) +{ + if(!mDragAndDrop->mIsOnDragAndDrop) + { + /// \todo + MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + setVisible(false); + } +} + void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index db1f973e7..ad029ae80 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -70,6 +70,7 @@ namespace MWGui void drawItems(); void onCloseButtonClicked(MyGUI::Widget* _sender); + void onTakeAllButtonClicked(MyGUI::Widget* _sender); void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); void onMouseMove(MyGUI::Widget* _sender, int _left, int _top); diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 31b036468..25156c5a2 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -3,22 +3,12 @@ - - - - - - - - - + + + From d9e39bd90e742fa17707a9202e58d486660af4e5 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 11 May 2012 21:32:38 +0200 Subject: [PATCH 030/289] Changed order of plugins.cfg file paths. Changed order of plugins.cfg file paths - before when plugins.cfg file was found in global path then it was used as default one. Now the behavoiur is opposite if plugins.cfg file exists in local path then it is used as default one. --- components/files/configurationmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index ef45b6543..d5f322ebd 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -28,10 +28,10 @@ ConfigurationManager::ConfigurationManager() { setupTokensMapping(); - mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile; + mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile; if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) { - mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile; + mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile; if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) { std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl; From ed6ff0a94ac090d3357ee6885c2f4fb309530db6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 13:12:37 +0200 Subject: [PATCH 031/289] cleanup 3 --- apps/openmw/mwgui/container.cpp | 304 ++++++++---------- apps/openmw/mwgui/container.hpp | 40 ++- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- .../mygui/openmw_container_window_layout.xml | 9 +- .../mygui/openmw_inventory_window_layout.xml | 9 +- files/mygui/openmw_scroll_skin.xml | 1 - 7 files changed, 173 insertions(+), 194 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b46dfdf53..b4d369806 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -25,177 +25,23 @@ using namespace MWGui; using namespace Widgets; -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) - : WindowBase("openmw_container_window_layout.xml", parWindowManager), - mDragAndDrop(dragAndDrop), - mContainer() -{ - setText("_Main", "Name of Container"); - - getWidget(mContainerWidget, "Items"); - getWidget(mTakeButton, "TakeButton"); - getWidget(mCloseButton, "CloseButton"); - - mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); - mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); - mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); - - setText("CloseButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sClose")->str); - setText("TakeButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTakeAll")->str); - - // adjust buttons size to fit text - int closeButtonWidth = mCloseButton->getTextSize().width+24; - int takeButtonWidth = mTakeButton->getTextSize().width+24; - mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height); - mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height); - - int w = MyGUI::RenderManager::getInstance().getViewSize().width; - int h = MyGUI::RenderManager::getInstance().getViewSize().height; - setCoord(w-600,h-300,600,300); -} - -ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) +ContainerBase::ContainerBase(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), mDragAndDrop(dragAndDrop), mContainer() { - setText("_Main", "Name of Container"); - adjustWindowCaption(); getWidget(mContainerWidget, "Items"); - mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onContainerClicked); + getWidget(mItemView, "ItemView"); + + mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); + static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerBase::onWindowResize); } -ContainerWindow::~ContainerWindow() + +ContainerBase::~ContainerBase() { } -void ContainerWindow::setName(std::string contName) -{ - setText("_Main", contName); - adjustWindowCaption(); -} - - - -void ContainerWindow::open(MWWorld::Ptr container) -{ - mContainer = container; - setName(MWWorld::Class::get(container).getName(container)); - //MWWorld::ContainerStore* containerStore = container.getContainerStore(); - drawItems(); - setVisible(true); -} - -void ContainerWindow::drawItems() -{ - while (mContainerWidget->getChildCount()) - { - MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); - } - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - //mContainerWidget-> - - /*MWWorld::ManualRef furRef (mWindowManager.getStore(), "fur_cuirass"); - furRef.getPtr().getRefData().setCount (5); - MWWorld::ManualRef bukkitRef (mWindowManager.getStore(), "misc_com_bucket_01"); - MWWorld::ManualRef broomRef (mWindowManager.getStore(), "misc_com_broom_01"); - MWWorld::ManualRef goldRef (mWindowManager.getStore(), "gold_100"); - - containerStore.add(furRef.getPtr()); - containerStore.add(furRef.getPtr()); - containerStore.add(furRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(broomRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(bukkitRef.getPtr()); - containerStore.add(goldRef.getPtr());*/ - - - // ESMS::LiveCellRef *ref = iter->get(); - - int x = 4; - int y = 4; - int count = 0; - int index = 0; - - for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) - { - index++; - if(iter->getRefData().getCount() > 0) - { - count++; - std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); - ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); - image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerWindow::onSelectedItem); - image->mPos = index; - image->mPtr = *iter; - //image->eventMouseMove += MyGUI::newDelegate(this,&ContainerWindow::onMouseMove); - x += 36; - if(count % 20 == 0) - { - y += 36; - x = 4; - count = 0; - } - - if(iter->getRefData().getCount() > 1) - text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture(path); - } - } -} - -void ContainerWindow::Update() -{ - if(mDragAndDrop->mIsOnDragAndDrop) - { - if(mDragAndDrop->mDraggedWidget) - mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); - else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. - } -} - -void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) -{ - if(!mDragAndDrop->mIsOnDragAndDrop) - { - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); - setVisible(false); - } -} - -void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) -{ - if(!mDragAndDrop->mIsOnDragAndDrop) - { - /// \todo - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); - setVisible(false); - } -} - -void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) +void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { @@ -221,22 +67,13 @@ void ContainerWindow::onSelectedItem(MyGUI::Widget* _sender) //std::cout << mContainerWidget->getParent()->getParent()->getName(); _sender->setUserString("drag","on"); mDragAndDrop->mDraggedWidget = _sender; - mDragAndDrop->mContainerWindow = const_cast(this); + mDragAndDrop->mContainerWindow = const_cast(this); drawItems(); std::cout << "selected!"; } } -void ContainerWindow::onMouseMove(MyGUI::Widget* _sender, int _left, int _top) -{ - /*if(_sender->getUserString("drag") == "on") - { - _sender->setPosition(_left,_top); - - }*/ -} - -void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) +void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { std::cout << "container clicked"; if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here @@ -255,3 +92,124 @@ void ContainerWindow::onContainerClicked(MyGUI::Widget* _sender) drawItems(); } } + +void ContainerBase::onWindowResize(MyGUI::Window* window) +{ +} + +void ContainerBase::setName(std::string contName) +{ + setText("_Main", contName); + adjustWindowCaption(); +} + +void ContainerBase::open(MWWorld::Ptr container) +{ + mContainer = container; + setName(MWWorld::Class::get(container).getName(container)); + drawItems(); + setVisible(true); +} + +void ContainerBase::drawItems() +{ + while (mContainerWidget->getChildCount()) + { + MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); + } + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + int x = 4; + int y = 4; + int count = 0; + int index = 0; + + for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) + { + index++; + if(iter->getRefData().getCount() > 0) + { + count++; + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); + ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); + image->mPos = index; + image->mPtr = *iter; + x += 36; + if(count % 20 == 0) + { + y += 36; + x = 4; + count = 0; + } + + if(iter->getRefData().getCount() > 1) + text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture(path); + } + } +} + +void ContainerBase::Update() +{ + if(mDragAndDrop->mIsOnDragAndDrop) + { + if(mDragAndDrop->mDraggedWidget) + mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); + else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. + } +} + +// ------------------------------------------------------------------------------------------------ + +ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) + : ContainerBase(parWindowManager, dragAndDrop, "openmw_container_window_layout.xml") +{ + getWidget(mTakeButton, "TakeButton"); + getWidget(mCloseButton, "CloseButton"); + + mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); + mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); + + setText("CloseButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sClose")->str); + setText("TakeButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTakeAll")->str); + + // adjust buttons size to fit text + int closeButtonWidth = mCloseButton->getTextSize().width+24; + int takeButtonWidth = mTakeButton->getTextSize().width+24; + mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height); + mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height); + + int w = MyGUI::RenderManager::getInstance().getViewSize().width; + int h = MyGUI::RenderManager::getInstance().getViewSize().height; + setCoord(w-600,h-300,600,300); +} + +ContainerWindow::~ContainerWindow() +{ +} + +void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) +{ + if(!mDragAndDrop->mIsOnDragAndDrop) + { + MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + setVisible(false); + } +} + +void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) +{ + if(!mDragAndDrop->mIsOnDragAndDrop) + { + /// \todo + MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + setVisible(false); + } +} diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index ad029ae80..84b63abc8 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -27,6 +27,7 @@ namespace MWGui { class WindowManager; class ContainerWindow; + class ContainerBase; } @@ -36,44 +37,55 @@ namespace MWGui { public: bool mIsOnDragAndDrop; - ContainerWindow* mContainerWindow; + ContainerBase* mContainerWindow; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; MWWorld::ContainerStore mStore; MWWorld::Ptr mItem; }; - class ContainerWindow : public WindowBase + class ContainerBase : public WindowBase { public: - ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); - ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop, - std::string guiFile); + ContainerBase(WindowManager& parWindowManager, DragAndDrop* dragAndDrop, std::string guiFile); + virtual ~ContainerBase(); void open(MWWorld::Ptr container); void setName(std::string contName); void Update(); + protected: + MyGUI::ScrollView* mItemView; + MyGUI::Widget* mContainerWidget; + + DragAndDrop* mDragAndDrop; + MWWorld::Ptr mContainer; + + void onSelectedItem(MyGUI::Widget* _sender); + void onContainerClicked(MyGUI::Widget* _sender); + void onWindowResize(MyGUI::Window* window); + + void drawItems(); + }; + + class ContainerWindow : public ContainerBase + { + public: + ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + virtual ~ContainerWindow(); protected: std::vector mContainerWidgets; - MyGUI::ItemBoxPtr mContainerWidget; - MyGUI::ButtonPtr mTakeButton; - MyGUI::ButtonPtr mCloseButton; - DragAndDrop* mDragAndDrop; + MyGUI::Button* mTakeButton; + MyGUI::Button* mCloseButton; - MWWorld::Ptr mContainer; bool mIsValid;//is in the right GUI Mode - void drawItems(); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); - void onSelectedItem(MyGUI::Widget* _sender); - void onContainerClicked(MyGUI::Widget* _sender); - void onMouseMove(MyGUI::Widget* _sender, int _left, int _top); }; } #endif // CONTAINER_H diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index cb628ba4a..416be5367 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -22,7 +22,7 @@ namespace MWGui { InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) - :ContainerWindow(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") + : ContainerBase(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") { } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 21f27b12f..152f8b0d0 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -21,7 +21,7 @@ namespace MWGui namespace MWGui { - class InventoryWindow : public MWGui::ContainerWindow + class InventoryWindow : public MWGui::ContainerBase { public: InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 25156c5a2..9679519d4 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -3,8 +3,13 @@ - - + + + + + + + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index 766cacdb1..40d89f221 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -3,7 +3,7 @@ - + @@ -14,7 +14,12 @@ - + + + + + + diff --git a/files/mygui/openmw_scroll_skin.xml b/files/mygui/openmw_scroll_skin.xml index 39437d54e..64e467661 100644 --- a/files/mygui/openmw_scroll_skin.xml +++ b/files/mygui/openmw_scroll_skin.xml @@ -4,7 +4,6 @@ - From 7723044df0009c58beb4fc4a1c00478cf352a147 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 13:30:34 +0200 Subject: [PATCH 032/289] added the item tooltips --- apps/openmw/mwgui/container.cpp | 5 +++-- apps/openmw/mwgui/itemwidget.hpp | 3 +-- apps/openmw/mwgui/tooltips.cpp | 9 ++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b4d369806..65df9a9dd 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -80,7 +80,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { ItemWidget* item = static_cast(mDragAndDrop->mDraggedWidget); std::cout << item->mPos << (*mDragAndDrop->mStore.begin()).getTypeName(); - if(item->mPtr.getContainerStore() == 0) std::cout << "nocontainer!"; + if((*item->getUserData()).getContainerStore() == 0) std::cout << "nocontainer!"; MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); containerStore.add(*mDragAndDrop->mStore.begin()); mDragAndDrop->mStore.clear(); @@ -135,8 +135,9 @@ void ContainerBase::drawItems() ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); + image->setUserString("ToolTipType", "ItemPtr"); + image->setUserData(*iter); image->mPos = index; - image->mPtr = *iter; x += 36; if(count % 20 == 0) { diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp index ff65bfd4d..0b204b10e 100644 --- a/apps/openmw/mwgui/itemwidget.hpp +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -10,9 +10,8 @@ namespace MWGui MYGUI_RTTI_DERIVED( ItemWidget ) public: - MWWorld::Ptr mPtr; int mPos; }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 7dc1ecba7..baa38f430 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -61,12 +61,14 @@ void ToolTips::onFrame(float frameDuration) else if (type == "Text") { info.text = text; + tooltipSize = createToolTip(info); } else if (type == "CaptionText") { std::string caption = focus->getUserString("ToolTipCaption"); info.caption = caption; info.text = text; + tooltipSize = createToolTip(info); } else if (type == "ImageCaptionText") { @@ -77,8 +79,13 @@ void ToolTips::onFrame(float frameDuration) info.text = text; info.caption = caption; info.icon = image; + tooltipSize = createToolTip(info); + } + else if (type == "ItemPtr") + { + mFocusObject = *focus->getUserData(); + tooltipSize = getToolTipViaPtr(); } - tooltipSize = createToolTip(info); IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); From d64fccec6fe71e9eca42750edf4043aa17a65c06 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 13:46:03 +0200 Subject: [PATCH 033/289] display the item count in the tooltip --- apps/openmw/mwclass/activator.cpp | 2 +- apps/openmw/mwclass/apparatus.cpp | 2 +- apps/openmw/mwclass/armor.cpp | 2 +- apps/openmw/mwclass/book.cpp | 2 +- apps/openmw/mwclass/clothing.cpp | 2 +- apps/openmw/mwclass/ingredient.cpp | 2 +- apps/openmw/mwclass/light.cpp | 2 +- apps/openmw/mwclass/lockpick.cpp | 2 +- apps/openmw/mwclass/misc.cpp | 2 +- apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwclass/probe.cpp | 2 +- apps/openmw/mwclass/repair.cpp | 2 +- apps/openmw/mwclass/weapon.cpp | 2 +- apps/openmw/mwgui/container.cpp | 11 ++++++----- apps/openmw/mwgui/container.hpp | 3 +-- apps/openmw/mwgui/tooltips.cpp | 8 ++++++++ apps/openmw/mwgui/tooltips.hpp | 3 +++ 17 files changed, 31 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 6faaacf31..505f61f4c 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -79,7 +79,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 24d08b804..0ce01024d 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -122,7 +122,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 1598085f3..9bd5f03d6 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -220,7 +220,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; std::string text; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 72ebb4b80..3d8adf014 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -119,7 +119,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 57d5e1a64..e81bb7419 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -188,7 +188,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 7a1cea7ff..c0186da37 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -120,7 +120,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 49c80b011..d9af2e73f 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -163,7 +163,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 89cff2855..5bb677646 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -132,7 +132,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 76444318b..70ba16c03 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -138,7 +138,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 51d3fefae..ffc838639 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -122,7 +122,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 5161301e0..1e713f0a5 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -131,7 +131,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index ce68843ed..5666a95a5 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -121,7 +121,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; std::string text; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ed31606d0..3865358bd 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -272,7 +272,7 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name; + info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 65df9a9dd..792010f38 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -34,7 +34,6 @@ ContainerBase::ContainerBase(WindowManager& parWindowManager,DragAndDrop* dragAn getWidget(mItemView, "ItemView"); mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); - static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerBase::onWindowResize); } ContainerBase::~ContainerBase() @@ -93,10 +92,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) } } -void ContainerBase::onWindowResize(MyGUI::Window* window) -{ -} - void ContainerBase::setName(std::string contName) { setText("_Main", contName); @@ -190,12 +185,18 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dr int w = MyGUI::RenderManager::getInstance().getViewSize().width; int h = MyGUI::RenderManager::getInstance().getViewSize().height; setCoord(w-600,h-300,600,300); + + static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize); } ContainerWindow::~ContainerWindow() { } +void ContainerWindow::onWindowResize(MyGUI::Window* window) +{ +} + void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 84b63abc8..2552922f8 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -63,7 +63,6 @@ namespace MWGui void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); - void onWindowResize(MyGUI::Window* window); void drawItems(); }; @@ -83,7 +82,7 @@ namespace MWGui bool mIsValid;//is in the right GUI Mode - + void onWindowResize(MyGUI::Window* window); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); }; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index baa38f430..aa189b2e8 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -357,6 +357,14 @@ std::string ToolTips::getMiscString(const std::string& text, const std::string& return "\n" + prefix + ": " + text; } +std::string ToolTips::getCountString(const int value) +{ + if (value == 1) + return ""; + else + return " (" + boost::lexical_cast(value) + ")"; +} + void ToolTips::toggleFullHelp() { mFullHelp = !mFullHelp; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index fafe471a5..d20360a79 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -53,6 +53,9 @@ namespace MWGui static std::string toString(const float value); static std::string toString(const int value); + static std::string getCountString(const int value); + ///< @return blank string if count is 1, or else " (value)" + private: MyGUI::Widget* mDynamicToolTipBox; From 722af60337e4faecc0e13a2ba2eefd8f244eebb7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 14:01:59 +0200 Subject: [PATCH 034/289] implemented the "Take all" button --- apps/openmw/mwgui/container.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 792010f38..0b264d48c 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -9,6 +9,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" #include "../mwclass/container.hpp" #include "../mwinput/inputmanager.hpp" @@ -210,7 +211,22 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { - /// \todo + // transfer everything into the player's inventory + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); + + for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) + { + if(iter->getRefData().getCount() > 0) + { + playerStore.add(*iter); + } + } + + containerStore.clear(); + MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); setVisible(false); } From a31a9e51d3e3b853ca02db3d667fd417dbf2d5df Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 14:29:49 +0200 Subject: [PATCH 035/289] add the sound for item drag&drop --- apps/openmw/mwclass/misc.cpp | 15 ++++++++++----- apps/openmw/mwgui/container.cpp | 20 ++++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 70ba16c03..936dc4558 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -138,11 +138,18 @@ namespace MWClass ptr.get(); MWGui::ToolTipInfo info; - info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); - info.icon = ref->base->icon; const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + int count = ptr.getRefData().getCount(); + // gold has count both as reference count and as value, multiply them together to get real count + bool isGold = (ref->base->name == store.gameSettings.search("sGold")->str); + if (isGold) + count *= ref->base->data.value; + + info.caption = ref->base->name + MWGui::ToolTips::getCountString(count); + info.icon = ref->base->icon; + if (ref->ref.soul != "") { const ESM::Creature *creature = store.creatures.search(ref->ref.soul); @@ -151,9 +158,7 @@ namespace MWClass std::string text; - if (ref->base->name == store.gameSettings.search("sGold")->str) - info.caption += " (" + boost::lexical_cast(ref->base->data.value) + ")"; - else + if (!isGold) { text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 0b264d48c..661495559 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -12,6 +12,7 @@ #include "../mwworld/player.hpp" #include "../mwclass/container.hpp" #include "../mwinput/inputmanager.hpp" +#include "../mwsound/soundmanager.hpp" #include #include @@ -53,34 +54,41 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) int count = 0; MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::Ptr object; for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) { count++; if(count == item->mPos) { mDragAndDrop->mStore.add(*iter); + object = *iter; iter->getRefData().setCount(0); break; } } - //containerStore. - //std::cout << mContainerWidget->getParent()->getParent()->getName(); + + std::string sound = MWWorld::Class::get(object).getUpSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + _sender->setUserString("drag","on"); mDragAndDrop->mDraggedWidget = _sender; mDragAndDrop->mContainerWindow = const_cast(this); drawItems(); - std::cout << "selected!"; } } void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { - std::cout << "container clicked"; if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { ItemWidget* item = static_cast(mDragAndDrop->mDraggedWidget); - std::cout << item->mPos << (*mDragAndDrop->mStore.begin()).getTypeName(); - if((*item->getUserData()).getContainerStore() == 0) std::cout << "nocontainer!"; + + MWWorld::Ptr object = *item->getUserData(); + assert(object.getContainerStore() && "Item is not in a container!"); + + std::string sound = MWWorld::Class::get(object).getDownSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); containerStore.add(*mDragAndDrop->mStore.begin()); mDragAndDrop->mStore.clear(); From 5b0251b09f1123874b5af665aa44eae5e452489c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 16:17:03 +0200 Subject: [PATCH 036/289] item stacking --- apps/openmw/mwclass/armor.cpp | 8 ++++++++ apps/openmw/mwclass/armor.hpp | 3 +++ apps/openmw/mwclass/clothing.cpp | 8 ++++++++ apps/openmw/mwclass/clothing.hpp | 3 +++ apps/openmw/mwclass/weapon.cpp | 8 ++++++++ apps/openmw/mwclass/weapon.hpp | 3 +++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 6 +++++- apps/openmw/mwworld/containerstore.cpp | 18 +++++++++++++++++- 9 files changed, 60 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index fb34e4c88..87a5dde27 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -248,4 +248,12 @@ namespace MWClass return info; } + + std::string Armor::getEnchantment (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->enchant; + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index c757587e5..3ff101a5e 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -55,6 +55,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id + + virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; + ///< @return the enchantment ID if the object is enchanted, otherwise an empty string }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 620b664cc..a242874df 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -201,4 +201,12 @@ namespace MWClass return info; } + + std::string Clothing::getEnchantment (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->enchant; + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index afb184999..9b9322969 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -49,6 +49,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id + + virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; + ///< @return the enchantment ID if the object is enchanted, otherwise an empty string }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index fcfaebcb7..0ddf19d3c 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -339,4 +339,12 @@ namespace MWClass return info; } + + std::string Weapon::getEnchantment (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->enchant; + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 9c5f43bd3..c27a39620 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -55,6 +55,9 @@ namespace MWClass virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const; ///< Return the put down sound Id + + virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; + ///< @return the enchantment ID if the object is enchanted, otherwise an empty string }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 78ed5ca2e..151d913be 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -181,4 +181,9 @@ namespace MWWorld { return false; } + + std::string Class::getEnchantment (const Ptr& ptr) const + { + return ""; + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index e69b8f2ac..d7a2d2d75 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -136,7 +136,7 @@ namespace MWWorld ///< Set or unset a stance. virtual bool getStance (const Ptr& ptr, Stance stance, bool ignoreForce = false) const; - ////< Check if a stance is active or not. + ///< Check if a stance is active or not. virtual float getSpeed (const Ptr& ptr) const; ///< Return movement speed. @@ -179,6 +179,10 @@ namespace MWWorld virtual std::string getDownSoundId (const Ptr& ptr) const; ///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) + + virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; + ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + /// (default implementation: return empty string) }; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 2800b6f3c..4f799f576 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -9,6 +9,7 @@ #include "manualref.hpp" #include "refdata.hpp" +#include "class.hpp" namespace { @@ -46,7 +47,22 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() void MWWorld::ContainerStore::add (const Ptr& ptr) { - /// \todo implement item stacking + // determine whether to stack or not + // item stacking depends on owner, script, enchantment and name + for (MWWorld::ContainerStoreIterator iter (begin(getType(ptr))); iter!=end(); ++iter) + { + if ( iter->mCellRef->refID == ptr.mCellRef->refID + && MWWorld::Class::get(*iter).getScript(*iter) == MWWorld::Class::get(ptr).getScript(ptr) + && MWWorld::Class::get(*iter).getEnchantment(*iter) == MWWorld::Class::get(ptr).getEnchantment(ptr) + && iter->mCellRef->owner == ptr.mCellRef->owner) + { + // stack + iter->getRefData().setCount( iter->getRefData().getCount() + ptr.getRefData().getCount() ); + + flagAsModified(); + return; + } + } switch (getType (ptr)) { From 9f2595183b039a29f3c79788a4048063041521d9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 16:30:27 +0200 Subject: [PATCH 037/289] type --- apps/openmw/mwworld/containerstore.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 4f799f576..32e2da0ae 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -47,9 +47,11 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() void MWWorld::ContainerStore::add (const Ptr& ptr) { + int type = getType(ptr); + // determine whether to stack or not // item stacking depends on owner, script, enchantment and name - for (MWWorld::ContainerStoreIterator iter (begin(getType(ptr))); iter!=end(); ++iter) + for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { if ( iter->mCellRef->refID == ptr.mCellRef->refID && MWWorld::Class::get(*iter).getScript(*iter) == MWWorld::Class::get(ptr).getScript(ptr) @@ -64,7 +66,7 @@ void MWWorld::ContainerStore::add (const Ptr& ptr) } } - switch (getType (ptr)) + switch (type) { case Type_Potion: potions.list.push_back (*ptr.get()); break; case Type_Apparatus: appas.list.push_back (*ptr.get()); break; From 1abf70692cb2381886e9586a66d766333fbd42b6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 18:24:47 +0200 Subject: [PATCH 038/289] added a scrollbar to the item container, dynamic positioning of items, fixed the item count display bug --- apps/openmw/mwgui/container.cpp | 24 ++++++++++++------- apps/openmw/mwgui/inventorywindow.cpp | 6 +++++ apps/openmw/mwgui/inventorywindow.hpp | 3 +++ .../mygui/openmw_container_window_layout.xml | 6 ++--- .../mygui/openmw_inventory_window_layout.xml | 2 +- files/mygui/openmw_list.skin.xml | 3 ++- files/mygui/openmw_scroll_skin.xml | 5 ++++ 7 files changed, 35 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 661495559..d79693114 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -125,7 +125,8 @@ void ContainerBase::drawItems() int x = 4; int y = 4; - int count = 0; + int maxHeight = mItemView->getSize().height - 48; + int index = 0; for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) @@ -133,21 +134,21 @@ void ContainerBase::drawItems() index++; if(iter->getRefData().getCount() > 0) { - count++; std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(x, y, 18, 18), MyGUI::Align::Default, std::string("Label")); + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(14, 14, 18, 18), MyGUI::Align::Default, std::string("Label")); + text->setTextAlign(MyGUI::Align::Right); + text->setNeedMouseFocus(false); image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); image->setUserString("ToolTipType", "ItemPtr"); image->setUserData(*iter); image->mPos = index; - x += 36; - if(count % 20 == 0) - { y += 36; - x = 4; - count = 0; + if (y > maxHeight) + { + x += 36; + y = 4; } if(iter->getRefData().getCount() > 1) @@ -158,7 +159,11 @@ void ContainerBase::drawItems() path.append(".dds"); image->setImageTexture(path); } - } + } + + MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x), 2048); + mItemView->setCanvasSize(size); + mContainerWidget->setSize(size); } void ContainerBase::Update() @@ -204,6 +209,7 @@ ContainerWindow::~ContainerWindow() void ContainerWindow::onWindowResize(MyGUI::Window* window) { + drawItems(); } void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 416be5367..b85380968 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -24,6 +24,7 @@ namespace MWGui InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : ContainerBase(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") { + static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); } void InventoryWindow::openInventory() @@ -31,4 +32,9 @@ namespace MWGui open(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); } + void InventoryWindow::onWindowResize(MyGUI::Window* _sender) + { + drawItems(); + } + } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 152f8b0d0..813fc88ab 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -27,6 +27,9 @@ namespace MWGui InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); void openInventory(); + + protected: + void onWindowResize(MyGUI::Window* _sender); }; } #endif // Inventory_H diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 9679519d4..26fe0a3d3 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -4,10 +4,10 @@ - - + + - + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index 40d89f221..a347a510e 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -15,7 +15,7 @@ - + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 89cc73123..213e8470f 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -131,6 +131,7 @@ + @@ -143,7 +144,7 @@ - + diff --git a/files/mygui/openmw_scroll_skin.xml b/files/mygui/openmw_scroll_skin.xml index 64e467661..70fad3f4b 100644 --- a/files/mygui/openmw_scroll_skin.xml +++ b/files/mygui/openmw_scroll_skin.xml @@ -7,4 +7,9 @@ + + + + + From e714b77df8a5ea34b1b8295688ebe6350832fc2d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 18:28:14 +0200 Subject: [PATCH 039/289] small fix --- apps/openmw/mwgui/container.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index d79693114..ba9a3213d 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -161,7 +161,7 @@ void ContainerBase::drawItems() } } - MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x), 2048); + MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x), mItemView->getSize().height); mItemView->setCanvasSize(size); mContainerWidget->setSize(size); } From 19e8e84f9ac4224c785a68799c645f7cad276464 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 18:50:19 +0200 Subject: [PATCH 040/289] more cleanup, removed the redundant ItemWidget and use widget userdata --- apps/openmw/mwgui/container.cpp | 68 ++++++++++++---------------- apps/openmw/mwgui/itemwidget.hpp | 17 ------- apps/openmw/mwgui/window_manager.cpp | 2 - 3 files changed, 30 insertions(+), 57 deletions(-) delete mode 100644 apps/openmw/mwgui/itemwidget.hpp diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index ba9a3213d..1f6a6f2f6 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -2,7 +2,6 @@ #include "window_manager.hpp" #include "widgets.hpp" -#include "itemwidget.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" @@ -50,22 +49,9 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) _sender->detachFromWidget(); _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); - ItemWidget* item = static_cast(_sender); - - int count = 0; - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - MWWorld::Ptr object; - for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) - { - count++; - if(count == item->mPos) - { - mDragAndDrop->mStore.add(*iter); - object = *iter; - iter->getRefData().setCount(0); - break; - } - } + MWWorld::Ptr object = *_sender->getUserData(); + mDragAndDrop->mStore.add(object); + object.getRefData().setCount(0); std::string sound = MWWorld::Class::get(object).getUpSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); @@ -81,9 +67,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { - ItemWidget* item = static_cast(mDragAndDrop->mDraggedWidget); - - MWWorld::Ptr object = *item->getUserData(); + MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); assert(object.getContainerStore() && "Item is not in a container!"); std::string sound = MWWorld::Class::get(object).getDownSoundId(object); @@ -123,8 +107,8 @@ void ContainerBase::drawItems() } MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - int x = 4; - int y = 4; + int x = 0; + int y = 0; int maxHeight = mItemView->getSize().height - 48; int index = 0; @@ -136,28 +120,36 @@ void ContainerBase::drawItems() { std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); - ItemWidget* image = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(x, y, 32, 32), MyGUI::Align::Default); - MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(14, 14, 18, 18), MyGUI::Align::Default, std::string("Label")); - text->setTextAlign(MyGUI::Align::Right); - text->setNeedMouseFocus(false); - image->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); - image->setUserString("ToolTipType", "ItemPtr"); - image->setUserData(*iter); - image->mPos = index; - y += 36; - if (y > maxHeight) - { - x += 36; - y = 4; - } - if(iter->getRefData().getCount() > 1) - text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + // background widget (for the "equipped" frame and magic item background image) + bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""); + MyGUI::Widget* backgroundWidget = mContainerWidget->createWidget(isMagic ? "ItemBackgroundMagic" : "ItemBackground", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); + backgroundWidget->setUserString("ToolTipType", "ItemPtr"); + backgroundWidget->setUserData(*iter); + backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); + // image + ImageBox* image = backgroundWidget->createWidget("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("SandBrightText", MyGUI::IntCoord(14, 14, 18, 18), MyGUI::Align::Default, std::string("Label")); + text->setTextAlign(MyGUI::Align::Right); + text->setNeedMouseFocus(false); + + y += 36; + if (y > maxHeight) + { + x += 36; + y = 0; + } + + if(iter->getRefData().getCount() > 1) + text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); } } diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp deleted file mode 100644 index 0b204b10e..000000000 --- a/apps/openmw/mwgui/itemwidget.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MWGUI_ITEM_WIDGET_H -#define MWGUI_ITEM_WIDGET_H -#include -#include "../mwworld/ptr.hpp" - -namespace MWGui -{ - class ItemWidget: public MyGUI::ImageBox - { - MYGUI_RTTI_DERIVED( ItemWidget ) - public: - - int mPos; - }; -} - -#endif diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 95fe3492a..6dfdc3bb4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -9,7 +9,6 @@ #include "messagebox.hpp" #include "container.hpp" #include "inventorywindow.hpp" -#include "itemwidget.hpp" #include "tooltips.hpp" #include "scrollwindow.hpp" #include "bookwindow.hpp" @@ -77,7 +76,6 @@ WindowManager::WindowManager( //Register own widgets with MyGUI MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); From 54c23c74224e273dbbe576fd72cbb571e944e4c0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 19:48:01 +0200 Subject: [PATCH 041/289] show the background texture for enchanted items in inventory/container --- apps/openmw/mwgui/container.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 1f6a6f2f6..e2be9147c 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -59,6 +59,8 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) _sender->setUserString("drag","on"); mDragAndDrop->mDraggedWidget = _sender; mDragAndDrop->mContainerWindow = const_cast(this); + // hide the count text + _sender->getChildAt(0)->getChildAt(0)->setVisible(false); drawItems(); } } @@ -123,9 +125,11 @@ void ContainerBase::drawItems() // background widget (for the "equipped" frame and magic item background image) bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""); - MyGUI::Widget* backgroundWidget = mContainerWidget->createWidget(isMagic ? "ItemBackgroundMagic" : "ItemBackground", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); + 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" : ""); + backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); // image @@ -137,7 +141,7 @@ void ContainerBase::drawItems() image->setNeedMouseFocus(false); // text widget that shows item count - MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(14, 14, 18, 18), MyGUI::Align::Default, std::string("Label")); + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); text->setTextAlign(MyGUI::Align::Right); text->setNeedMouseFocus(false); From f3c88adc0b6f8ff8cb86d49ec6d5ee50cdcd365c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 20:06:44 +0200 Subject: [PATCH 042/289] items can now also be dropped on another item (and will be placed in container) --- apps/openmw/mwgui/container.cpp | 2 ++ apps/openmw/mwgui/tooltips.cpp | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index e2be9147c..448ae6482 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -63,6 +63,8 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) _sender->getChildAt(0)->getChildAt(0)->setVisible(false); drawItems(); } + else + onContainerClicked(mContainerWidget); } void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index aa189b2e8..67479e3f9 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -29,8 +29,6 @@ ToolTips::ToolTips(WindowManager* windowManager) : void ToolTips::onFrame(float frameDuration) { - /// \todo Store a MWWorld::Ptr in the widget user data, retrieve it here and construct a tooltip dynamically - MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); mDynamicToolTipBox = mMainWidget->createWidget("HUD_Box", IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), @@ -110,6 +108,7 @@ void ToolTips::onFrame(float frameDuration) // adjust tooltip size to fit its content, position it above the crosshair /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind) + /// relevant link: http://www.ogre3d.org/tikiwiki/ObjectTextDisplay setCoord(std::max(0, viewSize.width/2 - (tooltipSize.width)/2), std::max(0, viewSize.height/2 - (tooltipSize.height) - 32), tooltipSize.width, From e6e50f4ad41a4b3bc5c1f50661953cdd71de5d98 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 20:14:19 +0200 Subject: [PATCH 043/289] fix items getting cut off --- apps/openmw/mwgui/container.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 448ae6482..84b1582cb 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -147,10 +147,10 @@ void ContainerBase::drawItems() text->setTextAlign(MyGUI::Align::Right); text->setNeedMouseFocus(false); - y += 36; + y += 42; if (y > maxHeight) { - x += 36; + x += 42; y = 0; } @@ -159,7 +159,7 @@ void ContainerBase::drawItems() } } - MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x), mItemView->getSize().height); + MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height); mItemView->setCanvasSize(size); mContainerWidget->setSize(size); } From 24e54a81bdf91a0b832d613324fcb1f9c7c5ec02 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 20:28:12 +0200 Subject: [PATCH 044/289] don't show icons in the inventory tooltips, exactly like MW does --- apps/openmw/mwgui/tooltips.cpp | 6 ++++-- apps/openmw/mwgui/tooltips.hpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 67479e3f9..7fc29f8c3 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -82,7 +82,7 @@ void ToolTips::onFrame(float frameDuration) else if (type == "ItemPtr") { mFocusObject = *focus->getUserData(); - tooltipSize = getToolTipViaPtr(); + tooltipSize = getToolTipViaPtr(false); } IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); @@ -134,7 +134,7 @@ void ToolTips::setFocusObject(const MWWorld::Ptr& focus) mFocusObject = focus; } -IntSize ToolTips::getToolTipViaPtr () +IntSize ToolTips::getToolTipViaPtr (bool image) { // this the maximum width of the tooltip before it starts word-wrapping setCoord(0, 0, 300, 300); @@ -151,6 +151,8 @@ IntSize ToolTips::getToolTipViaPtr () mDynamicToolTipBox->setVisible(true); ToolTipInfo info = object.getToolTipInfo(mFocusObject); + if (!image) + info.icon = ""; tooltipSize = createToolTip(info); } diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index d20360a79..8d0970965 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -65,7 +65,7 @@ namespace MWGui void findImageExtension(std::string& image); - MyGUI::IntSize getToolTipViaPtr (); + MyGUI::IntSize getToolTipViaPtr (bool image=true); ///< @return requested tooltip size MyGUI::IntSize createToolTip(const ToolTipInfo& info); From fd18c95c5f812ff86009b8833db23aae3385adf4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 20:35:50 +0200 Subject: [PATCH 045/289] implemented filters (no gui yet) --- apps/openmw/mwgui/container.cpp | 9 ++++++++- apps/openmw/mwgui/container.hpp | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 84b1582cb..c4407152d 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -29,6 +29,7 @@ using namespace Widgets; ContainerBase::ContainerBase(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), mDragAndDrop(dragAndDrop), + mFilter(MWWorld::ContainerStore::Type_All), mContainer() { getWidget(mContainerWidget, "Items"); @@ -95,6 +96,12 @@ void ContainerBase::setName(std::string contName) adjustWindowCaption(); } +void ContainerBase::setFilter(int filter) +{ + mFilter = filter; + drawItems(); +} + void ContainerBase::open(MWWorld::Ptr container) { mContainer = container; @@ -117,7 +124,7 @@ void ContainerBase::drawItems() int index = 0; - for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) + for (MWWorld::ContainerStoreIterator iter (containerStore.begin(mFilter)); iter!=containerStore.end(); ++iter) { index++; if(iter->getRefData().getCount() > 0) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 2552922f8..a34d22c77 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -52,6 +52,7 @@ namespace MWGui void open(MWWorld::Ptr container); void setName(std::string contName); + void setFilter(int filter); ///< set category filter void Update(); protected: @@ -61,6 +62,8 @@ namespace MWGui DragAndDrop* mDragAndDrop; MWWorld::Ptr mContainer; + int mFilter; + void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); From 8e6c9434009d390d055fe154b705c310d8c03696 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 20:39:21 +0200 Subject: [PATCH 046/289] "take all"-button sound (first item) --- apps/openmw/mwgui/container.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index c4407152d..39bd577af 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -236,11 +236,21 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) 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) { if(iter->getRefData().getCount() > 0) { playerStore.add(*iter); + + if (i==0) + { + // play the sound of the first object + std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + } + + ++i; } } From 0114bf948c8d4397a40a509f4d2d88725c9a29ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 21:28:04 +0200 Subject: [PATCH 047/289] revised filters --- apps/openmw/mwgui/container.cpp | 30 ++++++++++++++--- apps/openmw/mwgui/container.hpp | 13 ++++++-- apps/openmw/mwgui/inventorywindow.cpp | 11 +++++++ apps/openmw/mwgui/inventorywindow.hpp | 11 +++++++ .../mygui/openmw_container_window_layout.xml | 4 +-- .../mygui/openmw_inventory_window_layout.xml | 32 +++++++++++-------- 6 files changed, 80 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 39bd577af..2de8e2bb3 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -29,7 +29,7 @@ using namespace Widgets; ContainerBase::ContainerBase(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) : WindowBase(guiFile, parWindowManager), mDragAndDrop(dragAndDrop), - mFilter(MWWorld::ContainerStore::Type_All), + mFilter(ContainerBase::Filter_All), mContainer() { getWidget(mContainerWidget, "Items"); @@ -96,7 +96,7 @@ void ContainerBase::setName(std::string contName) adjustWindowCaption(); } -void ContainerBase::setFilter(int filter) +void ContainerBase::setFilter(ContainerBase::Filter filter) { mFilter = filter; drawItems(); @@ -124,10 +124,32 @@ void ContainerBase::drawItems() int index = 0; - for (MWWorld::ContainerStoreIterator iter (containerStore.begin(mFilter)); iter!=containerStore.end(); ++iter) + + bool onlyMagic = false; + int categories; + if (mFilter == Filter_All) + categories = MWWorld::ContainerStore::Type_All; + else if (mFilter == Filter_Weapon) + categories = MWWorld::ContainerStore::Type_Weapon; + else if (mFilter == Filter_Apparel) + categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor; + else 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; + } + else if (mFilter == Filter_Misc) + { + categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book + + MWWorld::ContainerStore::Type_Ingredient; + } + + for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { index++; - if(iter->getRefData().getCount() > 0) + if(iter->getRefData().getCount() > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index a34d22c77..a8c12bb6a 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -50,9 +50,18 @@ namespace MWGui ContainerBase(WindowManager& parWindowManager, DragAndDrop* dragAndDrop, std::string guiFile); virtual ~ContainerBase(); + enum Filter + { + Filter_All = 0x01, + Filter_Weapon = 0x02, + Filter_Apparel = 0x03, + Filter_Magic = 0x04, + Filter_Misc = 0x05 + }; + void open(MWWorld::Ptr container); void setName(std::string contName); - void setFilter(int filter); ///< set category filter + void setFilter(Filter filter); ///< set category filter void Update(); protected: @@ -62,7 +71,7 @@ namespace MWGui DragAndDrop* mDragAndDrop; MWWorld::Ptr mContainer; - int mFilter; + Filter mFilter; void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index b85380968..738ab578a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -25,11 +25,22 @@ namespace MWGui : ContainerBase(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); + + getWidget(mAvatar, "Avatar"); + getWidget(mEncumbranceBar, "EncumbranceBar"); + getWidget(mEncumbranceText, "EncumbranceBarT"); + getWidget(mFilterAll, "AllButton"); + getWidget(mFilterWeapon, "WeaponButton"); + getWidget(mFilterApparel, "ApparelButton"); + getWidget(mFilterMagic, "MagicButton"); + getWidget(mFilterMisc, "MiscButton"); } void InventoryWindow::openInventory() { open(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + + onWindowResize(static_cast(mMainWidget)); } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 813fc88ab..db105a2f8 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -29,6 +29,17 @@ namespace MWGui void openInventory(); protected: + MyGUI::Widget* mAvatar; + MyGUI::TextBox* mArmorRating; + MyGUI::ProgressBar* mEncumbranceBar; + MyGUI::TextBox* mEncumbranceText; + + MyGUI::Button* mFilterAll; + MyGUI::Button* mFilterWeapon; + MyGUI::Button* mFilterApparel; + MyGUI::Button* mFilterMagic; + MyGUI::Button* mFilterMisc; + void onWindowResize(MyGUI::Window* _sender); }; } diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 26fe0a3d3..7b14f5b58 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -5,9 +5,9 @@ - + - + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index a347a510e..b2b32ea2c 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -4,30 +4,36 @@ - - + + + + + + - - + + + + - - + + - + - - - - - - + + + + + + From 902309a554f96370f652ec4bb32dd141d7a60815 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 21:44:33 +0200 Subject: [PATCH 048/289] working filters --- apps/openmw/mwclass/book.cpp | 8 +++++ apps/openmw/mwclass/book.hpp | 3 ++ apps/openmw/mwgui/inventorywindow.cpp | 46 +++++++++++++++++++++++++++ apps/openmw/mwgui/inventorywindow.hpp | 1 + 4 files changed, 58 insertions(+) diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 3d8adf014..f58eac7ec 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -140,4 +140,12 @@ namespace MWClass return info; } + + std::string Book::getEnchantment (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->enchant; + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index fd6e38e04..6858bac7f 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -44,6 +44,9 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; + ///< @return the enchantment ID if the object is enchanted, otherwise an empty string }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 738ab578a..7e02a63e8 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -34,6 +34,38 @@ namespace MWGui getWidget(mFilterApparel, "ApparelButton"); getWidget(mFilterMagic, "MagicButton"); getWidget(mFilterMisc, "MiscButton"); + + mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); + mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); + mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); + mFilterMagic->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMagicTab")->str); + mFilterMisc->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMiscTab")->str); + + // adjust size of buttons to fit text + int curX = 0; + mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height ); + curX += mFilterAll->getTextSize().width + 24 + 4; + + mFilterWeapon->setPosition(curX, mFilterWeapon->getPosition().top); + mFilterWeapon->setSize( mFilterWeapon->getTextSize().width + 24, mFilterWeapon->getSize().height ); + curX += mFilterWeapon->getTextSize().width + 24 + 4; + + mFilterApparel->setPosition(curX, mFilterApparel->getPosition().top); + mFilterApparel->setSize( mFilterApparel->getTextSize().width + 24, mFilterApparel->getSize().height ); + curX += mFilterApparel->getTextSize().width + 24 + 4; + + mFilterMagic->setPosition(curX, mFilterMagic->getPosition().top); + mFilterMagic->setSize( mFilterMagic->getTextSize().width + 24, mFilterMagic->getSize().height ); + curX += mFilterMagic->getTextSize().width + 24 + 4; + + mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top); + mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height ); + + mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); + mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); + mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); + mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); + mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); } void InventoryWindow::openInventory() @@ -48,4 +80,18 @@ namespace MWGui drawItems(); } + void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender) + { + if (_sender == mFilterAll) + setFilter(ContainerBase::Filter_All); + else if (_sender == mFilterWeapon) + setFilter(ContainerBase::Filter_Weapon); + else if (_sender == mFilterApparel) + setFilter(ContainerBase::Filter_Apparel); + else if (_sender == mFilterMagic) + setFilter(ContainerBase::Filter_Magic); + else if (_sender == mFilterMisc) + setFilter(ContainerBase::Filter_Misc); + } + } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index db105a2f8..63188e84b 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -41,6 +41,7 @@ namespace MWGui MyGUI::Button* mFilterMisc; void onWindowResize(MyGUI::Window* _sender); + void onFilterChanged(MyGUI::Widget* _sender); }; } #endif // Inventory_H From 822e5fbe1e2c01cfc93079edf7bcffb88b97adab Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 22:00:15 +0200 Subject: [PATCH 049/289] add indication which filter is selected --- apps/openmw/mwgui/inventorywindow.cpp | 10 ++++++++++ files/mygui/openmw_button.skin.xml | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7e02a63e8..340c03562 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -66,6 +66,8 @@ namespace MWGui mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); + + mFilterAll->setStateSelected(true); } void InventoryWindow::openInventory() @@ -92,6 +94,14 @@ namespace MWGui setFilter(ContainerBase::Filter_Magic); else if (_sender == mFilterMisc) setFilter(ContainerBase::Filter_Misc); + + mFilterAll->setStateSelected(false); + mFilterWeapon->setStateSelected(false); + mFilterApparel->setStateSelected(false); + mFilterMagic->setStateSelected(false); + mFilterMisc->setStateSelected(false); + + static_cast(_sender)->setStateSelected(true); } } diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml index b88e99406..9efcf776f 100644 --- a/files/mygui/openmw_button.skin.xml +++ b/files/mygui/openmw_button.skin.xml @@ -62,6 +62,10 @@ + + + + From 78b06d0ebfc7e3a2ebf63d7a5fe9c9f92031b617 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 22:44:12 +0200 Subject: [PATCH 050/289] inventory window pinning --- apps/openmw/mwgui/container.cpp | 39 +++++++++++-------- apps/openmw/mwgui/container.hpp | 13 ++++--- apps/openmw/mwgui/inventorywindow.cpp | 16 +++++++- apps/openmw/mwgui/inventorywindow.hpp | 5 ++- apps/openmw/mwgui/window_manager.cpp | 10 +++++ apps/openmw/mwgui/window_manager.hpp | 2 + .../mygui/openmw_inventory_window_layout.xml | 2 +- libs/openengine/gui/layout.hpp | 7 ++++ 8 files changed, 69 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 2de8e2bb3..8742bf4f7 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -26,14 +26,16 @@ using namespace MWGui; using namespace Widgets; -ContainerBase::ContainerBase(WindowManager& parWindowManager,DragAndDrop* dragAndDrop,std::string guiFile) - : WindowBase(guiFile, parWindowManager), +ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) : mDragAndDrop(dragAndDrop), - mFilter(ContainerBase::Filter_All), - mContainer() + mFilter(ContainerBase::Filter_All) { - getWidget(mContainerWidget, "Items"); - getWidget(mItemView, "ItemView"); +} + +void ContainerBase::setWidgets(Widget* containerWidget, ScrollView* itemView) +{ + mContainerWidget = containerWidget; + mItemView = itemView; mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); } @@ -90,24 +92,16 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) } } -void ContainerBase::setName(std::string contName) -{ - setText("_Main", contName); - adjustWindowCaption(); -} - void ContainerBase::setFilter(ContainerBase::Filter filter) { mFilter = filter; drawItems(); } -void ContainerBase::open(MWWorld::Ptr container) +void ContainerBase::openContainer(MWWorld::Ptr container) { mContainer = container; - setName(MWWorld::Class::get(container).getName(container)); drawItems(); - setVisible(true); } void ContainerBase::drawItems() @@ -206,11 +200,18 @@ void ContainerBase::Update() // ------------------------------------------------------------------------------------------------ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) - : ContainerBase(parWindowManager, dragAndDrop, "openmw_container_window_layout.xml") + : ContainerBase(dragAndDrop) + , WindowBase("openmw_container_window_layout.xml", parWindowManager) { getWidget(mTakeButton, "TakeButton"); getWidget(mCloseButton, "CloseButton"); + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); @@ -239,6 +240,12 @@ void ContainerWindow::onWindowResize(MyGUI::Window* window) drawItems(); } +void ContainerWindow::open(MWWorld::Ptr container) +{ + openContainer(container); + setTitle(MWWorld::Class::get(container).getName(container)); +} + void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index a8c12bb6a..7fe04cd48 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -44,10 +44,10 @@ namespace MWGui MWWorld::Ptr mItem; }; - class ContainerBase : public WindowBase + class ContainerBase { public: - ContainerBase(WindowManager& parWindowManager, DragAndDrop* dragAndDrop, std::string guiFile); + ContainerBase(DragAndDrop* dragAndDrop); virtual ~ContainerBase(); enum Filter @@ -59,8 +59,9 @@ namespace MWGui Filter_Misc = 0x05 }; - void open(MWWorld::Ptr container); - void setName(std::string contName); + void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once + + void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter void Update(); @@ -79,13 +80,15 @@ namespace MWGui void drawItems(); }; - class ContainerWindow : public ContainerBase + class ContainerWindow : public ContainerBase, public WindowBase { public: ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); virtual ~ContainerWindow(); + void open(MWWorld::Ptr container); + protected: std::vector mContainerWidgets; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 340c03562..560e940d8 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -22,7 +22,8 @@ namespace MWGui { InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) - : ContainerBase(parWindowManager,dragAndDrop,"openmw_inventory_window_layout.xml") + : ContainerBase(dragAndDrop) + , WindowPinnableBase("openmw_inventory_window_layout.xml", parWindowManager) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); @@ -35,6 +36,12 @@ namespace MWGui getWidget(mFilterMagic, "MagicButton"); getWidget(mFilterMisc, "MiscButton"); + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); @@ -72,7 +79,7 @@ namespace MWGui void InventoryWindow::openInventory() { - open(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); onWindowResize(static_cast(mMainWidget)); } @@ -104,4 +111,9 @@ namespace MWGui static_cast(_sender)->setStateSelected(true); } + void InventoryWindow::onPinToggled() + { + mWindowManager.setWeaponVisibility(!mPinned); + } + } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 63188e84b..dd4ff90b6 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -2,6 +2,8 @@ #define MGUI_Inventory_H #include "container.hpp" +#include "window_pinnable_base.hpp" + namespace MWWorld { class Environment; @@ -21,7 +23,7 @@ namespace MWGui namespace MWGui { - class InventoryWindow : public MWGui::ContainerBase + class InventoryWindow : public ContainerBase, public WindowPinnableBase { public: InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); @@ -42,6 +44,7 @@ namespace MWGui void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); + void onPinToggled(); }; } #endif // Inventory_H diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 6dfdc3bb4..249f1fcfd 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -548,3 +548,13 @@ bool WindowManager::getFullHelp() const { return mToolTips->getFullHelp(); } + +void WindowManager::setWeaponVisibility(bool visible) +{ + hud->weapBox->setVisible(visible); +} + +void WindowManager::setSpellVisibility(bool visible) +{ + hud->spellBox->setVisible(visible); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index c3fb2b9f9..1ea4f267f 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -180,6 +180,8 @@ namespace MWGui void setHMSVisibility(bool visible); // sets the visibility of the hud minimap void setMinimapVisibility(bool visible); + void setWeaponVisibility(bool visible); + void setSpellVisibility(bool visible); template void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index b2b32ea2c..0e8abf45b 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -1,7 +1,7 @@ - + diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index bda8935af..abcc01753 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -115,6 +115,13 @@ namespace GUI static_cast(pt)->setCaption(caption); } + void setTitle(const std::string& title) + { + // NOTE: this assume that mMainWidget is of type Window. + static_cast(mMainWidget)->setCaption(title); + adjustWindowCaption(); + } + void setState(const std::string& widget, const std::string& state) { MyGUI::Widget* pt; From 16522ddc59dfe697c3b4fe73f6b91beae96222bc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 May 2012 23:09:03 +0200 Subject: [PATCH 051/289] InventoryStore re-stacking unequipped items --- apps/openmw/mwworld/containerstore.cpp | 19 ++++++++++++++----- apps/openmw/mwworld/containerstore.hpp | 3 +++ apps/openmw/mwworld/inventorystore.cpp | 20 ++++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 32e2da0ae..e28346de5 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -45,18 +45,27 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() return ContainerStoreIterator (this); } +bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const +{ + /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented + if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID + && (MWWorld::Class::get(ptr1).getScript(ptr1) == "" && MWWorld::Class::get(ptr2).getScript(ptr2) == "") // item with a script never stacks + && ptr1.mCellRef->owner == ptr2.mCellRef->owner + && ptr1.mCellRef->soul == ptr2.mCellRef->soul + && ptr1.mCellRef->charge == ptr2.mCellRef->charge) + return true; + + return false; +} + void MWWorld::ContainerStore::add (const Ptr& ptr) { int type = getType(ptr); // determine whether to stack or not - // item stacking depends on owner, script, enchantment and name for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if ( iter->mCellRef->refID == ptr.mCellRef->refID - && MWWorld::Class::get(*iter).getScript(*iter) == MWWorld::Class::get(ptr).getScript(ptr) - && MWWorld::Class::get(*iter).getEnchantment(*iter) == MWWorld::Class::get(ptr).getEnchantment(ptr) - && iter->mCellRef->owner == ptr.mCellRef->owner) + if (stacks(*iter, ptr)) { // stack iter->getRefData().setCount( iter->getRefData().getCount() + ptr.getRefData().getCount() ); diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index da5424fe0..2d330f6ea 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -66,6 +66,9 @@ namespace MWWorld ContainerStoreIterator end(); + bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; + ///< @return true if the two specified objects can stack with each other + void add (const Ptr& ptr); ///< Add the item pointed to by \a ptr to this container. /// diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 576f2371f..f149513df 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -67,9 +67,25 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite throw std::runtime_error ("invalid slot"); } - /// \todo restack item previously in this slot (if required) + // restack item previously in this slot (if required) + if (mSlots[slot] != end()) + { + for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter) + { + if (stacks(*iter, *mSlots[slot])) + { + iter->getRefData().setCount( iter->getRefData().getCount() + mSlots[slot]->getRefData().getCount() ); + mSlots[slot]->getRefData().setCount(0); + break; + } + } + } - /// \todo unstack item pointed to by iterator if required) + // unstack item pointed to by iterator if required + if (iterator->getRefData().getCount() > 1) + { + /// \ŧodo ??? + } mSlots[slot] = iterator; From f31853d30bfca002dec038169f60d3f89eaa89a1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 01:27:17 +0200 Subject: [PATCH 052/289] mouse wheel works when mouse is over an item --- apps/openmw/mwgui/container.cpp | 12 +++++++++++- apps/openmw/mwgui/container.hpp | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8742bf4f7..fd83bddfc 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -38,6 +38,7 @@ void ContainerBase::setWidgets(Widget* containerWidget, ScrollView* itemView) mItemView = itemView; mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); + mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel); } ContainerBase::~ContainerBase() @@ -92,6 +93,14 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) } } +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(ContainerBase::Filter filter) { mFilter = filter; @@ -155,7 +164,8 @@ void ContainerBase::drawItems() backgroundWidget->setUserData(*iter); backgroundWidget->setImageTexture( isMagic ? "textures\\menu_icon_magic.dds" : ""); backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); - backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this,&ContainerBase::onSelectedItem); + backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem); + backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel); // image ImageBox* image = backgroundWidget->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 7fe04cd48..6bfee1346 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -76,6 +76,7 @@ namespace MWGui void onSelectedItem(MyGUI::Widget* _sender); void onContainerClicked(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); void drawItems(); }; From d266b4fe87a5a7377d5846076562339b18415539 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 10:18:17 +0200 Subject: [PATCH 053/289] hide the cursor during drag&drop and don't allow hotkeys that change guimode --- apps/openmw/mwgui/container.cpp | 11 +++++++++-- apps/openmw/mwgui/window_manager.cpp | 5 +++++ apps/openmw/mwgui/window_manager.hpp | 2 ++ apps/openmw/mwinput/inputmanager.cpp | 21 ++++++++++++++++++++- apps/openmw/mwinput/inputmanager.hpp | 2 ++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index fd83bddfc..0236e17c2 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -60,12 +60,14 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) std::string sound = MWWorld::Class::get(object).getUpSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - _sender->setUserString("drag","on"); mDragAndDrop->mDraggedWidget = _sender; mDragAndDrop->mContainerWindow = const_cast(this); // hide the count text _sender->getChildAt(0)->getChildAt(0)->setVisible(false); drawItems(); + + MWBase::Environment::get().getInputManager()->setDragDrop(true); + MWBase::Environment::get().getWindowManager()->setMouseVisible(false); } else onContainerClicked(mContainerWidget); @@ -90,6 +92,9 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) mDragAndDrop->mDraggedWidget = 0; mDragAndDrop->mContainerWindow = 0; drawItems(); + + MWBase::Environment::get().getInputManager()->setDragDrop(false); + MWBase::Environment::get().getWindowManager()->setMouseVisible(true); } } @@ -146,7 +151,9 @@ void ContainerBase::drawItems() else if (mFilter == Filter_Misc) { categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book - + MWWorld::ContainerStore::Type_Ingredient; + + MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair + + MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light + + MWWorld::ContainerStore::Type_Apparatus; } for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 249f1fcfd..067d67ca4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -558,3 +558,8 @@ void WindowManager::setSpellVisibility(bool visible) { hud->spellBox->setVisible(visible); } + +void WindowManager::setMouseVisible(bool visible) +{ + MyGUI::PointerManager::getInstance().setVisible(visible); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 1ea4f267f..b55b425a8 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -166,6 +166,8 @@ namespace MWGui void setFocusObject(const MWWorld::Ptr& focus); + void setMouseVisible(bool visible); + void toggleFogOfWar(); void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 9026cdf64..4d79eb321 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -88,6 +88,8 @@ namespace MWInput MWGui::WindowManager &windows; OMW::Engine& mEngine; + bool mDragDrop; + /* InputImpl Methods */ @@ -143,6 +145,9 @@ namespace MWInput { using namespace MWGui; + if (mDragDrop) + return; + GuiMode mode = windows.getMode(); // Toggle between game mode and inventory mode @@ -159,6 +164,9 @@ namespace MWInput { using namespace MWGui; + if (mDragDrop) + return; + GuiMode mode = windows.getMode(); // Switch to console mode no matter what mode we are currently @@ -219,7 +227,8 @@ namespace MWInput poller(input), player(_player), windows(_windows), - mEngine (engine) + mEngine (engine), + mDragDrop(false) { using namespace OEngine::Input; using namespace OEngine::Render; @@ -319,6 +328,11 @@ namespace MWInput poller.bind(A_Crouch, KC_LCONTROL); } + void setDragDrop(bool dragDrop) + { + mDragDrop = dragDrop; + } + //NOTE: Used to check for movement keys void update () { @@ -426,4 +440,9 @@ namespace MWInput { impl->update(); } + + void MWInputManager::setDragDrop(bool dragDrop) + { + impl->setDragDrop(dragDrop); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 721c77d9f..158d05f0e 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -50,6 +50,8 @@ namespace MWInput void update(); + void setDragDrop(bool dragDrop); + void setGuiMode(MWGui::GuiMode mode); }; } From 3a93df8db4d58479c5c82fa103339787d4f2743a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 11:25:35 +0200 Subject: [PATCH 054/289] dynamic inventory layout like morrowind --- apps/openmw/mwgui/container.cpp | 17 +++--- apps/openmw/mwgui/inventorywindow.cpp | 8 +++ apps/openmw/mwgui/inventorywindow.hpp | 3 + apps/openmw/mwgui/tooltips.cpp | 12 ++++ apps/openmw/mwgui/tooltips.hpp | 4 ++ apps/openmw/mwgui/window_manager.cpp | 7 +++ apps/openmw/mwgui/window_manager.hpp | 3 +- .../mygui/openmw_inventory_window_layout.xml | 57 +++++++++++-------- 8 files changed, 78 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 0236e17c2..1b165f995 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -66,8 +66,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) _sender->getChildAt(0)->getChildAt(0)->setVisible(false); drawItems(); - MWBase::Environment::get().getInputManager()->setDragDrop(true); - MWBase::Environment::get().getWindowManager()->setMouseVisible(false); + MWBase::Environment::get().getWindowManager()->setDragDrop(true); } else onContainerClicked(mContainerWidget); @@ -93,8 +92,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) mDragAndDrop->mContainerWindow = 0; drawItems(); - MWBase::Environment::get().getInputManager()->setDragDrop(false); - MWBase::Environment::get().getWindowManager()->setMouseVisible(true); + MWBase::Environment::get().getWindowManager()->setDragDrop(false); } } @@ -128,7 +126,7 @@ void ContainerBase::drawItems() int x = 0; int y = 0; - int maxHeight = mItemView->getSize().height - 48; + int maxHeight = mItemView->getSize().height - 58; int index = 0; @@ -195,7 +193,12 @@ void ContainerBase::drawItems() } if(iter->getRefData().getCount() > 1) - text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + { + if (iter->getRefData().getCount() > 9999) + text->setCaption(boost::lexical_cast(iter->getRefData().getCount()/1000.f) + "k"); + else + text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); + } } } @@ -209,7 +212,7 @@ void ContainerBase::Update() if(mDragAndDrop->mIsOnDragAndDrop) { if(mDragAndDrop->mDraggedWidget) - mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); + mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition() - MyGUI::IntPoint(21, 21)); else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. } } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 560e940d8..4bd4fe88c 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -35,6 +35,8 @@ namespace MWGui getWidget(mFilterApparel, "ApparelButton"); getWidget(mFilterMagic, "MagicButton"); getWidget(mFilterMisc, "MiscButton"); + getWidget(mLeftPane, "LeftPane"); + getWidget(mRightPane, "RightPane"); MyGUI::ScrollView* itemView; MyGUI::Widget* containerWidget; @@ -86,6 +88,12 @@ namespace MWGui void InventoryWindow::onWindowResize(MyGUI::Window* _sender) { + const float aspect = 0.5; // fixed aspect ratio for the left pane + mLeftPane->setSize( (_sender->getSize().height-44) * aspect, _sender->getSize().height-44 ); + mRightPane->setCoord( mLeftPane->getPosition().left + (_sender->getSize().height-44) * aspect + 4, + mRightPane->getPosition().top, + _sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15, + _sender->getSize().height-44 ); drawItems(); } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index dd4ff90b6..f16dcf433 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -36,6 +36,9 @@ namespace MWGui MyGUI::ProgressBar* mEncumbranceBar; MyGUI::TextBox* mEncumbranceText; + MyGUI::Widget* mLeftPane; + MyGUI::Widget* mRightPane; + MyGUI::Button* mFilterAll; MyGUI::Button* mFilterWeapon; MyGUI::Button* mFilterApparel; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 7fc29f8c3..635e9481b 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -16,6 +16,7 @@ ToolTips::ToolTips(WindowManager* windowManager) : , mGameMode(true) , mWindowManager(windowManager) , mFullHelp(false) + , mEnabled(true) { getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); @@ -27,6 +28,11 @@ ToolTips::ToolTips(WindowManager* windowManager) : mMainWidget->setNeedMouseFocus(false); } +void ToolTips::setEnabled(bool enabled) +{ + mEnabled = enabled; +} + void ToolTips::onFrame(float frameDuration) { MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); @@ -36,6 +42,12 @@ void ToolTips::onFrame(float frameDuration) const IntSize &viewSize = RenderManager::getInstance().getViewSize(); + if (!mEnabled) + { + mDynamicToolTipBox->setVisible(false); + return; + } + if (!mGameMode) { Widget* focus = InputManager::getInstance().getMouseFocusWidget(); diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 8d0970965..87b9e97bf 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -39,6 +39,8 @@ namespace MWGui void enterGameMode(); void enterGuiMode(); + void setEnabled(bool enabled); + void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; @@ -73,6 +75,8 @@ namespace MWGui bool mGameMode; + bool mEnabled; + bool mFullHelp; }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 067d67ca4..47fae2003 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -563,3 +563,10 @@ void WindowManager::setMouseVisible(bool visible) { MyGUI::PointerManager::getInstance().setVisible(visible); } + +void WindowManager::setDragDrop(bool dragDrop) +{ + mToolTips->setEnabled(!dragDrop); + MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); + setMouseVisible(!dragDrop); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index b55b425a8..5dfcf6470 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -166,7 +166,8 @@ namespace MWGui void setFocusObject(const MWWorld::Ptr& focus); - void setMouseVisible(bool visible); + void setMouseVisible(bool visible); + void setDragDrop(bool dragDrop); void toggleFogOfWar(); void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index 0e8abf45b..cd6e1469e 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -3,37 +3,44 @@ - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + - - - - - + + + + + + + + + + + + + + - - - - - - - - From ee7e482cba639a8c34b3b94e4433827032725a80 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 11:52:17 +0200 Subject: [PATCH 055/289] implemented un-stacking --- apps/openmw/mwworld/containerstore.cpp | 8 +++++++- apps/openmw/mwworld/containerstore.hpp | 8 +++++++- apps/openmw/mwworld/inventorystore.cpp | 19 +++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index e28346de5..94df222d4 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -75,7 +75,13 @@ void MWWorld::ContainerStore::add (const Ptr& ptr) } } - switch (type) + // if we got here, this means no stacking + addImpl(ptr); +} + +void MWWorld::ContainerStore::addImpl (const Ptr& ptr) +{ + switch (getType(ptr)) { case Type_Potion: potions.list.push_back (*ptr.get()); break; case Type_Apparatus: appas.list.push_back (*ptr.get()); break; diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 2d330f6ea..9b9d29c57 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -70,13 +70,19 @@ namespace MWWorld ///< @return true if the two specified objects can stack with each other void add (const Ptr& ptr); - ///< Add the item pointed to by \a ptr to this container. + ///< 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! + protected: + void addImpl (const Ptr& ptr); + ///< Add the item to this container (no stacking) + + public: + void fill (const ESM::InventoryList& items, const ESMS::ESMStore& store); ///< Insert items into *this. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index f149513df..ea295e903 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -84,7 +84,11 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite // unstack item pointed to by iterator if required if (iterator->getRefData().getCount() > 1) { - /// \ŧodo ??? + // add the item again with a count of count-1, then set the count of the original (that will be equipped) to 1 + int count = iterator->getRefData().getCount(); + iterator->getRefData().setCount(count-1); + addImpl(*iterator); + iterator->getRefData().setCount(1); } mSlots[slot] = iterator; @@ -163,7 +167,18 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) } } - /// \todo unstack, if reqquired (itemsSlots.second) + if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped + { + // unstack item pointed to by iterator if required + if (iter->getRefData().getCount() > 1) + { + // add the item again with a count of count-1, then set the count of the original (that will be equipped) to 1 + int count = iter->getRefData().getCount(); + iter->getRefData().setCount(count-1); + addImpl(*iter); + iter->getRefData().setCount(1); + } + } slots[*iter2] = iter; break; From a54e52586b5d3a213ad8a1fa25de05eb3a3a64c5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 12:17:07 +0200 Subject: [PATCH 056/289] fix for a potential directx problem --- files/shadows/depthshadowcaster.material | 92 +++++++++++++----------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/files/shadows/depthshadowcaster.material b/files/shadows/depthshadowcaster.material index 9ff51c5b1..f645cad01 100644 --- a/files/shadows/depthshadowcaster.material +++ b/files/shadows/depthshadowcaster.material @@ -1,67 +1,73 @@ vertex_program depth_shadow_caster_vs cg { - source depthshadowcaster.cg - profiles vs_1_1 arbvp1 - entry_point main_vp + source depthshadowcaster.cg + profiles vs_1_1 arbvp1 + entry_point main_vp - default_params - { - param_named_auto wvpMat worldviewproj_matrix - } + default_params + { + param_named_auto wvpMat worldviewproj_matrix + } } fragment_program depth_shadow_caster_ps cg { - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp + source depthshadowcaster.cg + profiles ps_2_0 arbfp1 + entry_point main_fp - default_params - { - } + default_params + { + } } fragment_program depth_shadow_caster_ps_noalpha cg { - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp_noalpha + source depthshadowcaster.cg + profiles ps_2_0 arbfp1 + entry_point main_fp_noalpha - default_params - { - } + default_params + { + } } material depth_shadow_caster { - technique - { - pass - { - vertex_program_ref depth_shadow_caster_vs - { - } + technique + { + pass + { + // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) + fog_override true - fragment_program_ref depth_shadow_caster_ps - { - } - } - } + vertex_program_ref depth_shadow_caster_vs + { + } + + fragment_program_ref depth_shadow_caster_ps + { + } + } + } } material depth_shadow_caster_noalpha { - technique - { - pass - { - vertex_program_ref depth_shadow_caster_vs - { - } + technique + { + pass + { + // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) + fog_override true - fragment_program_ref depth_shadow_caster_ps_noalpha - { - } - } - } + vertex_program_ref depth_shadow_caster_vs + { + } + + fragment_program_ref depth_shadow_caster_ps_noalpha + { + } + } + } } From ddb0a9199408c68fbf9c378b80e8f1fae6246004 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 12:19:49 +0200 Subject: [PATCH 057/289] addition to last commit --- components/nifogre/ogre_nif_loader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 05d35b85f..80b2fc469 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -326,6 +326,8 @@ void NIFLoader::createMaterial(const String &name, { material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp"); material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp"); + + material->getTechnique(0)->getPass(0)->setFog(true); // force-disable fixed function fog, it is calculated in shader } // Create a fallback technique without shadows and without mrt @@ -338,6 +340,7 @@ void NIFLoader::createMaterial(const String &name, { pass2->setVertexProgram("main_fallback_vp"); pass2->setFragmentProgram("main_fallback_fp"); + pass2->setFog(true); // force-disable fixed function fog, it is calculated in shader } // Add material bells and whistles From d341d2113c8585093781f3c6975b3d7c3b1fabd4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 14:58:38 +0200 Subject: [PATCH 058/289] fixed some issues --- apps/openmw/mwworld/containerstore.cpp | 2 +- apps/openmw/mwworld/containerstore.hpp | 7 ++++--- apps/openmw/mwworld/inventorystore.cpp | 22 ++++++++++++++++++++-- apps/openmw/mwworld/inventorystore.hpp | 7 +++++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 94df222d4..dcddc333b 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -49,7 +49,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const { /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID - && (MWWorld::Class::get(ptr1).getScript(ptr1) == "" && MWWorld::Class::get(ptr2).getScript(ptr2) == "") // item with a script never stacks + && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks && ptr1.mCellRef->owner == ptr2.mCellRef->owner && ptr1.mCellRef->soul == ptr2.mCellRef->soul && ptr1.mCellRef->charge == ptr2.mCellRef->charge) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 9b9d29c57..f0e9d7e4a 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -66,9 +66,6 @@ namespace MWWorld ContainerStoreIterator end(); - bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; - ///< @return true if the two specified objects can stack with each other - void add (const Ptr& ptr); ///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed) /// @@ -81,6 +78,10 @@ namespace MWWorld void addImpl (const Ptr& ptr); ///< Add the item to this container (no stacking) + virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; + ///< @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 ESMS::ESMStore& store); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index ea295e903..6cf35ac64 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -59,9 +59,10 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite if (iterator.getContainerStore()!=this) throw std::runtime_error ("attempt to equip an item that is not in the inventory"); + std::pair, bool> slots; if (iterator!=end()) { - std::pair, bool> slots = Class::get (*iterator).getEquipmentSlots (*iterator); + slots = Class::get (*iterator).getEquipmentSlots (*iterator); if (std::find (slots.first.begin(), slots.first.end(), slot)==slots.first.end()) throw std::runtime_error ("invalid slot"); @@ -82,7 +83,7 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite } // unstack item pointed to by iterator if required - if (iterator->getRefData().getCount() > 1) + if (iterator!=end() && !slots.second && iterator->getRefData().getCount() > 1) // if slots.second is true, item can stay stacked when equipped { // add the item again with a count of count-1, then set the count of the original (that will be equipped) to 1 int count = iterator->getRefData().getCount(); @@ -199,3 +200,20 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) flagAsModified(); } } + +bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const +{ + bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2); + if (!canStack) + return false; + + // don't stack if the item being checked against is currently equipped. + for (TSlots::const_iterator iter (mSlots.begin()); + iter!=mSlots.end(); ++iter) + { + if (ptr1 == **iter) + return false; + } + + return true; +} diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 5eeaf570d..4162c7e2e 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -64,6 +64,13 @@ namespace MWWorld void autoEquip (const MWMechanics::NpcStats& stats); ///< Auto equip items according to stats and item value. + + protected: + + virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; + ///< @return true if the two specified objects can stack with each other + /// @note ptr1 is the item that is already in this container + }; } From a47d29c184f335f86f9c3972c8bbc253cad91944 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 16:41:00 +0200 Subject: [PATCH 059/289] fix the inventory window overlapping with over windows in default layout --- apps/openmw/mwgui/container.cpp | 5 +++-- apps/openmw/mwgui/inventorywindow.cpp | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 1b165f995..de7419b80 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -245,10 +245,11 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dr mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height); int w = MyGUI::RenderManager::getInstance().getViewSize().width; - int h = MyGUI::RenderManager::getInstance().getViewSize().height; - setCoord(w-600,h-300,600,300); + //int h = MyGUI::RenderManager::getInstance().getViewSize().height; static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize); + + setCoord(w-600,0,600,300); } ContainerWindow::~ContainerWindow() diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4bd4fe88c..23e4949f7 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -77,6 +77,8 @@ namespace MWGui mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterAll->setStateSelected(true); + + setCoord(0, 342, 600, 258); } void InventoryWindow::openInventory() From 82b9f835b1a907f72acec44a325cb1d5a74bf85e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 16:54:18 +0200 Subject: [PATCH 060/289] make sure iterator is not end() before trying to get the equipped item --- apps/openmw/mwworld/containerstore.cpp | 2 +- apps/openmw/mwworld/containerstore.hpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 4 ++-- apps/openmw/mwworld/inventorystore.hpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index dcddc333b..ee1b620cd 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -45,7 +45,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() return ContainerStoreIterator (this); } -bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const +bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index f0e9d7e4a..3cb3f3bdc 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -78,7 +78,7 @@ namespace MWWorld void addImpl (const Ptr& ptr); ///< Add the item to this container (no stacking) - virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; + 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 diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 6cf35ac64..3e535793c 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -201,7 +201,7 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) } } -bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const +bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2); if (!canStack) @@ -211,7 +211,7 @@ bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const for (TSlots::const_iterator iter (mSlots.begin()); iter!=mSlots.end(); ++iter) { - if (ptr1 == **iter) + if (*iter != end() && ptr1 == **iter) return false; } diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 4162c7e2e..05fc651ee 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -67,7 +67,7 @@ namespace MWWorld protected: - virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const; + 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 From 967fb13fca9d0e4c9265c9840643b0070e7d80ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 18:14:03 +0200 Subject: [PATCH 061/289] remove the old inventory code, split HUD, map and mainmenu into seperate implementation files --- apps/openmw/CMakeLists.txt | 4 +- apps/openmw/mwgui/{layouts.cpp => hud.cpp} | 97 +-------- apps/openmw/mwgui/hud.hpp | 50 +++++ apps/openmw/mwgui/layouts.hpp | 236 --------------------- apps/openmw/mwgui/mainmenu.hpp | 16 ++ apps/openmw/mwgui/map_window.cpp | 94 +++++++- apps/openmw/mwgui/map_window.hpp | 30 ++- apps/openmw/mwgui/window_manager.cpp | 3 +- 8 files changed, 190 insertions(+), 340 deletions(-) rename apps/openmw/mwgui/{layouts.cpp => hud.cpp} (72%) create mode 100644 apps/openmw/mwgui/hud.hpp delete mode 100644 apps/openmw/mwgui/layouts.hpp create mode 100644 apps/openmw/mwgui/mainmenu.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index be99cefdd..5ecb2eea8 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -23,10 +23,10 @@ add_openmw_dir (mwinput ) add_openmw_dir (mwgui - layouts text_input widgets race class birth review window_manager console dialogue + text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list - formatting itemwidget inventorywindow container + formatting itemwidget inventorywindow container hud ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/layouts.cpp b/apps/openmw/mwgui/hud.cpp similarity index 72% rename from apps/openmw/mwgui/layouts.cpp rename to apps/openmw/mwgui/hud.cpp index 21302d7c1..ffee9f6c7 100644 --- a/apps/openmw/mwgui/layouts.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -1,18 +1,14 @@ -#include "layouts.hpp" - -#include "../mwmechanics/mechanicsmanager.hpp" -#include "window_manager.hpp" +#include "hud.hpp" #include -#include -#include -#undef min -#undef max +#include + +#include + using namespace MWGui; - HUD::HUD(int width, int height, int fpsLevel) : Layout("openmw_hud_layout.xml") , health(NULL) @@ -247,86 +243,3 @@ void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible effectBox->setVisible(effectBoxVisible); } -LocalMapBase::LocalMapBase() - : mCurX(0) - , mCurY(0) - , mInterior(false) - , mFogOfWar(true) - , mLocalMap(NULL) - , mPrefix() - , mChanged(true) - , mLayout(NULL) - , mLastPositionX(0.0f) - , mLastPositionY(0.0f) - , mLastDirectionX(0.0f) - , mLastDirectionY(0.0f) -{ -} - -void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) -{ - mLocalMap = widget; - mLayout = layout; -} - -void LocalMapBase::setCellPrefix(const std::string& prefix) -{ - mPrefix = prefix; - mChanged = true; -} - -void LocalMapBase::toggleFogOfWar() -{ - mFogOfWar = !mFogOfWar; - applyFogOfWar(); -} - -void LocalMapBase::applyFogOfWar() -{ - for (int mx=0; mx<3; ++mx) - { - for (int my=0; my<3; ++my) - { - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" - + boost::lexical_cast(mCurY + (mInterior ? (my-1) : -1*(my-1))); - MyGUI::ImageBox* fog; - mLayout->getWidget(fog, name+"_fog"); - fog->setImageTexture(mFogOfWar ? - ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" - : "black.png" ) - : ""); - } - } -} - -void LocalMapBase::setActiveCell(const int x, const int y, bool interior) -{ - if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell - for (int mx=0; mx<3; ++mx) - { - for (int my=0; my<3; ++my) - { - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - - std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" - + boost::lexical_cast(y + (interior ? (my-1) : -1*(my-1))); - - MyGUI::ImageBox* box; - mLayout->getWidget(box, name); - - if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) - box->setImageTexture(image); - else - box->setImageTexture("black.png"); - } - } - mInterior = interior; - mCurX = x; - mCurY = y; - mChanged = false; - applyFogOfWar(); -} - diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp new file mode 100644 index 000000000..831707511 --- /dev/null +++ b/apps/openmw/mwgui/hud.hpp @@ -0,0 +1,50 @@ +#include "map_window.hpp" + +#include + +#include "../mwmechanics/stat.hpp" + +namespace MWGui +{ + class HUD : public OEngine::GUI::Layout, public LocalMapBase + { + public: + HUD(int width, int height, int fpsLevel); + void setStats(int h, int hmax, int m, int mmax, int s, int smax); + void setWeapIcon(const char *str); + void setSpellIcon(const char *str); + void setWeapStatus(int s, int smax); + void setSpellStatus(int s, int smax); + void setEffect(const char *img); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setFPS(float fps); + void setTriangleCount(size_t count); + void setBatchCount(size_t count); + void setPlayerDir(const float x, const float y); + void setPlayerPos(const float x, const float y); + void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); + void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); + void setFpsLevel(const int level); + + MyGUI::ProgressPtr health, magicka, stamina; + MyGUI::Widget *weapBox, *spellBox; + MyGUI::ImageBox *weapImage, *spellImage; + MyGUI::ProgressPtr weapStatus, spellStatus; + MyGUI::Widget *effectBox, *minimapBox; + MyGUI::ImageBox* effect1; + MyGUI::ScrollView* minimap; + MyGUI::ImageBox* compass; + MyGUI::ImageBox* crosshair; + + MyGUI::WidgetPtr fpsbox; + MyGUI::TextBox* fpscounter; + MyGUI::TextBox* trianglecounter; + MyGUI::TextBox* batchcounter; + + private: + // bottom left elements + int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft; + // bottom right elements + int minimapBoxBaseRight, effectBoxBaseRight; + }; +} diff --git a/apps/openmw/mwgui/layouts.hpp b/apps/openmw/mwgui/layouts.hpp deleted file mode 100644 index 19d96d2ef..000000000 --- a/apps/openmw/mwgui/layouts.hpp +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef MWGUI_LAYOUTS_H -#define MWGUI_LAYOUTS_H - -#include - -#include -#include - -#include -#include -#include -#include - -#include "../mwmechanics/stat.hpp" -#include "window_base.hpp" - -#include - -/* - This file contains classes corresponding to window layouts - defined in resources/mygui/ *.xml. - - Each class inherites GUI::Layout and loads the XML file, and - provides some helper functions to manipulate the elements of the - window. - - The windows are never created or destroyed (except at startup and - shutdown), they are only hid. You can control visibility with - setVisible(). - */ - -namespace MWGui -{ - class LocalMapBase - { - public: - LocalMapBase(); - void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); - - void setCellPrefix(const std::string& prefix); - void setActiveCell(const int x, const int y, bool interior=false); - - void toggleFogOfWar(); - - protected: - int mCurX, mCurY; - bool mInterior; - MyGUI::ScrollView* mLocalMap; - std::string mPrefix; - bool mChanged; - bool mFogOfWar; - - void applyFogOfWar(); - - OEngine::GUI::Layout* mLayout; - - float mLastPositionX; - float mLastPositionY; - float mLastDirectionX; - float mLastDirectionY; - }; - - class HUD : public OEngine::GUI::Layout, public LocalMapBase - { - public: - HUD(int width, int height, int fpsLevel); - void setStats(int h, int hmax, int m, int mmax, int s, int smax); - void setWeapIcon(const char *str); - void setSpellIcon(const char *str); - void setWeapStatus(int s, int smax); - void setSpellStatus(int s, int smax); - void setEffect(const char *img); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setFPS(float fps); - void setTriangleCount(size_t count); - void setBatchCount(size_t count); - void setPlayerDir(const float x, const float y); - void setPlayerPos(const float x, const float y); - void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); - void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); - void setFpsLevel(const int level); - - MyGUI::ProgressPtr health, magicka, stamina; - MyGUI::Widget *weapBox, *spellBox; - MyGUI::ImageBox *weapImage, *spellImage; - MyGUI::ProgressPtr weapStatus, spellStatus; - MyGUI::Widget *effectBox, *minimapBox; - MyGUI::ImageBox* effect1; - MyGUI::ScrollView* minimap; - MyGUI::ImageBox* compass; - MyGUI::ImageBox* crosshair; - - MyGUI::WidgetPtr fpsbox; - MyGUI::TextBox* fpscounter; - MyGUI::TextBox* trianglecounter; - MyGUI::TextBox* batchcounter; - - private: - // bottom left elements - int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft; - // bottom right elements - int minimapBoxBaseRight, effectBoxBaseRight; - }; - - class MainMenu : public OEngine::GUI::Layout - { - public: - MainMenu(int w, int h) - : Layout("openmw_mainmenu_layout.xml") - { - setCoord(0,0,w,h); - } - }; - -#if 0 - class InventoryWindow : public OEngine::GUI::Layout - { - public: - enum CategoryMode - { - CM_All = 0, // All items - CM_Weapon = 1, // Only weapons - CM_Apparel = 2, // Apparel - CM_Magic = 3, // Magic - CM_Misc = 4 // Misc - }; - - InventoryWindow () - : Layout("openmw_inventory_window_layout.xml") - , categoryMode(CM_All) - - // color should be fetched from skin - , activeColor(0, 0, 1) - , inactiveColor(0.7, 0.7, 0.7) - { - setCoord(0, 200, 600, 400); - - // These are just demo values, you should replace these with - // real calls from outside the class later. - - mMainWidget->setCaption("Glass Frostsword"); - setText("EncumbranceBarT", "176/210"); - - MyGUI::ProgressPtr pt; - getWidget(pt, "EncumbranceBar"); - pt->setProgressRange(210); - pt->setProgressPosition(176); - - MyGUI::WidgetPtr avatar; - getWidget(avatar, "Avatar"); - - // Adjust armor rating text to bottom of avatar widget - MyGUI::TextBox* armor_rating; - getWidget(armor_rating, "ArmorRating"); - armor_rating->setCaption("Armor: 11"); - MyGUI::IntCoord coord = armor_rating->getCoord(); - coord.top = avatar->getCoord().height - 4 - coord.height; - armor_rating->setCoord(coord); - - names[0] = "All"; - names[1] = "Weapon"; - names[2] = "Apparel"; - names[3] = "Magic"; - names[4] = "Misc"; - - boost::array categories = { { - CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc - } }; - - // Initialize buttons with text and adjust sizes, also mark All as active button - int margin = 2; - int last_x = 0; - for (int i = 0; i < categories.size(); ++i) - { - CategoryMode mode = categories[i]; - std::string name = names[mode]; - name += "Button"; - setText(name, names[mode]); - getWidget(buttons[mode], name); - - MyGUI::ButtonPtr &button_pt = buttons[mode]; - if (mode == CM_All) - button_pt->setTextColour(activeColor); - else - button_pt->setTextColour(inactiveColor); - MyGUI::IntCoord coord = button_pt->getCoord(); - coord.left = last_x; - last_x += coord.width + margin; - button_pt->setCoord(coord); - - button_pt->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onCategorySelected); - } - } - - void setCategory(CategoryMode mode) - { - MyGUI::ButtonPtr pt = getCategoryButton(categoryMode); - pt->setTextColour(inactiveColor); - - pt = getCategoryButton(mode); - pt->setTextColour(activeColor); - categoryMode = mode; - } - - MyGUI::ButtonPtr getCategoryButton(CategoryMode mode) - { - return buttons[mode]; - } - - void onCategorySelected(MyGUI::Widget *widget) - { - boost::array categories = { { - CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc - } }; - - for (int i = 0; i < categories.size(); ++i) - { - CategoryMode mode = categories[i]; - if (widget == buttons[mode]) - { - setCategory(mode); - return; - } - } - } - - CategoryMode categoryMode; // Current category filter - MyGUI::ButtonPtr buttons[5]; // Button pointers - std::string names[5]; // Names of category buttons - - MyGUI::Colour activeColor; - MyGUI::Colour inactiveColor; - }; -#endif -} -#endif diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp new file mode 100644 index 000000000..b32f2d900 --- /dev/null +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -0,0 +1,16 @@ +#include + +namespace MWGui +{ + + class MainMenu : public OEngine::GUI::Layout + { + public: + MainMenu(int w, int h) + : Layout("openmw_mainmenu_layout.xml") + { + setCoord(0,0,w,h); + } + }; + +} diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index e0c828fdc..d3541f774 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -1,17 +1,95 @@ #include "map_window.hpp" #include "window_manager.hpp" -/* -#include "../mwmechanics/mechanicsmanager.hpp" -#include -#include -#include +#include -#undef min -#undef max -*/ using namespace MWGui; +LocalMapBase::LocalMapBase() + : mCurX(0) + , mCurY(0) + , mInterior(false) + , mFogOfWar(true) + , mLocalMap(NULL) + , mPrefix() + , mChanged(true) + , mLayout(NULL) + , mLastPositionX(0.0f) + , mLastPositionY(0.0f) + , mLastDirectionX(0.0f) + , mLastDirectionY(0.0f) +{ +} + +void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) +{ + mLocalMap = widget; + mLayout = layout; +} + +void LocalMapBase::setCellPrefix(const std::string& prefix) +{ + mPrefix = prefix; + mChanged = true; +} + +void LocalMapBase::toggleFogOfWar() +{ + mFogOfWar = !mFogOfWar; + applyFogOfWar(); +} + +void LocalMapBase::applyFogOfWar() +{ + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" + + boost::lexical_cast(mCurY + (mInterior ? (my-1) : -1*(my-1))); + MyGUI::ImageBox* fog; + mLayout->getWidget(fog, name+"_fog"); + fog->setImageTexture(mFogOfWar ? + ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" + : "black.png" ) + : ""); + } + } +} + +void LocalMapBase::setActiveCell(const int x, const int y, bool interior) +{ + if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + + std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" + + boost::lexical_cast(y + (interior ? (my-1) : -1*(my-1))); + + MyGUI::ImageBox* box; + mLayout->getWidget(box, name); + + if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) + box->setImageTexture(image); + else + box->setImageTexture("black.png"); + } + } + mInterior = interior; + mCurX = x; + mCurY = y; + mChanged = false; + applyFogOfWar(); +} + +// ------------------------------------------------------------------------------------------ + MapWindow::MapWindow(WindowManager& parWindowManager) : MWGui::WindowPinnableBase("openmw_map_window_layout.xml", parWindowManager), mGlobal(false) diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp index d14221a40..e7318f4e4 100644 --- a/apps/openmw/mwgui/map_window.hpp +++ b/apps/openmw/mwgui/map_window.hpp @@ -1,11 +1,39 @@ #ifndef MWGUI_MAPWINDOW_H #define MWGUI_MAPWINDOW_H -#include "layouts.hpp" #include "window_pinnable_base.hpp" namespace MWGui { + class LocalMapBase + { + public: + LocalMapBase(); + void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); + + void setCellPrefix(const std::string& prefix); + void setActiveCell(const int x, const int y, bool interior=false); + + void toggleFogOfWar(); + + protected: + int mCurX, mCurY; + bool mInterior; + MyGUI::ScrollView* mLocalMap; + std::string mPrefix; + bool mChanged; + bool mFogOfWar; + + void applyFogOfWar(); + + OEngine::GUI::Layout* mLayout; + + float mLastPositionX; + float mLastPositionY; + float mLastDirectionX; + float mLastDirectionY; + }; + class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase { public: diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 47fae2003..290e0029a 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -1,5 +1,4 @@ #include "window_manager.hpp" -#include "layouts.hpp" #include "text_input.hpp" #include "review.hpp" #include "dialogue.hpp" @@ -13,6 +12,8 @@ #include "scrollwindow.hpp" #include "bookwindow.hpp" #include "list.hpp" +#include "hud.hpp" +#include "mainmenu.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" From 6c9f75b322d54c0079d9ad95299b014da51b19c9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 18:35:56 +0200 Subject: [PATCH 062/289] some unfinished work for dropping objects into the gameworld --- apps/openmw/mwgui/hud.cpp | 26 +++++++++++++++++++++++++- apps/openmw/mwgui/hud.hpp | 8 +++++++- apps/openmw/mwgui/window_manager.cpp | 2 +- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index ffee9f6c7..47bf27799 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -6,10 +6,14 @@ #include +#include "../mwbase/environment.hpp" + +#include "window_manager.hpp" +#include "container.hpp" using namespace MWGui; -HUD::HUD(int width, int height, int fpsLevel) +HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) : Layout("openmw_hud_layout.xml") , health(NULL) , magicka(NULL) @@ -32,6 +36,7 @@ HUD::HUD(int width, int height, int fpsLevel) , spellBoxBaseLeft(0) , effectBoxBaseRight(0) , minimapBoxBaseRight(0) + , mDragAndDrop(dragAndDrop) { setCoord(0,0, width, height); @@ -80,6 +85,8 @@ HUD::HUD(int width, int height, int fpsLevel) setEffect("icons\\s\\tx_s_chameleon.dds"); LocalMapBase::init(minimap, this); + + mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); } void HUD::setFpsLevel(int level) @@ -243,3 +250,20 @@ void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible effectBox->setVisible(effectBoxVisible); } +void HUD::onWorldClicked(MyGUI::Widget* _sender) +{ + if (mDragAndDrop->mIsOnDragAndDrop) + { + // drop item into the gameworld + + + mDragAndDrop->mStore.clear(); + mDragAndDrop->mIsOnDragAndDrop = false; + MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); + mDragAndDrop->mDraggedWidget = 0; + mDragAndDrop->mContainerWindow = 0; + + MWBase::Environment::get().getWindowManager()->setDragDrop(false); + } +} + diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 831707511..22b1b8738 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -6,10 +6,12 @@ namespace MWGui { + class DragAndDrop; + class HUD : public OEngine::GUI::Layout, public LocalMapBase { public: - HUD(int width, int height, int fpsLevel); + HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); void setStats(int h, int hmax, int m, int mmax, int s, int smax); void setWeapIcon(const char *str); void setSpellIcon(const char *str); @@ -46,5 +48,9 @@ namespace MWGui int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft; // bottom right elements int minimapBoxBaseRight, effectBoxBaseRight; + + DragAndDrop* mDragAndDrop; + + void onWorldClicked(MyGUI::Widget* _sender); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 290e0029a..bb533e698 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -99,7 +99,6 @@ WindowManager::WindowManager( mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; mDragAndDrop->mContainerWindow = 0; - hud = new HUD(w,h, showFPSLevel); menu = new MainMenu(w,h); map = new MapWindow(*this); stats = new StatsWindow(*this); @@ -109,6 +108,7 @@ WindowManager::WindowManager( mDialogueWindow = new DialogueWindow(*this); mContainerWindow = new ContainerWindow(*this,mDragAndDrop); mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); + hud = new HUD(w,h, showFPSLevel, mDragAndDrop); mToolTips = new ToolTips(this); mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); From d3e162ec830087be3cd04a5ff51ae90192bedab8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 14 May 2012 17:41:17 +0200 Subject: [PATCH 063/289] dropping items works --- apps/openmw/mwgui/container.cpp | 2 + apps/openmw/mwgui/container.hpp | 1 - apps/openmw/mwgui/hud.cpp | 18 +++++ apps/openmw/mwworld/scene.cpp | 135 ++++++++++++++++++++------------ apps/openmw/mwworld/scene.hpp | 4 + apps/openmw/mwworld/world.cpp | 5 ++ apps/openmw/mwworld/world.hpp | 3 + 7 files changed, 119 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index de7419b80..99a4b686e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -184,6 +184,8 @@ void ContainerBase::drawItems() MyGUI::TextBox* text = image->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)); y += 42; if (y > maxHeight) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 6bfee1346..88fc55217 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -41,7 +41,6 @@ namespace MWGui MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; MWWorld::ContainerStore mStore; - MWWorld::Ptr mItem; }; class ContainerBase diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 47bf27799..80c02cd82 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -7,6 +7,10 @@ #include #include "../mwbase/environment.hpp" +#include "../mwsound/soundmanager.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" #include "window_manager.hpp" #include "container.hpp" @@ -255,7 +259,21 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if (mDragAndDrop->mIsOnDragAndDrop) { // drop item into the gameworld + MWWorld::Ptr object = *mDragAndDrop->mStore.begin(); + float* playerPos; + playerPos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition().pos; + MWWorld::Ptr::CellStore* cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); /// \todo this might be a different cell + + ESM::Position& pos = object.getRefData().getPosition(); + pos.pos[0] = playerPos[0]; + pos.pos[1] = playerPos[1]; + pos.pos[2] = playerPos[2]; + + MWBase::Environment::get().getWorld()->insertObject(object, cell); + + std::string sound = MWWorld::Class::get(object).getDownSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); mDragAndDrop->mStore.clear(); mDragAndDrop->mIsOnDragAndDrop = false; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 6f9f3ed3e..1d4f078d5 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -15,39 +15,40 @@ #include "cellfunctors.hpp" -namespace { - -template -void insertCellRefList(MWRender::RenderingManager& rendering, - T& cellRefList, ESMS::CellStore &cell, MWWorld::PhysicsSystem& physics) +namespace { - if (!cellRefList.list.empty()) + + template + void insertCellRefList(MWRender::RenderingManager& rendering, + T& cellRefList, ESMS::CellStore &cell, MWWorld::PhysicsSystem& physics) { - const MWWorld::Class& class_ = - MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); - - for (typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) + if (!cellRefList.list.empty()) { - if (it->mData.getCount() || it->mData.isEnabled()) - { - MWWorld::Ptr ptr (&*it, &cell); + const MWWorld::Class& class_ = + MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); - try + for (typename T::List::iterator it = cellRefList.list.begin(); + it != cellRefList.list.end(); it++) + { + if (it->mData.getCount() || it->mData.isEnabled()) { - rendering.addObject(ptr); - class_.insertObject(ptr, physics); - class_.enable (ptr); - } - catch (const std::exception& e) - { - std::string error ("error during rendering: "); - std::cerr << error + e.what() << std::endl; + MWWorld::Ptr ptr (&*it, &cell); + + try + { + rendering.addObject(ptr); + class_.insertObject(ptr, physics); + class_.enable (ptr); + } + catch (const std::exception& e) + { + std::string error ("error during rendering: "); + std::cerr << error + e.what() << std::endl; + } } } } } -} } @@ -300,30 +301,68 @@ namespace MWWorld mCellChanged = false; } -void Scene::insertCell(ESMS::CellStore &cell) -{ - // Loop through all references in the cell - insertCellRefList(mRendering, cell.activators, cell, *mPhysics); - insertCellRefList(mRendering, cell.potions, cell, *mPhysics); - insertCellRefList(mRendering, cell.appas, cell, *mPhysics); - insertCellRefList(mRendering, cell.armors, cell, *mPhysics); - insertCellRefList(mRendering, cell.books, cell, *mPhysics); - insertCellRefList(mRendering, cell.clothes, cell, *mPhysics); - insertCellRefList(mRendering, cell.containers, cell, *mPhysics); - insertCellRefList(mRendering, cell.creatures, cell, *mPhysics); - insertCellRefList(mRendering, cell.doors, cell, *mPhysics); - insertCellRefList(mRendering, cell.ingreds, cell, *mPhysics); - insertCellRefList(mRendering, cell.creatureLists, cell, *mPhysics); - insertCellRefList(mRendering, cell.itemLists, cell, *mPhysics); - insertCellRefList(mRendering, cell.lights, cell, *mPhysics); - insertCellRefList(mRendering, cell.lockpicks, cell, *mPhysics); - insertCellRefList(mRendering, cell.miscItems, cell, *mPhysics); - insertCellRefList(mRendering, cell.npcs, cell, *mPhysics); - insertCellRefList(mRendering, cell.probes, cell, *mPhysics); - insertCellRefList(mRendering, cell.repairs, cell, *mPhysics); - insertCellRefList(mRendering, cell.statics, cell, *mPhysics); - insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); -} + void Scene::insertCell(ESMS::CellStore &cell) + { + // Loop through all references in the cell + insertCellRefList(mRendering, cell.activators, cell, *mPhysics); + insertCellRefList(mRendering, cell.potions, cell, *mPhysics); + insertCellRefList(mRendering, cell.appas, cell, *mPhysics); + insertCellRefList(mRendering, cell.armors, cell, *mPhysics); + insertCellRefList(mRendering, cell.books, cell, *mPhysics); + insertCellRefList(mRendering, cell.clothes, cell, *mPhysics); + insertCellRefList(mRendering, cell.containers, cell, *mPhysics); + insertCellRefList(mRendering, cell.creatures, cell, *mPhysics); + insertCellRefList(mRendering, cell.doors, cell, *mPhysics); + insertCellRefList(mRendering, cell.ingreds, cell, *mPhysics); + insertCellRefList(mRendering, cell.creatureLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.itemLists, cell, *mPhysics); + insertCellRefList(mRendering, cell.lights, cell, *mPhysics); + insertCellRefList(mRendering, cell.lockpicks, cell, *mPhysics); + insertCellRefList(mRendering, cell.miscItems, cell, *mPhysics); + insertCellRefList(mRendering, cell.npcs, cell, *mPhysics); + insertCellRefList(mRendering, cell.probes, cell, *mPhysics); + insertCellRefList(mRendering, cell.repairs, cell, *mPhysics); + insertCellRefList(mRendering, cell.statics, cell, *mPhysics); + insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); + } + void Scene::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell) + { + ptr.mCell = cell; + + mRendering.addObject(ptr); + MWWorld::Class::get(ptr).insertObject(ptr, *mPhysics); + MWWorld::Class::get(ptr).enable(ptr); + + std::string type = ptr.getTypeName(); + + // insert into the correct CellRefList + if (type == typeid(ESM::Potion).name()) + cell->potions.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Apparatus).name()) + cell->appas.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Armor).name()) + cell->armors.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Book).name()) + cell->books.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Clothing).name()) + cell->clothes.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Ingredient).name()) + cell->ingreds.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Light).name()) + cell->lights.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Tool).name()) + cell->lockpicks.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Repair).name()) + cell->repairs.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Probe).name()) + cell->probes.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Weapon).name()) + cell->weapons.list.push_back( *ptr.get() ); + else if (type == typeid(ESM::Miscellaneous).name()) + cell->miscItems.list.push_back( *ptr.get() ); + else + throw std::runtime_error("Trying to insert object of unhandled type"); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 1a9f2f271..857ee50d1 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -100,6 +100,10 @@ namespace MWWorld void insertCell(ESMS::CellStore &cell); + /// this method is only meant for dropping objects into the gameworld from a container + /// and thus only handles object types that can be placed in a container + void insertObject(MWWorld::Ptr object, Ptr::CellStore* cell); + void update (float duration); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 4adaf7918..d2b687742 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -948,4 +948,9 @@ namespace MWWorld mRendering->toggleWater(); } + void World::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell) + { + mWorldScene->insertObject(ptr, cell); + } + } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 7359f8b90..3b56dea97 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -263,6 +263,9 @@ namespace MWWorld void update (float duration); + void insertObject (MWWorld::Ptr ptr, Ptr::CellStore* cell); + ///< insert object in a given cell + /// \note this method is only meant for dropping items into the gameworld from a container }; } From 933a40de14f1dc64c6d74685388841dca0fbc54d Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 14 May 2012 21:37:43 +0200 Subject: [PATCH 064/289] better floating object label positioning. --- apps/openmw/mwgui/tooltips.cpp | 15 ++++++--- apps/openmw/mwgui/tooltips.hpp | 5 +++ apps/openmw/mwgui/window_manager.cpp | 5 +++ apps/openmw/mwgui/window_manager.hpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 39 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 4 +++ apps/openmw/mwworld/world.cpp | 19 ++++++++++- 7 files changed, 82 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 635e9481b..6f8434535 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -17,6 +17,8 @@ ToolTips::ToolTips(WindowManager* windowManager) : , mWindowManager(windowManager) , mFullHelp(false) , mEnabled(true) + , mFocusToolTipX(0.0) + , mFocusToolTipY(0.0) { getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); @@ -118,11 +120,8 @@ void ToolTips::onFrame(float frameDuration) { IntSize tooltipSize = getToolTipViaPtr(); - // adjust tooltip size to fit its content, position it above the crosshair - /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind) - /// relevant link: http://www.ogre3d.org/tikiwiki/ObjectTextDisplay - setCoord(std::max(0, viewSize.width/2 - (tooltipSize.width)/2), - std::max(0, viewSize.height/2 - (tooltipSize.height) - 32), + setCoord(viewSize.width/2 - tooltipSize.width/2, + std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)), tooltipSize.width, tooltipSize.height); } @@ -387,3 +386,9 @@ bool ToolTips::getFullHelp() const { return mFullHelp; } + +void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) +{ + mFocusToolTipX = (min_x + max_x) / 2; + mFocusToolTipY = min_y; +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 87b9e97bf..4be0baff9 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -45,6 +45,8 @@ namespace MWGui bool getFullHelp() const; void setFocusObject(const MWWorld::Ptr& focus); + void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); + ///< set the screen-space position of the tooltip for focused object static std::string getValueString(const int value, const std::string& prefix); ///< @return "prefix: value" or "" if value is 0 @@ -73,6 +75,9 @@ namespace MWGui MyGUI::IntSize createToolTip(const ToolTipInfo& info); ///< @return requested tooltip size + float mFocusToolTipX; + float mFocusToolTipY; + bool mGameMode; bool mEnabled; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index bb533e698..c93d5303c 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -540,6 +540,11 @@ void WindowManager::setFocusObject(const MWWorld::Ptr& focus) mToolTips->setFocusObject(focus); } +void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) +{ + mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y); +} + void WindowManager::toggleFullHelp() { mToolTips->toggleFullHelp(); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 5dfcf6470..cff93266c 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -165,6 +165,7 @@ namespace MWGui void setPlayerDir(const float x, const float y); ///< set player view direction in map space void setFocusObject(const MWWorld::Ptr& focus); + void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setMouseVisible(bool visible); void setDragDrop(bool dragDrop); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a95a179c6..f795ed372 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -518,4 +518,43 @@ void RenderingManager::switchToExterior() mRendering.getScene()->setCameraRelativeRendering(true); } +Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds) +{ + Ogre::Matrix4 mat = mRendering.getCamera()->getViewMatrix(); + + const Ogre::Vector3* corners = bounds.getAllCorners(); + + float min_x = 1.0f, max_x = 0.0f, min_y = 1.0f, max_y = 0.0f; + + // expand the screen-space bounding-box so that it completely encloses + // the object's AABB + for (int i=0; i<8; i++) + { + Ogre::Vector3 corner = corners[i]; + + // multiply the AABB corner vertex by the view matrix to + // get a camera-space vertex + corner = mat * corner; + + // make 2D relative/normalized coords from the view-space vertex + // by dividing out the Z (depth) factor -- this is an approximation + float x = corner.x / corner.z + 0.5; + float y = corner.y / corner.z + 0.5; + + if (x < min_x) + min_x = x; + + if (x > max_x) + max_x = x; + + if (y < min_y) + min_y = y; + + if (y > max_y) + max_y = y; + } + + return Vector4(min_x, min_y, max_x, max_y); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 0d11b3d57..8b457997d 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -151,6 +151,10 @@ class RenderingManager: private RenderingInterface { ///< Skip the animation for the given MW-reference for one frame. Calls to this function for /// references that are currently not in the rendered scene should be ignored. + Ogre::Vector4 boundingBoxToScreen(Ogre::AxisAlignedBox bounds); + ///< transform the specified bounding box (in world coordinates) into screen coordinates. + /// @return packed vector4 (min_x, min_y, max_x, max_y) + private: void setAmbientMode(); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index d2b687742..0474d894c 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -768,7 +768,24 @@ namespace MWWorld // inform the GUI about focused object try { - MWBase::Environment::get().getWindowManager()->setFocusObject(getPtrViaHandle(mFacedHandle)); + MWWorld::Ptr object = getPtrViaHandle(mFacedHandle); + MWBase::Environment::get().getWindowManager()->setFocusObject(object); + + // retrieve object dimensions so we know where to place the floating label + Ogre::SceneNode* node = object.getRefData().getBaseNode(); + Ogre::AxisAlignedBox bounds; + int i; + for (i=0; inumAttachedObjects(); ++i) + { + Ogre::MovableObject* ob = node->getAttachedObject(i); + bounds.merge(ob->getWorldBoundingBox()); + } + if (bounds.isFinite()) + { + Vector4 screenCoords = mRendering->boundingBoxToScreen(bounds); + MWBase::Environment::get().getWindowManager()->setFocusObjectScreenCoords( + screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]); + } } catch (std::runtime_error&) { From 320cc7d020f3d68a1104d8207f8020ed0933f6bd Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 11:02:50 +0200 Subject: [PATCH 065/289] implemented ctrl and shift-keys for item drag&drop (take all, take 1) --- apps/openmw/mwgui/container.cpp | 74 +++++++++++++++++++--------- apps/openmw/mwgui/container.hpp | 7 ++- apps/openmw/mwinput/inputmanager.cpp | 39 ++++++++++++--- apps/openmw/mwinput/inputmanager.hpp | 3 ++ 4 files changed, 89 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 99a4b686e..82b695a2b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -49,29 +49,49 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { - mDragAndDrop->mIsOnDragAndDrop = true; - _sender->detachFromWidget(); - _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); + int count = (*_sender->getUserData()).getRefData().getCount(); - MWWorld::Ptr object = *_sender->getUserData(); - mDragAndDrop->mStore.add(object); - object.getRefData().setCount(0); - - std::string sound = MWWorld::Class::get(object).getUpSoundId(object); - MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - - mDragAndDrop->mDraggedWidget = _sender; - mDragAndDrop->mContainerWindow = const_cast(this); - // hide the count text - _sender->getChildAt(0)->getChildAt(0)->setVisible(false); - drawItems(); - - MWBase::Environment::get().getWindowManager()->setDragDrop(true); + if (MWBase::Environment::get().getInputManager()->getShiftDown() || count == 1) + { + onSelectedItemImpl(_sender, count); + } + else if (MWBase::Environment::get().getInputManager()->getCtrlDown()) + { + onSelectedItemImpl(_sender, 1); + } + else + { + /// \todo count selection window + onSelectedItemImpl(_sender, count); + } } else onContainerClicked(mContainerWidget); } +void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) +{ + mDragAndDrop->mIsOnDragAndDrop = true; + _sender->detachFromWidget(); + _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); + + MWWorld::Ptr object = *_sender->getUserData(); + int originalCount = object.getRefData().getCount(); + object.getRefData().setCount(count); + mDragAndDrop->mStore.add(object); + object.getRefData().setCount(originalCount - count); + + std::string sound = MWWorld::Class::get(object).getUpSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + + mDragAndDrop->mDraggedWidget = _sender; + mDragAndDrop->mContainerWindow = const_cast(this); + static_cast(_sender->getChildAt(0)->getChildAt(0))->setCaption(getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); + drawItems(); + + MWBase::Environment::get().getWindowManager()->setDragDrop(true); +} + void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here @@ -154,6 +174,8 @@ void ContainerBase::drawItems() + MWWorld::ContainerStore::Type_Apparatus; } + /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them + for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { index++; @@ -194,13 +216,7 @@ void ContainerBase::drawItems() y = 0; } - if(iter->getRefData().getCount() > 1) - { - if (iter->getRefData().getCount() > 9999) - text->setCaption(boost::lexical_cast(iter->getRefData().getCount()/1000.f) + "k"); - else - text->setCaption(boost::lexical_cast(iter->getRefData().getCount())); - } + text->setCaption(getCountString(iter->getRefData().getCount())); } } @@ -209,6 +225,16 @@ void ContainerBase::drawItems() mContainerWidget->setSize(size); } +std::string ContainerBase::getCountString(const int count) +{ + if (count == 1) + return ""; + if (count > 9999) + return boost::lexical_cast(count/1000.f) + "k"; + else + return boost::lexical_cast(count); +} + void ContainerBase::Update() { if(mDragAndDrop->mIsOnDragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 88fc55217..5cdc8ef1d 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -74,9 +74,12 @@ namespace MWGui Filter mFilter; void onSelectedItem(MyGUI::Widget* _sender); + void onSelectedItemImpl(MyGUI::Widget* _sender, int count); void onContainerClicked(MyGUI::Widget* _sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); + std::string getCountString(const int count); + void drawItems(); }; @@ -90,13 +93,9 @@ namespace MWGui void open(MWWorld::Ptr container); protected: - std::vector mContainerWidgets; - MyGUI::Button* mTakeButton; MyGUI::Button* mCloseButton; - bool mIsValid;//is in the right GUI Mode - void onWindowResize(MyGUI::Window* window); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 4d79eb321..787f12f25 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -60,7 +60,7 @@ namespace MWInput A_CycleWeaponRight, A_ToggleSneak, //Toggles Sneak, add Push-Sneak later A_ToggleWalk, //Toggle Walking/Running - A_Crouch, + A_Crouch, A_QuickSave, A_QuickLoad, @@ -69,6 +69,8 @@ namespace MWInput A_ToggleWeapon, A_ToggleSpell, + A_Shift, + A_ToggleFps, // Toggle FPS display (this is temporary) A_LAST // Marker for the last item @@ -90,6 +92,14 @@ namespace MWInput bool mDragDrop; + bool mShiftDown; + bool mCtrlDown; + +public: + bool getShiftDown() { return mShiftDown; } + bool getCtrlDown() { return mCtrlDown; } + +private: /* InputImpl Methods */ @@ -228,7 +238,9 @@ namespace MWInput player(_player), windows(_windows), mEngine (engine), - mDragDrop(false) + mDragDrop(false), + mShiftDown(false), + mCtrlDown(false) { using namespace OEngine::Input; using namespace OEngine::Render; @@ -323,9 +335,11 @@ namespace MWInput poller.bind(A_MoveRight, KC_D); poller.bind(A_MoveForward, KC_W); poller.bind(A_MoveBackward, KC_S); - - poller.bind(A_Jump, KC_E); - poller.bind(A_Crouch, KC_LCONTROL); + + poller.bind(A_Jump, KC_E); + poller.bind(A_Crouch, KC_LCONTROL); + + poller.bind(A_Shift, KC_LSHIFT); } void setDragDrop(bool dragDrop) @@ -347,6 +361,9 @@ namespace MWInput // event callbacks (which may crash) windows.update(); + mShiftDown = poller.isDown(A_Shift); + mCtrlDown = poller.isDown(A_Crouch); + // Disable movement in Gui mode if (windows.isGuiMode()) return; @@ -378,7 +395,7 @@ namespace MWInput else player.setForwardBackward (0); - if (poller.isDown(A_Jump)) + if (poller.isDown(A_Jump)) player.setUpDown (1); else if (poller.isDown(A_Crouch)) player.setUpDown (-1); @@ -445,4 +462,14 @@ namespace MWInput { impl->setDragDrop(dragDrop); } + + bool MWInputManager::getShiftDown() + { + return impl->getShiftDown(); + } + + bool MWInputManager::getCtrlDown() + { + return impl->getCtrlDown(); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 158d05f0e..9e46e59a3 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -50,6 +50,9 @@ namespace MWInput void update(); + bool getShiftDown(); + bool getCtrlDown(); + void setDragDrop(bool dragDrop); void setGuiMode(MWGui::GuiMode mode); From 24a0fecd37576cc3045e7cf69011d1f2472b8487 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 12:51:51 +0200 Subject: [PATCH 066/289] implemented item count selection dialog --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/class.hpp | 2 +- apps/openmw/mwgui/container.cpp | 42 ++++---- apps/openmw/mwgui/container.hpp | 2 + apps/openmw/mwgui/countdialog.cpp | 110 +++++++++++++++++++++ apps/openmw/mwgui/countdialog.hpp | 39 ++++++++ apps/openmw/mwgui/window_manager.cpp | 3 + apps/openmw/mwgui/window_manager.hpp | 3 + files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_count_window_layout.xml | 27 +++++ 10 files changed, 211 insertions(+), 20 deletions(-) create mode 100644 apps/openmw/mwgui/countdialog.cpp create mode 100644 apps/openmw/mwgui/countdialog.hpp create mode 100644 files/mygui/openmw_count_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 5ecb2eea8..972c7f2e4 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -26,7 +26,7 @@ add_openmw_dir (mwgui text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list - formatting itemwidget inventorywindow container hud + formatting itemwidget inventorywindow container hud countdialog ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 0e3348086..6f0138aa4 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -34,7 +34,7 @@ namespace MWGui typedef delegates::CMultiDelegate1 EventHandle_Int; /** Event : Button was clicked.\n - signature : void method(MyGUI::WidgetPtr widget, int index)\n + signature : void method(int index)\n */ EventHandle_Int eventButtonSelected; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 82b695a2b..afcd398a4 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -1,7 +1,12 @@ #include "container.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" +#include +#include +#include +#include +#include + +#include #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" @@ -13,14 +18,9 @@ #include "../mwinput/inputmanager.hpp" #include "../mwsound/soundmanager.hpp" -#include -#include -#include -#include -#include - -#include - +#include "window_manager.hpp" +#include "widgets.hpp" +#include "countdialog.hpp" using namespace MWGui; using namespace Widgets; @@ -49,7 +49,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { if(!mDragAndDrop->mIsOnDragAndDrop) { - int count = (*_sender->getUserData()).getRefData().getCount(); + mSelectedItem = _sender; + + MWWorld::Ptr object = (*_sender->getUserData()); + int count = object.getRefData().getCount(); if (MWBase::Environment::get().getInputManager()->getShiftDown() || count == 1) { @@ -61,8 +64,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) } else { - /// \todo count selection window - onSelectedItemImpl(_sender, count); + CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); + dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl); } } else @@ -72,10 +77,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) { mDragAndDrop->mIsOnDragAndDrop = true; - _sender->detachFromWidget(); - _sender->attachToWidget(mDragAndDrop->mDragAndDropWidget); + mSelectedItem->detachFromWidget(); + mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget); - MWWorld::Ptr object = *_sender->getUserData(); + MWWorld::Ptr object = *mSelectedItem->getUserData(); int originalCount = object.getRefData().getCount(); object.getRefData().setCount(count); mDragAndDrop->mStore.add(object); @@ -84,9 +89,10 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) std::string sound = MWWorld::Class::get(object).getUpSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mDragAndDrop->mDraggedWidget = _sender; + mDragAndDrop->mDraggedWidget = mSelectedItem; mDragAndDrop->mContainerWindow = const_cast(this); - static_cast(_sender->getChildAt(0)->getChildAt(0))->setCaption(getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); + static_cast(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( + getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); drawItems(); MWBase::Environment::get().getWindowManager()->setDragDrop(true); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 5cdc8ef1d..20dc16cca 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -68,6 +68,8 @@ namespace MWGui MyGUI::ScrollView* mItemView; MyGUI::Widget* mContainerWidget; + MyGUI::Widget* mSelectedItem; + DragAndDrop* mDragAndDrop; MWWorld::Ptr mContainer; diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp new file mode 100644 index 000000000..dc7e75e0e --- /dev/null +++ b/apps/openmw/mwgui/countdialog.cpp @@ -0,0 +1,110 @@ +#include "countdialog.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + +namespace MWGui +{ + CountDialog::CountDialog(WindowManager& parWindowManager) : + WindowBase("openmw_count_window_layout.xml", parWindowManager) + { + getWidget(mSlider, "CountSlider"); + getWidget(mItemEdit, "ItemEdit"); + getWidget(mItemText, "ItemText"); + getWidget(mLabelText, "LabelText"); + getWidget(mOkButton, "OkButton"); + getWidget(mCancelButton, "CancelButton"); + + mOkButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOk")->str); + mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); + mLabelText->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTake")->str); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); + mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange); + mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved); + } + + void CountDialog::open(const std::string& item, const int maxCount) + { + setVisible(true); + + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + + mSlider->setScrollRange(maxCount); + mItemText->setCaption(item); + + int width = std::max(mItemText->getTextSize().width + 128, 320); + setCoord(viewSize.width/2 - width/2, + viewSize.height/2 - mMainWidget->getHeight()/2, + width, + mMainWidget->getHeight()); + + // make other gui elements inaccessible while this dialog is open + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); + + MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit); + + mSlider->setScrollPosition(maxCount-1); + mItemEdit->setCaption(boost::lexical_cast(maxCount)); + + int okButtonWidth = mOkButton->getTextSize().width + 24; + mOkButton->setCoord(width - 30 - okButtonWidth, + mOkButton->getTop(), + okButtonWidth, + mOkButton->getHeight()); + + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(width - 30 - okButtonWidth - cancelButtonWidth - 8, + mCancelButton->getTop(), + cancelButtonWidth, + mCancelButton->getHeight()); + } + + void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender) + { + close(); + } + + void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender) + { + eventOkClicked(NULL, mSlider->getScrollPosition()+1); + + close(); + } + + void CountDialog::onEditTextChange(MyGUI::EditBox* _sender) + { + if (_sender->getCaption() == "") + return; + + unsigned int count; + try + { + count = boost::lexical_cast(_sender->getCaption()); + } + catch (std::bad_cast&) + { + count = 1; + } + if (count > mSlider->getScrollRange()) + { + count = mSlider->getScrollRange(); + } + mSlider->setScrollPosition(count-1); + onSliderMoved(mSlider, count-1); + } + + void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position) + { + mItemEdit->setCaption(boost::lexical_cast(_position+1)); + } + + void CountDialog::close() + { + setVisible(false); + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); + } +} diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp new file mode 100644 index 000000000..b6c836c9d --- /dev/null +++ b/apps/openmw/mwgui/countdialog.hpp @@ -0,0 +1,39 @@ +#ifndef MWGUI_COUNTDIALOG_H +#define MWGUI_COUNTDIALOG_H + +#include "window_base.hpp" + +namespace MWGui +{ + class CountDialog : public WindowBase + { + public: + CountDialog(WindowManager& parWindowManager); + void open(const std::string& item, const int maxCount); + + typedef MyGUI::delegates::CMultiDelegate2 EventHandle_WidgetInt; + + /** Event : Ok button was clicked.\n + signature : void method(MyGUI::Widget* _sender, int _count)\n + */ + EventHandle_WidgetInt eventOkClicked; + + private: + MyGUI::ScrollBar* mSlider; + MyGUI::EditBox* mItemEdit; + MyGUI::TextBox* mItemText; + MyGUI::TextBox* mLabelText; + MyGUI::Button* mOkButton; + MyGUI::Button* mCancelButton; + + void onCancelButtonClicked(MyGUI::Widget* _sender); + void onOkButtonClicked(MyGUI::Widget* _sender); + void onEditTextChange(MyGUI::EditBox* _sender); + void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position); + + void close(); + }; + +} + +#endif diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index c93d5303c..a068de7d9 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -14,6 +14,7 @@ #include "list.hpp" #include "hud.hpp" #include "mainmenu.hpp" +#include "countdialog.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -46,6 +47,7 @@ WindowManager::WindowManager( , mDialogueWindow(nullptr) , mBookWindow(NULL) , mScrollWindow(NULL) + , mCountDialog(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -112,6 +114,7 @@ WindowManager::WindowManager( mToolTips = new ToolTips(this); mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); + mCountDialog = new CountDialog(*this); // The HUD is always on hud->setVisible(true); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index cff93266c..3f5df5789 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -71,6 +71,7 @@ namespace MWGui class InfoBoxDialog; class DialogueWindow; class MessageBoxManager; + class CountDialog; struct ClassPoint { @@ -133,6 +134,7 @@ namespace MWGui MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} + MWGui::CountDialog* getCountDialog() {return mCountDialog;} MyGUI::Gui* getGui() const { return gui; } @@ -223,6 +225,7 @@ namespace MWGui InventoryWindow *mInventoryWindow; ScrollWindow* mScrollWindow; BookWindow* mBookWindow; + CountDialog* mCountDialog; CharacterCreation* mCharGen; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index ae9ddd395..2ee823d2a 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -55,6 +55,7 @@ configure_file("${SDIR}/openmw_tooltips.xml" "${DDIR}/openmw_tooltips.xml" COPYO configure_file("${SDIR}/openmw_scroll_layout.xml" "${DDIR}/openmw_scroll_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" COPYONLY) configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) diff --git a/files/mygui/openmw_count_window_layout.xml b/files/mygui/openmw_count_window_layout.xml new file mode 100644 index 000000000..38ba7644f --- /dev/null +++ b/files/mygui/openmw_count_window_layout.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7fbee0d488383d7e7aeddd1c46a0a7b436768ccd Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 13:00:26 +0200 Subject: [PATCH 067/289] use MyGUI::InputManager instead of MWInputManager to detect ctrl/shift --- apps/openmw/mwgui/container.cpp | 6 ++---- apps/openmw/mwgui/container.hpp | 1 - apps/openmw/mwgui/hud.cpp | 1 - apps/openmw/mwgui/window_manager.cpp | 1 - apps/openmw/mwinput/inputmanager.cpp | 29 +--------------------------- apps/openmw/mwinput/inputmanager.hpp | 3 --- 6 files changed, 3 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index afcd398a4..d926346d3 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -54,11 +54,11 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) MWWorld::Ptr object = (*_sender->getUserData()); int count = object.getRefData().getCount(); - if (MWBase::Environment::get().getInputManager()->getShiftDown() || count == 1) + if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) { onSelectedItemImpl(_sender, count); } - else if (MWBase::Environment::get().getInputManager()->getCtrlDown()) + else if (MyGUI::InputManager::getInstance().isControlPressed()) { onSelectedItemImpl(_sender, 1); } @@ -90,7 +90,6 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); mDragAndDrop->mDraggedWidget = mSelectedItem; - mDragAndDrop->mContainerWindow = const_cast(this); static_cast(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); drawItems(); @@ -115,7 +114,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) mDragAndDrop->mDraggedWidget->detachFromWidget(); mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); mDragAndDrop->mDraggedWidget = 0; - mDragAndDrop->mContainerWindow = 0; drawItems(); MWBase::Environment::get().getWindowManager()->setDragDrop(false); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 20dc16cca..b90044ab5 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -37,7 +37,6 @@ namespace MWGui { public: bool mIsOnDragAndDrop; - ContainerBase* mContainerWindow; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; MWWorld::ContainerStore mStore; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 80c02cd82..482047b9b 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -279,7 +279,6 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); mDragAndDrop->mDraggedWidget = 0; - mDragAndDrop->mContainerWindow = 0; MWBase::Environment::get().getWindowManager()->setDragDrop(false); } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a068de7d9..8624699cd 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -99,7 +99,6 @@ WindowManager::WindowManager( mDragAndDrop->mIsOnDragAndDrop = false; mDragAndDrop->mDraggedWidget = 0; mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; - mDragAndDrop->mContainerWindow = 0; menu = new MainMenu(w,h); map = new MapWindow(*this); diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 787f12f25..8f8f1e1ee 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -69,8 +69,6 @@ namespace MWInput A_ToggleWeapon, A_ToggleSpell, - A_Shift, - A_ToggleFps, // Toggle FPS display (this is temporary) A_LAST // Marker for the last item @@ -92,14 +90,6 @@ namespace MWInput bool mDragDrop; - bool mShiftDown; - bool mCtrlDown; - -public: - bool getShiftDown() { return mShiftDown; } - bool getCtrlDown() { return mCtrlDown; } - -private: /* InputImpl Methods */ @@ -238,9 +228,7 @@ private: player(_player), windows(_windows), mEngine (engine), - mDragDrop(false), - mShiftDown(false), - mCtrlDown(false) + mDragDrop(false) { using namespace OEngine::Input; using namespace OEngine::Render; @@ -338,8 +326,6 @@ private: poller.bind(A_Jump, KC_E); poller.bind(A_Crouch, KC_LCONTROL); - - poller.bind(A_Shift, KC_LSHIFT); } void setDragDrop(bool dragDrop) @@ -361,9 +347,6 @@ private: // event callbacks (which may crash) windows.update(); - mShiftDown = poller.isDown(A_Shift); - mCtrlDown = poller.isDown(A_Crouch); - // Disable movement in Gui mode if (windows.isGuiMode()) return; @@ -462,14 +445,4 @@ private: { impl->setDragDrop(dragDrop); } - - bool MWInputManager::getShiftDown() - { - return impl->getShiftDown(); - } - - bool MWInputManager::getCtrlDown() - { - return impl->getCtrlDown(); - } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 9e46e59a3..158d05f0e 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -50,9 +50,6 @@ namespace MWInput void update(); - bool getShiftDown(); - bool getCtrlDown(); - void setDragDrop(bool dragDrop); void setGuiMode(MWGui::GuiMode mode); From b18ee198b4b882879a9722d8e93630dca379f94b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 16:47:23 +0200 Subject: [PATCH 068/289] use a raycast to determine where to place object, if distance is too far drop it on the ground --- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 47 +++++++++++++++++++----- apps/openmw/mwgui/hud.hpp | 1 + apps/openmw/mwgui/window_manager.cpp | 1 - apps/openmw/mwworld/physicssystem.cpp | 25 ++++++++++++- apps/openmw/mwworld/physicssystem.hpp | 3 ++ apps/openmw/mwworld/world.cpp | 52 +++++++++++++++++++++++++-- apps/openmw/mwworld/world.hpp | 14 ++++++-- files/mygui/openmw.pointer.xml | 5 +++ files/mygui/openmw_layers.xml | 3 +- files/mygui/openmw_resources.xml | 7 ++++ 11 files changed, 142 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index d926346d3..bab0051b8 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -244,7 +244,7 @@ void ContainerBase::Update() if(mDragAndDrop->mIsOnDragAndDrop) { if(mDragAndDrop->mDraggedWidget) - mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition() - MyGUI::IntPoint(21, 21)); + mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. } } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 482047b9b..b99276440 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -91,6 +91,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) LocalMapBase::init(minimap, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); + mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); } void HUD::setFpsLevel(int level) @@ -261,16 +262,19 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) // drop item into the gameworld MWWorld::Ptr object = *mDragAndDrop->mStore.begin(); - float* playerPos; - playerPos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition().pos; - MWWorld::Ptr::CellStore* cell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); /// \todo this might be a different cell + MWWorld::World* world = MWBase::Environment::get().getWorld(); - ESM::Position& pos = object.getRefData().getPosition(); - pos.pos[0] = playerPos[0]; - pos.pos[1] = playerPos[1]; - pos.pos[2] = playerPos[2]; + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); + float mouseX = cursorPosition.left / float(viewSize.width); + float mouseY = cursorPosition.top / float(viewSize.height); - MWBase::Environment::get().getWorld()->insertObject(object, cell); + if (world->canPlaceObject(mouseX, mouseY)) + world->placeObject(object, mouseX, mouseY); + else + world->dropObjectOnGround(object); + + MyGUI::PointerManager::getInstance().setPointer("arrow"); std::string sound = MWWorld::Class::get(object).getDownSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); @@ -284,3 +288,30 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) } } +void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) +{ + if (mDragAndDrop->mIsOnDragAndDrop) + { + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); + float mouseX = cursorPosition.left / float(viewSize.width); + float mouseY = cursorPosition.top / float(viewSize.height); + + MWWorld::World* world = MWBase::Environment::get().getWorld(); + + // if we can't drop the object at the wanted position, show the "drop on ground" cursor. + bool canDrop = world->canPlaceObject(mouseX, mouseY); + + if (!canDrop) + MyGUI::PointerManager::getInstance().setPointer("drop_ground"); + else + MyGUI::PointerManager::getInstance().setPointer("arrow"); + + } + else + { + MyGUI::PointerManager::getInstance().setPointer("arrow"); + /// \todo make it possible to pick up objects with the mouse, if inventory or container window is open + } +} + diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 22b1b8738..cccfb0541 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -52,5 +52,6 @@ namespace MWGui DragAndDrop* mDragAndDrop; void onWorldClicked(MyGUI::Widget* _sender); + void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 8624699cd..a4788ad3b 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -576,5 +576,4 @@ void WindowManager::setDragDrop(bool dragDrop) { mToolTips->setEnabled(!dragDrop); MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); - setMouseVisible(!dragDrop); } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index fb13e37c6..808c712a0 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -80,7 +80,7 @@ namespace MWWorld Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); - btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); + btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable return result; } @@ -95,6 +95,29 @@ namespace MWWorld return !(result.first == ""); } + std::pair PhysicsSystem::castRay(float mouseX, float mouseY) + { + Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay( + mouseX, + mouseY); + Ogre::Vector3 from = ray.getOrigin(); + Ogre::Vector3 to = ray.getPoint(200); /// \todo make this distance (ray length) configurable + + btVector3 _from, _to; + // OGRE to MW coordinates + _from = btVector3(from.x, -from.z, from.y); + _to = btVector3(to.x, -to.z, to.y); + + std::pair result = mEngine->rayTest(_from, _to); + + if (result.first == "") + return std::make_pair(false, Ogre::Vector3()); + else + { + return std::make_pair(true, ray.getPoint(200*result.second)); /// \todo make this distance (ray length) configurable + } + } + void PhysicsSystem::doPhysics(float dt, const std::vector >& actors) { //set the DebugRenderingMode. To disable it,set it to 0 diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 1af6bcca2..9b03d2124 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -53,6 +53,9 @@ namespace MWWorld // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); + std::pair castRay(float mouseX, float mouseY); + ///< cast ray from the mouse, return true if it hit something and the first result (in OGRE coordinates) + void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model); void insertActorPhysics(const MWWorld::Ptr&, std::string model); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 0474d894c..973407b0c 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -965,9 +965,57 @@ namespace MWWorld mRendering->toggleWater(); } - void World::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell) + bool World::placeObject(MWWorld::Ptr object, float cursorX, float cursorY) { - mWorldScene->insertObject(ptr, cell); + std::pair result = mPhysics->castRay(cursorX, cursorY); + + if (!result.first) + return false; + + MWWorld::Ptr::CellStore* cell; + if (isCellExterior()) + { + int cellX, cellY; + positionToIndex(result.second[0], -result.second[2], cellX, cellY); + cell = mCells.getExterior(cellX, cellY); + } + else + cell = getPlayer().getPlayer().getCell(); + + ESM::Position& pos = object.getRefData().getPosition(); + pos.pos[0] = result.second[0]; + pos.pos[1] = -result.second[2]; + pos.pos[2] = result.second[1]; + + mWorldScene->insertObject(object, cell); + + /// \todo retrieve the bounds of the object and translate it accordingly + + return true; } + bool World::canPlaceObject(float cursorX, float cursorY) + { + std::pair result = mPhysics->castRay(cursorX, cursorY); + + /// \todo also check if the wanted position is on a flat surface, and not e.g. against a vertical wall! + + if (!result.first) + return false; + return true; + } + + void World::dropObjectOnGround(MWWorld::Ptr object) + { + MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); + + float* playerPos = getPlayer().getPlayer().getRefData().getPosition().pos; + + ESM::Position& pos = object.getRefData().getPosition(); + pos.pos[0] = playerPos[0]; + pos.pos[1] = playerPos[1]; + pos.pos[2] = playerPos[2]; + + mWorldScene->insertObject(object, cell); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 3b56dea97..1ed6a976e 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -263,9 +263,17 @@ namespace MWWorld void update (float duration); - void insertObject (MWWorld::Ptr ptr, Ptr::CellStore* cell); - ///< insert object in a given cell - /// \note this method is only meant for dropping items into the gameworld from a container + bool placeObject(MWWorld::Ptr object, float cursorX, float cursorY); + ///< place an object into the gameworld at the specified cursor position + /// @param object + /// @param cursor X (relative 0-1) + /// @param cursor Y (relative 0-1) + /// @return true if the object was placed, or false if it was rejected because the position is too far away + + void dropObjectOnGround(MWWorld::Ptr object); + + bool canPlaceObject(float cursorX, float cursorY); + ///< @return true if it is possible to place on object at specified cursor location }; } diff --git a/files/mygui/openmw.pointer.xml b/files/mygui/openmw.pointer.xml index 0fbef2fdf..42ee5d435 100644 --- a/files/mygui/openmw.pointer.xml +++ b/files/mygui/openmw.pointer.xml @@ -26,4 +26,9 @@ + + + + + diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 81cd99fea..a5044fb78 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -8,7 +8,6 @@ + - - diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index b2bd90d10..4c509ae13 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -36,6 +36,13 @@ + + + + + + + From ab6336b745ca83e96cecb81185ec8912fcf37661 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 18:05:53 +0200 Subject: [PATCH 069/289] using items via the inventory is now possible by dragging them on the avatar (only implemented for books right now) --- apps/openmw/engine.cpp | 18 +------- apps/openmw/mwclass/book.cpp | 6 +++ apps/openmw/mwclass/book.hpp | 3 ++ apps/openmw/mwgui/bookwindow.cpp | 14 ++++-- apps/openmw/mwgui/bookwindow.hpp | 2 + apps/openmw/mwgui/container.cpp | 7 +-- apps/openmw/mwgui/container.hpp | 8 ++++ apps/openmw/mwgui/inventorywindow.cpp | 62 +++++++++++++++++++++++---- apps/openmw/mwgui/inventorywindow.hpp | 3 ++ apps/openmw/mwgui/scrollwindow.cpp | 14 ++++-- apps/openmw/mwgui/scrollwindow.hpp | 2 + apps/openmw/mwworld/actiontake.cpp | 5 ++- apps/openmw/mwworld/ptr.hpp | 5 +++ apps/openmw/mwworld/world.cpp | 27 ++++++++++++ apps/openmw/mwworld/world.hpp | 3 ++ 15 files changed, 144 insertions(+), 35 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 85b0557b1..a9e7c82b0 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -437,25 +437,11 @@ void OMW::Engine::activate() return; } - MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); - boost::shared_ptr action = MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - interpreterContext.activate (ptr, action); - - std::string script = MWWorld::Class::get (ptr).getScript (ptr); - - if (!script.empty()) - { - MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr); - MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); - } - - if (!interpreterContext.hasActivationBeenHandled()) - { - interpreterContext.executeActivation(); - } + // execute action and script + MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); } void OMW::Engine::screenshot() diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index f58eac7ec..a107d9b21 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -148,4 +148,10 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const + { + return boost::shared_ptr(new MWWorld::ActionRead(ptr)); + } + } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 6858bac7f..ee3aac8d8 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -47,6 +47,9 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 8de45984c..c6411175d 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -52,7 +52,7 @@ void BookWindow::open (MWWorld::Ptr book) clearPages(); mCurrentPage = 0; - MWBase::Environment::get().getSoundManager()->playSound3D (book, "book open", 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); ESMS::LiveCellRef *ref = mBook.get(); @@ -77,18 +77,26 @@ void BookWindow::open (MWWorld::Ptr book) } updatePages(); + + setTakeButtonShow(true); +} + +void BookWindow::setTakeButtonShow(bool show) +{ + mTakeButton->setVisible(show); } void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound3D (mBook, "book close", 1.0, 1.0); + // no 3d sounds because the object could be in a container. + MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound3D (mBook, "Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); MWWorld::ActionTake take(mBook); take.execute(); diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index fcea1d11f..9ea011433 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -11,7 +11,9 @@ namespace MWGui { public: BookWindow(WindowManager& parWindowManager); + void open(MWWorld::Ptr book); + void setTakeButtonShow(bool show); protected: void onNextPageButtonClicked (MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index bab0051b8..ff7bb889e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -92,6 +92,9 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) mDragAndDrop->mDraggedWidget = mSelectedItem; static_cast(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount())); + + mDragAndDrop->mWasInInventory = isInventory(); + drawItems(); MWBase::Environment::get().getWindowManager()->setDragDrop(true); @@ -111,9 +114,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) containerStore.add(*mDragAndDrop->mStore.begin()); mDragAndDrop->mStore.clear(); mDragAndDrop->mIsOnDragAndDrop = false; - mDragAndDrop->mDraggedWidget->detachFromWidget(); - mDragAndDrop->mDraggedWidget->attachToWidget(mContainerWidget); - mDragAndDrop->mDraggedWidget = 0; + MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); drawItems(); MWBase::Environment::get().getWindowManager()->setDragDrop(false); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index b90044ab5..8a1307967 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -36,10 +36,16 @@ namespace MWGui class DragAndDrop { public: + DragAndDrop() : + mWasInInventory(false) + { + } + bool mIsOnDragAndDrop; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; MWWorld::ContainerStore mStore; + bool mWasInInventory; // was the item in inventory before it was dragged }; class ContainerBase @@ -81,6 +87,8 @@ namespace MWGui std::string getCountString(const int count); + virtual bool isInventory() { return false; } + void drawItems(); }; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 23e4949f7..e9c3af7d4 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -1,23 +1,33 @@ #include "inventorywindow.hpp" -#include -#include -#include "window_manager.hpp" -#include "widgets.hpp" -#include "../mwbase/environment.hpp" -#include "../mwworld/manualref.hpp" #include #include #include - #include #include + +#include + #include "../mwclass/container.hpp" #include "../mwworld/containerstore.hpp" -#include #include "../mwworld/class.hpp" #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/manualref.hpp" + +#include "../mwscript/scriptmanager.hpp" +#include "../mwscript/compilercontext.hpp" +#include "../mwscript/interpretercontext.hpp" +#include "../mwscript/extensions.hpp" +#include "../mwscript/globalscripts.hpp" + + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "bookwindow.hpp" +#include "scrollwindow.hpp" + namespace MWGui { @@ -38,6 +48,8 @@ namespace MWGui getWidget(mLeftPane, "LeftPane"); getWidget(mRightPane, "RightPane"); + mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked); + MyGUI::ScrollView* itemView; MyGUI::Widget* containerWidget; getWidget(containerWidget, "Items"); @@ -126,4 +138,38 @@ namespace MWGui mWindowManager.setWeaponVisibility(!mPinned); } + void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender) + { + if (mDragAndDrop->mIsOnDragAndDrop) + { + MWWorld::Ptr ptr = *mDragAndDrop->mStore.begin(); + + boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + + // execute action and script + MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); + + // this is necessary for books/scrolls: if they are already in the player's inventory, + // the "Take" button should not be visible. + // NOTE: the take button is "reset" when the window opens, so we can safely do the following + // without screwing up future book windows + if (mDragAndDrop->mWasInInventory) + { + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); + } + + // put back in inventory + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + containerStore.add(ptr); + drawItems(); + + mDragAndDrop->mStore.clear(); + mDragAndDrop->mIsOnDragAndDrop = false; + MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); + + mWindowManager.setDragDrop(false); + } + } + } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index f16dcf433..b09ff8521 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -47,7 +47,10 @@ namespace MWGui void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); + void onAvatarClicked(MyGUI::Widget* _sender); void onPinToggled(); + + virtual bool isInventory() { return true; } }; } #endif // Inventory_H diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 38e2f77c1..877864cfe 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -25,7 +25,8 @@ ScrollWindow::ScrollWindow (WindowManager& parWindowManager) : void ScrollWindow::open (MWWorld::Ptr scroll) { - MWBase::Environment::get().getSoundManager()->playSound3D (scroll, "scroll", 1.0, 1.0); + // no 3d sounds because the object could be in a container. + MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); mScroll = scroll; @@ -41,18 +42,25 @@ void ScrollWindow::open (MWWorld::Ptr scroll) mTextView->setCanvasSize(410, mTextView->getSize().height); mTextView->setViewOffset(MyGUI::IntPoint(0,0)); + + setTakeButtonShow(true); +} + +void ScrollWindow::setTakeButtonShow(bool show) +{ + mTakeButton->setVisible(show); } void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound3D (mScroll, "scroll", 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound3D (mScroll, "Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); + MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); MWWorld::ActionTake take(mScroll); take.execute(); diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 918a3d3ef..d58596b4b 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -11,7 +11,9 @@ namespace MWGui { public: ScrollWindow (WindowManager& parWindowManager); + void open (MWWorld::Ptr scroll); + void setTakeButtonShow(bool show); protected: void onCloseButtonClicked (MyGUI::Widget* _sender); diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index b1e2e1fc3..384cb3ffe 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -18,7 +18,8 @@ namespace MWWorld MWWorld::Class::get (player).getContainerStore (player).add (mObject); - // remove from world - MWBase::Environment::get().getWorld()->deleteObject (mObject); + // remove from world, if the item is currently in the world (it could also be in a container) + if (mObject.isInCell()) + MWBase::Environment::get().getWorld()->deleteObject (mObject); } } diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index d6e485f41..4cf3e98da 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -77,6 +77,11 @@ namespace MWWorld return mCell; } + bool isInCell() const + { + return (mCell != 0); + } + void setContainerStore (ContainerStore *store); ///< Must not be called on references that are in a cell. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 973407b0c..ce7821280 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -17,6 +17,13 @@ #include "../mwgui/window_manager.hpp" +#include "../mwscript/scriptmanager.hpp" +#include "../mwscript/compilercontext.hpp" +#include "../mwscript/interpretercontext.hpp" +#include "../mwscript/extensions.hpp" +#include "../mwscript/globalscripts.hpp" + + #include "ptr.hpp" #include "class.hpp" #include "player.hpp" @@ -1018,4 +1025,24 @@ namespace MWWorld mWorldScene->insertObject(object, cell); } + + void World::executeActionScript(MWWorld::Ptr ptr, boost::shared_ptr action) + { + MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); + + action->execute(); + + // execute script + interpreterContext.activate (ptr, action); + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + if (!script.empty()) + { + getLocalScripts().setIgnore (ptr); + MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); + } + if (!interpreterContext.hasActivationBeenHandled()) + { + interpreterContext.executeActivation(); + } + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 1ed6a976e..c1d4ace20 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -274,6 +274,9 @@ namespace MWWorld bool canPlaceObject(float cursorX, float cursorY); ///< @return true if it is possible to place on object at specified cursor location + + void executeActionScript(MWWorld::Ptr ptr, boost::shared_ptr action); + ///< execute the activation script of an object (when activating the object with space, or when activating it via the inventory) }; } From 765881a61d8b770ff2509f287953198b6dafb721 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 18:20:32 +0200 Subject: [PATCH 070/289] equipping items in the inventorywindow (there is no visual indication yet) --- apps/openmw/mwgui/inventorywindow.cpp | 55 +++++++++++++++++++-------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e9c3af7d4..956961b63 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -144,24 +144,49 @@ namespace MWGui { MWWorld::Ptr ptr = *mDragAndDrop->mStore.begin(); - boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); - - // execute action and script - MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); - - // this is necessary for books/scrolls: if they are already in the player's inventory, - // the "Take" button should not be visible. - // NOTE: the take button is "reset" when the window opens, so we can safely do the following - // without screwing up future book windows - if (mDragAndDrop->mWasInInventory) + // can the object be equipped? + std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); + if (slots.first.empty()) { - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); + // can't be equipped, try to use instead + boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + + // execute action and script + MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); + + // this is necessary for books/scrolls: if they are already in the player's inventory, + // the "Take" button should not be visible. + // NOTE: the take button is "reset" when the window opens, so we can safely do the following + // without screwing up future book windows + if (mDragAndDrop->mWasInInventory) + { + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); + } + + // put back in inventory + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + containerStore.add(ptr); + } + else + { + // 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()) + { + ++it; + ++nextIt; + } + + // equip the item in the first available slot + invStore.equip(slots.first.front(), it); } - // put back in inventory - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - containerStore.add(ptr); drawItems(); mDragAndDrop->mStore.clear(); From 71de10cb7ed0e19db20e050f37df41bec65ef480 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 20:33:34 +0200 Subject: [PATCH 071/289] equipping items works, but only if you have more than one of the item that you're equipping --- apps/openmw/mwgui/container.cpp | 57 +++++++++++++++++++++- apps/openmw/mwgui/container.hpp | 12 +++++ apps/openmw/mwgui/inventorywindow.cpp | 66 +++++++++++++++++++++++--- apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwworld/containerstore.cpp | 5 +- apps/openmw/mwworld/containerstore.hpp | 4 +- apps/openmw/mwworld/inventorystore.cpp | 7 +++ apps/openmw/mwworld/inventorystore.hpp | 3 ++ 8 files changed, 145 insertions(+), 11 deletions(-) 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); From ca4fa21d64256244615a4fe86ffa2126be79ec35 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 20:51:19 +0200 Subject: [PATCH 072/289] removed the attempt to unify activation and use scripts which was incorrect --- apps/openmw/engine.cpp | 18 ++++++++++++++++-- apps/openmw/mwgui/inventorywindow.cpp | 5 +++-- apps/openmw/mwworld/world.cpp | 27 --------------------------- apps/openmw/mwworld/world.hpp | 3 --- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a9e7c82b0..85b0557b1 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -437,11 +437,25 @@ void OMW::Engine::activate() return; } + MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); + boost::shared_ptr action = MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - // execute action and script - MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); + interpreterContext.activate (ptr, action); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (!script.empty()) + { + MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr); + MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); + } + + if (!interpreterContext.hasActivationBeenHandled()) + { + interpreterContext.executeActivation(); + } } void OMW::Engine::screenshot() diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e466c34d1..ef41bf10a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -153,8 +153,9 @@ namespace MWGui std::cout << "Item can't be equipped" << std::endl; - // execute action and script - MWBase::Environment::get().getWorld()->executeActionScript(ptr, action); + action->execute(); + + /// \todo scripts // this is necessary for books/scrolls: if they are already in the player's inventory, // the "Take" button should not be visible. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index ce7821280..973407b0c 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -17,13 +17,6 @@ #include "../mwgui/window_manager.hpp" -#include "../mwscript/scriptmanager.hpp" -#include "../mwscript/compilercontext.hpp" -#include "../mwscript/interpretercontext.hpp" -#include "../mwscript/extensions.hpp" -#include "../mwscript/globalscripts.hpp" - - #include "ptr.hpp" #include "class.hpp" #include "player.hpp" @@ -1025,24 +1018,4 @@ namespace MWWorld mWorldScene->insertObject(object, cell); } - - void World::executeActionScript(MWWorld::Ptr ptr, boost::shared_ptr action) - { - MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); - - action->execute(); - - // execute script - interpreterContext.activate (ptr, action); - std::string script = MWWorld::Class::get (ptr).getScript (ptr); - if (!script.empty()) - { - getLocalScripts().setIgnore (ptr); - MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); - } - if (!interpreterContext.hasActivationBeenHandled()) - { - interpreterContext.executeActivation(); - } - } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index c1d4ace20..1ed6a976e 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -274,9 +274,6 @@ namespace MWWorld bool canPlaceObject(float cursorX, float cursorY); ///< @return true if it is possible to place on object at specified cursor location - - void executeActionScript(MWWorld::Ptr ptr, boost::shared_ptr action); - ///< execute the activation script of an object (when activating the object with space, or when activating it via the inventory) }; } From c6493fb133b36bec6aeccb634d1cfb4b3bd1335f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 May 2012 21:17:00 +0200 Subject: [PATCH 073/289] added getCapacity function --- apps/openmw/mwclass/container.cpp | 8 ++++++++ apps/openmw/mwclass/container.hpp | 4 ++++ apps/openmw/mwclass/creature.cpp | 6 ++++++ apps/openmw/mwclass/creature.hpp | 4 ++++ apps/openmw/mwclass/npc.cpp | 6 ++++++ apps/openmw/mwclass/npc.hpp | 4 ++++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 5 +++++ 8 files changed, 42 insertions(+) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index a9def96aa..82a9212a2 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -176,4 +176,12 @@ namespace MWClass return info; } + + float Container::getCapactiy (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->weight; + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 3b1c8de09..0231ce26b 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -36,6 +36,10 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr + virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + ///< Return total weight that fits into the object (including modifications from magic + /// effects). Throws an exception, if the object can't hold other objects. + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index cf00f361b..a16455430 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -166,4 +166,10 @@ namespace MWClass return info; } + + float Creature::getCapactiy (const MWWorld::Ptr& ptr) const + { + const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); + return stats.mAttributes[0].getModified()*5; + } } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 4a1a8285f..c68d1995d 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -52,6 +52,10 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr + virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + ///< Return total weight that fits into the object (including modifications from magic + /// effects). Throws an exception, if the object can't hold other objects. + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 444fe9965..3c1c0e29a 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -325,4 +325,10 @@ namespace MWClass return info; } + + float Npc::getCapactiy (const MWWorld::Ptr& ptr) const + { + const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); + return stats.mAttributes[0].getModified()*5; + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 38b0ba03f..d2ecc7aa7 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -74,6 +74,10 @@ namespace MWClass ///< Return desired movement vector (determined based on movement settings, /// stance and stats). + virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + ///< Return total weight that fits into the object (including modifications from magic + /// effects). Throws an exception, if the object can't hold other objects. + static void registerSelf(); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 151d913be..24d2d07f1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -142,6 +142,11 @@ namespace MWWorld throw std::logic_error ("value not supported by this class"); } + float Class::getCapactiy (const MWWorld::Ptr& ptr) const + { + throw std::runtime_error ("capacity not supported by class"); + } + const Class& Class::get (const std::string& key) { std::map >::const_iterator iter = sClasses.find (key); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index d7a2d2d75..34e61c54a 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -164,6 +164,11 @@ namespace MWWorld ///< Return trade value of the object. Throws an exception, if the object can't be traded. /// (default implementation: throws an exception) + virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + ///< Return total weight that fits into the object (including modifications from magic + /// effects). Throws an exception, if the object can't hold other objects. + /// (default implementation: throws an exception) + static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. From 7e00fea18b3666529d33a968b371b4297fb85bfc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 May 2012 21:34:00 +0200 Subject: [PATCH 074/289] added getEncumbrance function --- apps/openmw/mwclass/container.cpp | 5 +++++ apps/openmw/mwclass/container.hpp | 6 +++++- apps/openmw/mwclass/creature.cpp | 17 +++++++++++++++++ apps/openmw/mwclass/creature.hpp | 6 +++++- apps/openmw/mwclass/npc.cpp | 16 ++++++++++++++++ apps/openmw/mwclass/npc.hpp | 6 +++++- apps/openmw/mwworld/class.cpp | 7 ++++++- apps/openmw/mwworld/class.hpp | 7 ++++++- 8 files changed, 65 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 82a9212a2..34d6b6c60 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -184,4 +184,9 @@ namespace MWClass return ref->base->weight; } + + float Container::getEncumbrance (const MWWorld::Ptr& ptr) const + { + return getContainerStore (ptr).getWeight(); + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 0231ce26b..61a0d912b 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -37,7 +37,11 @@ namespace MWClass ///< Return name of the script attached to ptr virtual float getCapactiy (const MWWorld::Ptr& ptr) const; - ///< Return total weight that fits into the object (including modifications from magic + ///< Return total weight that fits into the object. Throws an exception, if the object can't + /// hold other objects. + + virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. static void registerSelf(); diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index a16455430..a0b2225db 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -5,6 +5,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwmechanics/magiceffects.hpp" #include "../mwbase/environment.hpp" @@ -172,4 +173,20 @@ namespace MWClass const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); return stats.mAttributes[0].getModified()*5; } + + float Creature::getEncumbrance (const MWWorld::Ptr& ptr) const + { + float weight = getContainerStore (ptr).getWeight(); + + const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); + + weight -= stats.mMagicEffects.get (MWMechanics::EffectKey (8)).mMagnitude; // feather + + weight += stats.mMagicEffects.get (MWMechanics::EffectKey (7)).mMagnitude; // burden + + if (weight<0) + weight = 0; + + return weight; + } } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index c68d1995d..7224d3ee1 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -53,7 +53,11 @@ namespace MWClass ///< Return name of the script attached to ptr virtual float getCapactiy (const MWWorld::Ptr& ptr) const; - ///< Return total weight that fits into the object (including modifications from magic + ///< Return total weight that fits into the object. Throws an exception, if the object can't + /// hold other objects. + + virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. static void registerSelf(); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 3c1c0e29a..3bb4519c2 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -331,4 +331,20 @@ namespace MWClass const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); return stats.mAttributes[0].getModified()*5; } + + float Npc::getEncumbrance (const MWWorld::Ptr& ptr) const + { + float weight = getContainerStore (ptr).getWeight(); + + const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); + + weight -= stats.mMagicEffects.get (MWMechanics::EffectKey (8)).mMagnitude; // feather + + weight += stats.mMagicEffects.get (MWMechanics::EffectKey (7)).mMagnitude; // burden + + if (weight<0) + weight = 0; + + return weight; + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index d2ecc7aa7..0cfad0347 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -75,7 +75,11 @@ namespace MWClass /// stance and stats). virtual float getCapactiy (const MWWorld::Ptr& ptr) const; - ///< Return total weight that fits into the object (including modifications from magic + ///< Return total weight that fits into the object. Throws an exception, if the object can't + /// hold other objects. + + virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. static void registerSelf(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 24d2d07f1..5fb503847 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -144,7 +144,12 @@ namespace MWWorld float Class::getCapactiy (const MWWorld::Ptr& ptr) const { - throw std::runtime_error ("capacity not supported by class"); + throw std::runtime_error ("capacity not supported by this class"); + } + + float Class::getEncumbrance (const MWWorld::Ptr& ptr) const + { + throw std::runtime_error ("encumbrance not supported by class"); } const Class& Class::get (const std::string& key) diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 34e61c54a..513dc942b 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -165,7 +165,12 @@ namespace MWWorld /// (default implementation: throws an exception) virtual float getCapactiy (const MWWorld::Ptr& ptr) const; - ///< Return total weight that fits into the object (including modifications from magic + ///< Return total weight that fits into the object. Throws an exception, if the object can't + /// hold other objects. + /// (default implementation: throws an exception) + + virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. /// (default implementation: throws an exception) From fdfddc8be7d8b720a8eb54aed365a17bb60bd082 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 May 2012 21:34:32 +0200 Subject: [PATCH 075/289] some todo comment cleanup --- apps/openmw/mwclass/creature.cpp | 2 -- apps/openmw/mwclass/npc.cpp | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index a0b2225db..c2623500d 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -57,8 +57,6 @@ namespace MWClass data->mCreatureStats.mLevel = ref->base->data.level; - // \todo add initial container content - // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 3bb4519c2..556798bf4 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -88,11 +88,9 @@ namespace MWClass } else { - //TODO: do something with npdt12 maybe:p + /// \todo do something with npdt12 maybe:p } - // \todo add initial container content - // store ptr.getRefData().setCustomData (data.release()); } From 175623bf22ab3608231524fae7164d05bb2154ae Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 21:44:57 +0200 Subject: [PATCH 076/289] change the drag&drop to not use a seperate containerstore --- apps/openmw/mwgui/container.cpp | 40 ++++++++++++++++++--------- apps/openmw/mwgui/container.hpp | 7 +++-- apps/openmw/mwgui/hud.cpp | 6 ++-- apps/openmw/mwgui/inventorywindow.cpp | 34 +++++++---------------- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6bf6a589e..66ccfd50f 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -83,10 +83,9 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) MWWorld::Ptr object = *mSelectedItem->getUserData(); _unequipItem(object); - int originalCount = object.getRefData().getCount(); - object.getRefData().setCount(count); - mDragAndDrop->mStore.add(object); - object.getRefData().setCount(originalCount - count); + 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); @@ -94,7 +93,7 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) 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())); + getCountString(mDragAndDrop->mDraggedCount)); mDragAndDrop->mWasInInventory = isInventory(); @@ -108,19 +107,27 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); - assert(object.getContainerStore() && "Item is not in a container!"); - std::string sound = MWWorld::Class::get(object).getDownSoundId(object); - MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + if (mDragAndDrop->mDraggedFrom != this) + { + assert(object.getContainerStore() && "Item is not in a container!"); + + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + int origCount = object.getRefData().getCount(); + object.getRefData().setCount (mDragAndDrop->mDraggedCount); + containerStore.add(object); + object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); + } - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - containerStore.add(*mDragAndDrop->mStore.begin()); - mDragAndDrop->mStore.clear(); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); drawItems(); + mDragAndDrop->mDraggedFrom->drawItems(); 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); } } @@ -224,7 +231,14 @@ void ContainerBase::drawItems() { 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())) + + int displayCount = iter->getRefData().getCount(); + if (mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) + { + std::cout << "beep" << std::endl; + displayCount -= mDragAndDrop->mDraggedCount; +} + if(displayCount > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); @@ -276,7 +290,7 @@ void ContainerBase::drawItems() y = 0; } - text->setCaption(getCountString(iter->getRefData().getCount())); + text->setCaption(getCountString(displayCount)); } } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 9f994be16..a19f9e91f 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -44,7 +44,8 @@ namespace MWGui bool mIsOnDragAndDrop; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; - MWWorld::ContainerStore mStore; + ContainerBase* mDraggedFrom; + int mDraggedCount; bool mWasInInventory; // was the item in inventory before it was dragged }; @@ -77,6 +78,8 @@ namespace MWGui void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter void Update(); + void drawItems(); + protected: MyGUI::ScrollView* mItemView; @@ -100,8 +103,6 @@ namespace MWGui virtual bool isInventory() { return false; } virtual std::vector getEquippedItems() { return std::vector(); } virtual void _unequipItem(MWWorld::Ptr item) { ; } - - void drawItems(); }; class ContainerWindow : public ContainerBase, public WindowBase diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index b99276440..90adb80d5 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -260,7 +260,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if (mDragAndDrop->mIsOnDragAndDrop) { // drop item into the gameworld - MWWorld::Ptr object = *mDragAndDrop->mStore.begin(); + MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); MWWorld::World* world = MWBase::Environment::get().getWorld(); @@ -279,7 +279,9 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) std::string sound = MWWorld::Class::get(object).getDownSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mDragAndDrop->mStore.clear(); + // remove object from the container it was coming from + object.getRefData().setCount(0); + mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); mDragAndDrop->mDraggedWidget = 0; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ef41bf10a..0c8ac459f 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -142,7 +142,7 @@ namespace MWGui { if (mDragAndDrop->mIsOnDragAndDrop) { - MWWorld::Ptr ptr = *mDragAndDrop->mStore.begin(); + MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData(); // can the object be equipped? std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); @@ -166,49 +166,35 @@ namespace MWGui mWindowManager.getBookWindow()->setTakeButtonShow(false); mWindowManager.getScrollWindow()->setTakeButtonShow(false); } - - // put back in inventory - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - containerStore.add(ptr); } else { - // put back in inventory MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - 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()) + // retrieve iterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) { - std::cout << "stacking didn't happen" << std::endl; - for (MWWorld::ContainerStoreIterator it2 = invStore.begin(); - it2 != invStore.end(); ++it2) + if (*it == ptr) { - if (*it2 == ptr) - { - std::cout << "found iterator" << std::endl; - it = it2; - return; - } + break; } } + assert(it != invStore.end()); + // 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(); - - mDragAndDrop->mStore.clear(); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); mWindowManager.setDragDrop(false); + + drawItems(); } } From d3a53ae0b8f295cff46f0dfafa01d576e8aac15f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 22:01:09 +0200 Subject: [PATCH 077/289] removed the _freeSlot method which is now unneeded --- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 7 ------- apps/openmw/mwworld/inventorystore.hpp | 3 --- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 0c8ac459f..5e33d4600 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -231,7 +231,7 @@ namespace MWGui MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); if (it != invStore.end() && *it == item) { - invStore._freeSlot(slot); + invStore.equip(slot, invStore.end()); return; } } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index b38167d70..3e535793c 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -97,13 +97,6 @@ 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 303604f4d..05fc651ee 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -60,9 +60,6 @@ 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); From e9ea1fba4e85ab99fc030ace36512f64d1140d9c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 22:31:52 +0200 Subject: [PATCH 078/289] fixed typo getCapacity method --- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwclass/container.hpp | 2 +- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/creature.hpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwclass/npc.hpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 2e0d2d866..e9b8ce31f 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -180,7 +180,7 @@ namespace MWClass return info; } - float Container::getCapactiy (const MWWorld::Ptr& ptr) const + float Container::getCapacity (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 61a0d912b..44f0fe927 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -36,7 +36,7 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr - virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index c2623500d..653fabd08 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -166,7 +166,7 @@ namespace MWClass return info; } - float Creature::getCapactiy (const MWWorld::Ptr& ptr) const + float Creature::getCapacity (const MWWorld::Ptr& ptr) const { const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); return stats.mAttributes[0].getModified()*5; diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 7224d3ee1..9d9491579 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -52,7 +52,7 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr - virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 556798bf4..db0a6460c 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -324,7 +324,7 @@ namespace MWClass return info; } - float Npc::getCapactiy (const MWWorld::Ptr& ptr) const + float Npc::getCapacity (const MWWorld::Ptr& ptr) const { const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); return stats.mAttributes[0].getModified()*5; diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 0cfad0347..ef154bad4 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -74,7 +74,7 @@ namespace MWClass ///< Return desired movement vector (determined based on movement settings, /// stance and stats). - virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c014fb375..15bc405ce 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -142,7 +142,7 @@ namespace MWWorld throw std::logic_error ("value not supported by this class"); } - float Class::getCapactiy (const MWWorld::Ptr& ptr) const + float Class::getCapacity (const MWWorld::Ptr& ptr) const { throw std::runtime_error ("capacity not supported by this class"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 7bf13d822..a8f2aba17 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -164,7 +164,7 @@ namespace MWWorld ///< Return trade value of the object. Throws an exception, if the object can't be traded. /// (default implementation: throws an exception) - virtual float getCapactiy (const MWWorld::Ptr& ptr) const; + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. /// (default implementation: throws an exception) From 3f4ce327270e862cdd91667ea3782984d9bf56b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 22:45:46 +0200 Subject: [PATCH 079/289] implemented player encumbrance bar --- apps/openmw/mwgui/container.cpp | 2 ++ apps/openmw/mwgui/container.hpp | 1 + apps/openmw/mwgui/hud.cpp | 1 + apps/openmw/mwgui/inventorywindow.cpp | 21 ++++++++++++++++++++- apps/openmw/mwgui/inventorywindow.hpp | 4 ++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 66ccfd50f..52714fd22 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -297,6 +297,8 @@ void ContainerBase::drawItems() 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) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index a19f9e91f..d93cdd187 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -80,6 +80,7 @@ namespace MWGui void Update(); void drawItems(); + virtual void notifyContentChanged() { } protected: MyGUI::ScrollView* mItemView; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 90adb80d5..d327653f0 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -281,6 +281,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) // remove object from the container it was coming from object.getRefData().setCount(0); + mDragAndDrop->mDraggedFrom->notifyContentChanged(); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 5e33d4600..8eb4b7bb1 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -95,9 +95,12 @@ namespace MWGui void InventoryWindow::openInventory() { - openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + openContainer(player); onWindowResize(static_cast(mMainWidget)); + + updateEncumbranceBar(); } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) @@ -236,4 +239,20 @@ namespace MWGui } } } + + void InventoryWindow::updateEncumbranceBar() + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + float capacity = MWWorld::Class::get(player).getCapacity(player); + float encumbrance = MWWorld::Class::get(player).getEncumbrance(player); + mEncumbranceBar->setProgressRange(capacity); + mEncumbranceBar->setProgressPosition(encumbrance); + mEncumbranceText->setCaption( boost::lexical_cast(int(encumbrance)) + "/" + boost::lexical_cast(int(capacity)) ); + } + + void InventoryWindow::notifyContentChanged() + { + updateEncumbranceBar(); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 18dc913fc..c1a36bd56 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -30,6 +30,8 @@ namespace MWGui void openInventory(); + virtual void notifyContentChanged(); + protected: MyGUI::Widget* mAvatar; MyGUI::TextBox* mArmorRating; @@ -50,6 +52,8 @@ namespace MWGui void onAvatarClicked(MyGUI::Widget* _sender); void onPinToggled(); + void updateEncumbranceBar(); + virtual bool isInventory() { return true; } virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); From 5a43fe3e5ff3d2d6fedb15d56f43291663dc40d3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 22:48:14 +0200 Subject: [PATCH 080/289] remove debug prints --- apps/openmw/mwgui/container.cpp | 1 - apps/openmw/mwgui/inventorywindow.cpp | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 52714fd22..6d80c16ed 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -235,7 +235,6 @@ void ContainerBase::drawItems() int displayCount = iter->getRefData().getCount(); if (mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) { - std::cout << "beep" << std::endl; displayCount -= mDragAndDrop->mDraggedCount; } if(displayCount > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 8eb4b7bb1..dbf335e5f 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -154,8 +154,6 @@ 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; - action->execute(); /// \todo scripts @@ -188,8 +186,6 @@ namespace MWGui // 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; } mDragAndDrop->mIsOnDragAndDrop = false; @@ -212,14 +208,8 @@ namespace MWGui 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; From 0f811edb4705c31c930bd11d7bf976319a1ca4dc Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 22:54:28 +0200 Subject: [PATCH 081/289] fixed a bug with dropping items on the ground --- apps/openmw/mwgui/hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index d327653f0..96c971c4e 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -280,7 +280,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); // remove object from the container it was coming from - object.getRefData().setCount(0); + object.getRefData().setCount(object.getRefData().getCount() - mDragAndDrop->mDraggedCount); mDragAndDrop->mDraggedFrom->notifyContentChanged(); mDragAndDrop->mIsOnDragAndDrop = false; From 477f1b42ab48495c320f02a32caa4aa99b994f0c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 May 2012 23:28:04 +0200 Subject: [PATCH 082/289] fixed another item dropping bug --- apps/openmw/mwgui/container.cpp | 11 +++++++++++ apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/hud.cpp | 5 ++++- apps/openmw/mwgui/inventorywindow.cpp | 6 ++++++ apps/openmw/mwgui/inventorywindow.hpp | 1 + 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6d80c16ed..5ae943ea4 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -118,6 +118,17 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) containerStore.add(object); object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); } + else + { + // check that we don't exceed the allowed weight (only for containers, not for inventory) + if (isInventory()) + { + float curWeight = MWWorld::Class::get(mContainer).getEncumbrance(mContainer); + float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); + + + } + } mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index d93cdd187..174f18f9a 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -77,7 +77,7 @@ namespace MWGui void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter - void Update(); + virtual void Update(); void drawItems(); virtual void notifyContentChanged() { } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 96c971c4e..c15801da4 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -269,6 +269,9 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) float mouseX = cursorPosition.left / float(viewSize.width); float mouseY = cursorPosition.top / float(viewSize.height); + int origCount = object.getRefData().getCount(); + object.getRefData().setCount(mDragAndDrop->mDraggedCount); + if (world->canPlaceObject(mouseX, mouseY)) world->placeObject(object, mouseX, mouseY); else @@ -280,7 +283,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); // remove object from the container it was coming from - object.getRefData().setCount(object.getRefData().getCount() - mDragAndDrop->mDraggedCount); + object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); mDragAndDrop->mDraggedFrom->notifyContentChanged(); mDragAndDrop->mIsOnDragAndDrop = false; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index dbf335e5f..a1e73d0ed 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -242,7 +242,13 @@ namespace MWGui } void InventoryWindow::notifyContentChanged() + { + } + + void InventoryWindow::Update() { updateEncumbranceBar(); + + ContainerBase::Update(); } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index c1a36bd56..ae0d80986 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -30,6 +30,7 @@ namespace MWGui void openInventory(); + virtual void Update(); virtual void notifyContentChanged(); protected: From 2fa7ce0c1903fed551da09300f65bc5389416b25 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 00:02:05 +0200 Subject: [PATCH 083/289] equipping works also when the item wasn't in player inventory before. --- apps/openmw/mwgui/inventorywindow.cpp | 39 +++++++++++++++--- apps/openmw/mwworld/containerstore.cpp | 57 +++++++++++++++++++------- apps/openmw/mwworld/containerstore.hpp | 16 +++++++- 3 files changed, 90 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index a1e73d0ed..b3da52b02 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -172,20 +172,47 @@ namespace MWGui { MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - // retrieve iterator to the item MWWorld::ContainerStoreIterator it = invStore.begin(); - for (; it != invStore.end(); ++it) + + if (mDragAndDrop->mDraggedFrom != this) { - if (*it == ptr) + // add item to the player's inventory + int origCount = ptr.getRefData().getCount(); + ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); + it = invStore.add(ptr); + (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); + } + else + { + // retrieve iterator to the item + for (; it != invStore.end(); ++it) { - break; + if (*it == ptr) + { + break; + } } } assert(it != invStore.end()); - // equip the item in the first available slot - invStore.equip(slots.first.front(), it); + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + // if all slots are occupied, replace the last slot + if (slot == --slots.first.end()) + { + invStore.equip(*slot, it); + break; + } + + if (invStore.getSlot(*slot) == invStore.end()) + { + invStore.equip(*slot, it); + break; + } + } } mDragAndDrop->mIsOnDragAndDrop = false; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 2e69de9c3..eca720603 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -76,29 +76,31 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) } // if we got here, this means no stacking - addImpl(ptr); - return end(); + return addImpl(ptr); } -void MWWorld::ContainerStore::addImpl (const Ptr& ptr) +MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr) { + ContainerStoreIterator it = begin(); + switch (getType(ptr)) { - case Type_Potion: potions.list.push_back (*ptr.get()); break; - case Type_Apparatus: appas.list.push_back (*ptr.get()); break; - case Type_Armor: armors.list.push_back (*ptr.get()); break; - case Type_Book: books.list.push_back (*ptr.get()); break; - case Type_Clothing: clothes.list.push_back (*ptr.get()); break; - case Type_Ingredient: ingreds.list.push_back (*ptr.get()); break; - case Type_Light: lights.list.push_back (*ptr.get()); break; - case Type_Lockpick: lockpicks.list.push_back (*ptr.get()); break; - case Type_Miscellaneous: miscItems.list.push_back (*ptr.get()); break; - case Type_Probe: probes.list.push_back (*ptr.get()); break; - case Type_Repair: repairs.list.push_back (*ptr.get()); break; - case Type_Weapon: weapons.list.push_back (*ptr.get()); break; + case Type_Potion: potions.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --potions.list.end()); break; + case Type_Apparatus: appas.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --appas.list.end()); break; + case Type_Armor: armors.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --armors.list.end()); break; + case Type_Book: books.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --books.list.end()); break; + case Type_Clothing: clothes.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --clothes.list.end()); break; + case Type_Ingredient: ingreds.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --ingreds.list.end()); break; + case Type_Light: lights.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lights.list.end()); break; + case Type_Lockpick: lockpicks.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lockpicks.list.end()); break; + case Type_Miscellaneous: miscItems.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --miscItems.list.end()); break; + case Type_Probe: probes.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --probes.list.end()); break; + case Type_Repair: repairs.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --repairs.list.end()); break; + case Type_Weapon: weapons.list.push_back (*ptr.get()); it = ContainerStoreIterator(this, --weapons.list.end()); break; } flagAsModified(); + return it; } void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const ESMS::ESMStore& store) @@ -231,6 +233,31 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor nextType(); } +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Potion), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mPotion(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Apparatus), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mApparatus(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Armor), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mArmor(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Book), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mBook(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Clothing), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mClothing(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Probe), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mProbe(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Repair), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mRepair(iterator){} +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator iterator) + : mType(MWWorld::ContainerStore::Type_Weapon), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mWeapon(iterator){} + void MWWorld::ContainerStoreIterator::incType() { if (mType==0) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 26c9f55a3..96c97415d 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -77,7 +77,7 @@ namespace MWWorld /// @return if stacking happened, return iterator to the item that was stacked against, otherwise end() iterator protected: - void addImpl (const Ptr& ptr); + ContainerStoreIterator addImpl (const Ptr& ptr); ///< Add the item to this container (no stacking) virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2); @@ -143,6 +143,20 @@ namespace MWWorld ContainerStoreIterator (int mask, ContainerStore *container); ///< Begin-iterator + // construct iterator using a CellRefList iterator + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, ESMS::CellRefList::List::iterator); + void incType(); void nextType(); From f8c20ef77f934939a9489fbd7c89f632cf36a9c6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 00:20:24 +0200 Subject: [PATCH 084/289] don't allow putting items into a container if the weight is exceeded. --- apps/openmw/mwgui/container.cpp | 41 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5ae943ea4..b7e0bf8b5 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -107,26 +107,45 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); if (mDragAndDrop->mDraggedFrom != this) { assert(object.getContainerStore() && "Item is not in a container!"); - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - int origCount = object.getRefData().getCount(); - object.getRefData().setCount (mDragAndDrop->mDraggedCount); - containerStore.add(object); - object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); - } - else - { + // check that we don't exceed the allowed weight (only for containers, not for inventory) - if (isInventory()) + if (!isInventory()) { - float curWeight = MWWorld::Class::get(mContainer).getEncumbrance(mContainer); float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); - + // try adding the item, and if weight is exceeded, just remove it again. + int origCount = object.getRefData().getCount(); + object.getRefData().setCount(mDragAndDrop->mDraggedCount); + MWWorld::ContainerStoreIterator it = containerStore.add(object); + + float curWeight = MWWorld::Class::get(mContainer).getEncumbrance(mContainer); + if (curWeight > capacity) + { + it->getRefData().setCount(0); + object.getRefData().setCount(origCount); + // user notification + MWBase::Environment::get().getWindowManager()-> + messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage3")->str, std::vector()); + return; + } + else + { + object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); + } + std::cout << "container weight " << curWeight << "/" << capacity << std::endl; + } + else + { + int origCount = object.getRefData().getCount(); + object.getRefData().setCount (mDragAndDrop->mDraggedCount); + containerStore.add(object); + object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); } } From c5d685c780c119f676c7bcff9dc53aa057f7a1db Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 14:28:57 +0200 Subject: [PATCH 085/289] added an assert --- apps/openmw/mwgui/container.cpp | 6 ++++-- apps/openmw/mwgui/inventorywindow.cpp | 1 + apps/openmw/mwgui/window_manager.cpp | 2 ++ libs/openengine/gui/layout.hpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index b7e0bf8b5..844d5d89a 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -239,7 +239,9 @@ void ContainerBase::drawItems() for (std::vector::iterator it=unwantedItems.begin(); it != unwantedItems.end(); ++it) { - equippedItems.erase(std::find(unwantedItems.begin(), unwantedItems.end(), *it)); + std::vector::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *it); + assert(found != unwantedItems.end()); + equippedItems.erase(found); } // and add the items that are left (= have the correct category) for (std::vector::const_iterator it=equippedItems.begin(); @@ -266,7 +268,7 @@ void ContainerBase::drawItems() if (mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) { displayCount -= mDragAndDrop->mDraggedCount; -} + } if(displayCount > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index b3da52b02..7160fa4f8 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -209,6 +209,7 @@ namespace MWGui if (invStore.getSlot(*slot) == invStore.end()) { + // slot is not occupied invStore.equip(*slot, it); break; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a4788ad3b..5c005835c 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -151,6 +151,8 @@ WindowManager::~WindowManager() delete mToolTips; delete mCharGen; delete mDragAndDrop; + delete mBookWindow; + delete mScrollWindow; cleanupGarbage(); } diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index abcc01753..d9eefe051 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -71,7 +71,7 @@ namespace GUI void shutdown() { - MyGUI::LayoutManager::getInstance().unloadLayout(mListWindowRoot); + MyGUI::Gui::getInstance().destroyWidget(mMainWidget); mListWindowRoot.clear(); } From 6a0cb32b7ee781857cec0fcc4676ce3607bfb339 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 14:30:02 +0200 Subject: [PATCH 086/289] removed unnecessary code --- apps/openmw/mwgui/container.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 844d5d89a..bdb06dd26 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -424,19 +424,16 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) int i=0; for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter) { - if(iter->getRefData().getCount() > 0) + playerStore.add(*iter); + + if (i==0) { - playerStore.add(*iter); - - if (i==0) - { - // play the sound of the first object - std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter); - MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - } - - ++i; + // play the sound of the first object + std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } + + ++i; } containerStore.clear(); From 398a7dc65c0e8875f08d458661639d777abb9488 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 14:32:48 +0200 Subject: [PATCH 087/289] crash fix (hopefully) --- apps/openmw/mwgui/container.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index bdb06dd26..20bef98b9 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -239,8 +239,8 @@ void ContainerBase::drawItems() for (std::vector::iterator it=unwantedItems.begin(); it != unwantedItems.end(); ++it) { - std::vector::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *it); - assert(found != unwantedItems.end()); + std::vector::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) From 9a01e18b29f08eda5a2bb603c30b995df645975c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 15:00:20 +0200 Subject: [PATCH 088/289] fix some MessageBox code that was using deleted pointers sometimes --- apps/openmw/mwgui/messagebox.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index c103bcb8b..a6b9025ce 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -15,6 +15,13 @@ void MessageBoxManager::onFrame (float frameDuration) std::vector::iterator it; for(it = mTimers.begin(); it != mTimers.end();) { + // if this messagebox is already deleted, remove the timer and move on + if (std::find(mMessageBoxes.begin(), mMessageBoxes.end(), it->messageBox) == mMessageBoxes.end()) + { + it = mTimers.erase(it); + continue; + } + it->current += frameDuration; if(it->current >= it->max) { From 9c4243782ee51dca419a617dc3d2677953fcbb17 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 15:17:55 +0200 Subject: [PATCH 089/289] sorting items --- apps/openmw/mwgui/container.cpp | 52 +++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 20bef98b9..8bb3976da 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -26,6 +26,47 @@ using namespace MWGui; using namespace Widgets; +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 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::Tool).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()); + } + } +} + + ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) : mDragAndDrop(dragAndDrop), mFilter(ContainerBase::Filter_All) @@ -251,11 +292,18 @@ void ContainerBase::drawItems() } // now add the regular items + std::vector regularItems; 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) ); + regularItems.push_back(*iter); + } + + // sort them and add + std::sort(regularItems.begin(), regularItems.end(), sortItems); + for (std::vector::const_iterator it=regularItems.begin(); it!=regularItems.end(); ++it) + { + items.push_back( std::make_pair(*it, ItemState_Normal) ); } for (std::vector< std::pair >::const_iterator it=items.begin(); From 0f1e09d2c1959eeb42204d6b888c3108bb369f3f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 16:08:55 +0200 Subject: [PATCH 090/289] make Class::use method return an equip action for equippable items, add sound for equipping --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwclass/armor.cpp | 8 +++ apps/openmw/mwclass/armor.hpp | 5 ++ apps/openmw/mwclass/clothing.cpp | 8 +++ apps/openmw/mwclass/clothing.hpp | 4 ++ apps/openmw/mwclass/weapon.cpp | 8 +++ apps/openmw/mwclass/weapon.hpp | 5 ++ apps/openmw/mwgui/inventorywindow.cpp | 79 +++++++-------------------- apps/openmw/mwworld/actionequip.cpp | 54 ++++++++++++++++++ apps/openmw/mwworld/actionequip.hpp | 21 +++++++ 10 files changed, 133 insertions(+), 60 deletions(-) create mode 100644 apps/openmw/mwworld/actionequip.cpp create mode 100644 apps/openmw/mwworld/actionequip.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 972c7f2e4..c105f28b1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,6 +48,7 @@ add_openmw_dir (mwworld refdata world physicssystem scene globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors cells localscripts customdata weather inventorystore ptr actionopen actionread + actionequip ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index abd351fb4..83c0120c7 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -264,4 +265,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 9842c5020..a63806162 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -61,6 +61,11 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu + }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 181af35cd..11b515faf 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -217,4 +218,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 64b857e26..aba317be0 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -55,6 +55,10 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ab5a57a3d..482d618b0 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -355,4 +356,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 9f9a3c4c8..92d703b4a 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -61,6 +61,11 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu + }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7160fa4f8..9773867ec 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -147,73 +147,32 @@ namespace MWGui { MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData(); - // can the object be equipped? - std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); - if (slots.first.empty()) - { - // can't be equipped, try to use instead - boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); - - action->execute(); - - /// \todo scripts - - // this is necessary for books/scrolls: if they are already in the player's inventory, - // the "Take" button should not be visible. - // NOTE: the take button is "reset" when the window opens, so we can safely do the following - // without screwing up future book windows - if (mDragAndDrop->mWasInInventory) - { - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); - } - } - else + if (mDragAndDrop->mDraggedFrom != this) { + // add item to the player's inventory MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - MWWorld::ContainerStoreIterator it = invStore.begin(); - if (mDragAndDrop->mDraggedFrom != this) - { - // add item to the player's inventory - int origCount = ptr.getRefData().getCount(); - ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); - it = invStore.add(ptr); - (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); - } - else - { - // retrieve iterator to the item - for (; it != invStore.end(); ++it) - { - if (*it == ptr) - { - break; - } - } - } + int origCount = ptr.getRefData().getCount(); + ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); + it = invStore.add(ptr); + (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); + } - assert(it != invStore.end()); + /// \todo scripts - // equip the item in the first free slot - for (std::vector::const_iterator slot=slots.first.begin(); - slot!=slots.first.end(); ++slot) - { - // if all slots are occupied, replace the last slot - if (slot == --slots.first.end()) - { - invStore.equip(*slot, it); - break; - } + boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + + action->execute(); - if (invStore.getSlot(*slot) == invStore.end()) - { - // slot is not occupied - invStore.equip(*slot, it); - break; - } - } + // this is necessary for books/scrolls: if they are already in the player's inventory, + // the "Take" button should not be visible. + // NOTE: the take button is "reset" when the window opens, so we can safely do the following + // without screwing up future book windows + if (mDragAndDrop->mWasInInventory) + { + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); } mDragAndDrop->mIsOnDragAndDrop = false; diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp new file mode 100644 index 000000000..f3bb256fd --- /dev/null +++ b/apps/openmw/mwworld/actionequip.cpp @@ -0,0 +1,54 @@ +#include "actionequip.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwworld/player.hpp" + +namespace MWWorld +{ + ActionEquip::ActionEquip (const MWWorld::Ptr& object) : mObject (object) + { + } + + void ActionEquip::execute () + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(player).getContainerStore(player)); + + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(mObject).getEquipmentSlots(mObject); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) + { + if (*it == mObject) + { + break; + } + } + + assert(it != invStore.end()); + + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + // if all slots are occupied, replace the last slot + if (slot == --slots.first.end()) + { + invStore.equip(*slot, it); + break; + } + + if (invStore.getSlot(*slot) == invStore.end()) + { + // slot is not occupied + invStore.equip(*slot, it); + break; + } + } + } +} + diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp new file mode 100644 index 000000000..6cf3640f8 --- /dev/null +++ b/apps/openmw/mwworld/actionequip.hpp @@ -0,0 +1,21 @@ +#ifndef GAME_MWWORLD_ACTIONEQUIP_H +#define GAME_MWWORLD_ACTIONEQUIP_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class ActionEquip : public Action + { + Ptr mObject; + + public: + /// @param item to equip + ActionEquip (const Ptr& object); + + virtual void execute (); + }; +} + +#endif From 4b5d6ce311f7c31461951ebb7675344931eb30f7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 17:22:25 +0200 Subject: [PATCH 091/289] allow stacking gold --- apps/openmw/mwclass/misc.cpp | 18 +++++++++++----- apps/openmw/mwworld/containerstore.cpp | 29 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 936dc4558..d8e0553b9 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -1,6 +1,8 @@ #include "misc.hpp" +#include + #include #include @@ -142,12 +144,18 @@ namespace MWClass const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); int count = ptr.getRefData().getCount(); - // gold has count both as reference count and as value, multiply them together to get real count - bool isGold = (ref->base->name == store.gameSettings.search("sGold")->str); - if (isGold) - count *= ref->base->data.value; - info.caption = ref->base->name + MWGui::ToolTips::getCountString(count); + bool isGold = (ref->base->name == store.gameSettings.search("sGold")->str); + if (isGold && count == 1) + count = ref->base->data.value; + + std::string countString; + if (!isGold) + countString = MWGui::ToolTips::getCountString(count); + else // gold displays its count also if it's 1. + countString = " (" + boost::lexical_cast(count) + ")"; + + info.caption = ref->base->name + countString; info.icon = ref->base->icon; if (ref->ref.soul != "") diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index eca720603..9b5afea74 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -7,6 +7,9 @@ #include +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + #include "manualref.hpp" #include "refdata.hpp" #include "class.hpp" @@ -62,6 +65,32 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) { int type = getType(ptr); + // gold needs special treatment because it uses several different meshes + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + ESMS::LiveCellRef *gold = + ptr.get(); + + int goldValue = (ptr.getRefData().getCount() == 1) ? gold->base->data.value : ptr.getRefData().getCount(); + + for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) + { + if (MWWorld::Class::get(*iter).getName(*iter) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + ESMS::LiveCellRef *ref = + iter->get(); + + if (iter->getRefData().getCount() == 1) + iter->getRefData().setCount(ref->base->data.value + goldValue); + else + iter->getRefData().setCount(iter->getRefData().getCount() + goldValue); + + flagAsModified(); + return iter; + } + } + } + // determine whether to stack or not for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { From 6d34e61dbd2d34a25d7194ea5507048747d7ea38 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 19:18:50 +0200 Subject: [PATCH 092/289] don't stack gold if it has a script (not used in MW, but some mods might) --- apps/openmw/mwworld/containerstore.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 9b5afea74..5dfc9a177 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -75,7 +75,8 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (MWWorld::Class::get(*iter).getName(*iter) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + if (MWWorld::Class::get(*iter).getName(*iter) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str + && MWWorld::Class::get(*iter).getScript(*iter) == "" && MWWorld::Class::get(ptr).getScript(ptr) == "") { ESMS::LiveCellRef *ref = iter->get(); @@ -89,6 +90,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) return iter; } } + + // if we get here, no already existing gold was found in the container + // we still need special handling because gold in a container should always have the real gold value as reference count. + ptr.getRefData().setCount(goldValue); } // determine whether to stack or not From f73d3ad33fa79fd99ce49ce549a98e313de48f4b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 21:27:02 +0200 Subject: [PATCH 093/289] fix to the "drop object on ground" feature. still crashes for gold. --- apps/openmw/mwworld/scene.cpp | 91 ++++++++++++++++++++++++++++------- apps/openmw/mwworld/world.cpp | 24 ++++++++- 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 1d4f078d5..311f8770b 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -328,41 +328,96 @@ namespace MWWorld void Scene::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell) { - ptr.mCell = cell; - - mRendering.addObject(ptr); - MWWorld::Class::get(ptr).insertObject(ptr, *mPhysics); - MWWorld::Class::get(ptr).enable(ptr); - std::string type = ptr.getTypeName(); + MWWorld::Ptr newPtr; + // insert into the correct CellRefList if (type == typeid(ESM::Potion).name()) - cell->potions.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->potions.list.push_back( *ref ); + } else if (type == typeid(ESM::Apparatus).name()) - cell->appas.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->appas.list.push_back( *ref ); + } else if (type == typeid(ESM::Armor).name()) - cell->armors.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->armors.list.push_back( *ref ); + } else if (type == typeid(ESM::Book).name()) - cell->books.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->books.list.push_back( *ref ); + } else if (type == typeid(ESM::Clothing).name()) - cell->clothes.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->clothes.list.push_back( *ref ); + } else if (type == typeid(ESM::Ingredient).name()) - cell->ingreds.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->ingreds.list.push_back( *ref ); + } else if (type == typeid(ESM::Light).name()) - cell->lights.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->lights.list.push_back( *ref ); + } else if (type == typeid(ESM::Tool).name()) - cell->lockpicks.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->lockpicks.list.push_back( *ref ); + } else if (type == typeid(ESM::Repair).name()) - cell->repairs.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->repairs.list.push_back( *ref ); + } else if (type == typeid(ESM::Probe).name()) - cell->probes.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->probes.list.push_back( *ref ); + } else if (type == typeid(ESM::Weapon).name()) - cell->weapons.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(ref, cell); + cell->weapons.list.push_back( *ref ); + } else if (type == typeid(ESM::Miscellaneous).name()) - cell->miscItems.list.push_back( *ptr.get() ); + { + ESMS::LiveCellRef* ref = ptr.get(); + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + } else throw std::runtime_error("Trying to insert object of unhandled type"); + + + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + + mRendering.addObject(newPtr); + MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); + MWWorld::Class::get(newPtr).enable(newPtr); + } } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 973407b0c..0672d5f3b 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -21,7 +21,7 @@ #include "class.hpp" #include "player.hpp" #include "weather.hpp" - +#include "manualref.hpp" #include "refdata.hpp" #include "globals.hpp" #include "cellfunctors.hpp" @@ -982,6 +982,28 @@ namespace MWWorld else cell = getPlayer().getPlayer().getCell(); + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(object).getName(object) == getStore().gameSettings.search("sGold")->str) + { + int goldAmount = object.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 5) + base = "Gold_005"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 100) + base = "Gold_100"; + + std::cout << "using " << base << std::endl; + MWWorld::ManualRef newRef (getStore(), base); + object = newRef.getPtr(); + object.getRefData().setCount(goldAmount); + object.mCell = cell; + } + ESM::Position& pos = object.getRefData().getPosition(); pos.pos[0] = result.second[0]; pos.pos[1] = -result.second[2]; From 5875ce51286fca173550d8ddea8c880ecac7710f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 22:13:56 +0200 Subject: [PATCH 094/289] select the correct gold base object (still crashing) --- apps/openmw/mwworld/world.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 0672d5f3b..2f8deeff9 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -988,20 +988,19 @@ namespace MWWorld int goldAmount = object.getRefData().getCount(); std::string base = "Gold_001"; - if (goldAmount >= 5) - base = "Gold_005"; - else if (goldAmount >= 10) - base = "Gold_010"; + if (goldAmount >= 100) + base = "Gold_100"; else if (goldAmount >= 25) base = "Gold_025"; - else if (goldAmount >= 100) - base = "Gold_100"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; std::cout << "using " << base << std::endl; MWWorld::ManualRef newRef (getStore(), base); object = newRef.getPtr(); object.getRefData().setCount(goldAmount); - object.mCell = cell; } ESM::Position& pos = object.getRefData().getPosition(); From 178ad876d74acc405026e604c780f391f56bcbcc Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 22:17:13 +0200 Subject: [PATCH 095/289] fix for objects other than Miscellaneous. --- apps/openmw/mwworld/scene.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 311f8770b..8fa7658c6 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -336,68 +336,68 @@ namespace MWWorld if (type == typeid(ESM::Potion).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->potions.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); } else if (type == typeid(ESM::Apparatus).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->appas.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); } else if (type == typeid(ESM::Armor).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->armors.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); } else if (type == typeid(ESM::Book).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->books.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); } else if (type == typeid(ESM::Clothing).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->clothes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); } else if (type == typeid(ESM::Ingredient).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->ingreds.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); } else if (type == typeid(ESM::Light).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->lights.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); } else if (type == typeid(ESM::Tool).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->lockpicks.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); } else if (type == typeid(ESM::Repair).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->repairs.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); } else if (type == typeid(ESM::Probe).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->probes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); } else if (type == typeid(ESM::Weapon).name()) { ESMS::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(ref, cell); cell->weapons.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); } else if (type == typeid(ESM::Miscellaneous).name()) { From fca9f1fc5f29de49e4767656b61e819d0f9da941 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 May 2012 22:56:54 +0200 Subject: [PATCH 096/289] gold dropping works without crash, but the code needs clean up. --- apps/openmw/mwworld/scene.cpp | 43 ++++++++++++++++++++++++++++++++--- apps/openmw/mwworld/world.cpp | 21 ----------------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 8fa7658c6..af7e21d7f 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -9,6 +9,9 @@ #include "../mwgui/window_manager.hpp" +#include "../mwworld/world.hpp" /// FIXME +#include "../mwworld/manualref.hpp" /// FIXME + #include "ptr.hpp" #include "player.hpp" #include "class.hpp" @@ -326,6 +329,8 @@ namespace MWWorld insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); } + + /// \todo this whole code needs major clean up, and doesn't belong in this class. void Scene::insertObject(MWWorld::Ptr ptr, Ptr::CellStore* cell) { std::string type = ptr.getTypeName(); @@ -401,9 +406,41 @@ namespace MWWorld } else if (type == typeid(ESM::Miscellaneous).name()) { - ESMS::LiveCellRef* ref = ptr.get(); - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); + + ESMS::LiveCellRef* ref = newRef.getPtr().get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + + ESM::Position& p = newPtr.getRefData().getPosition(); + p.pos[0] = ptr.getRefData().getPosition().pos[0]; + p.pos[1] = ptr.getRefData().getPosition().pos[1]; + p.pos[2] = ptr.getRefData().getPosition().pos[2]; + } + else + { + ESMS::LiveCellRef* ref = ptr.get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + } } else throw std::runtime_error("Trying to insert object of unhandled type"); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 2f8deeff9..b324ee1a0 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -982,27 +982,6 @@ namespace MWWorld else cell = getPlayer().getPlayer().getCell(); - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(object).getName(object) == getStore().gameSettings.search("sGold")->str) - { - int goldAmount = object.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - std::cout << "using " << base << std::endl; - MWWorld::ManualRef newRef (getStore(), base); - object = newRef.getPtr(); - object.getRefData().setCount(goldAmount); - } - ESM::Position& pos = object.getRefData().getPosition(); pos.pos[0] = result.second[0]; pos.pos[1] = -result.second[2]; From c5185cf2e4f750845594986e0ee87edf74148e22 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 12:09:53 +0200 Subject: [PATCH 097/289] drop item on avatar from external container bugfix --- apps/openmw/mwgui/container.cpp | 2 -- apps/openmw/mwgui/container.hpp | 6 ------ apps/openmw/mwgui/inventorywindow.cpp | 3 ++- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8bb3976da..3656a8919 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -136,8 +136,6 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) static_cast(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption( getCountString(mDragAndDrop->mDraggedCount)); - mDragAndDrop->mWasInInventory = isInventory(); - drawItems(); MWBase::Environment::get().getWindowManager()->setDragDrop(true); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 174f18f9a..fe4ffc285 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -36,17 +36,11 @@ namespace MWGui class DragAndDrop { public: - DragAndDrop() : - mWasInInventory(false) - { - } - bool mIsOnDragAndDrop; MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDragAndDropWidget; ContainerBase* mDraggedFrom; int mDraggedCount; - bool mWasInInventory; // was the item in inventory before it was dragged }; class ContainerBase diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 9773867ec..4f16152ea 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -157,6 +157,7 @@ namespace MWGui ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); it = invStore.add(ptr); (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); + ptr = *it; } /// \todo scripts @@ -169,7 +170,7 @@ namespace MWGui // the "Take" button should not be visible. // NOTE: the take button is "reset" when the window opens, so we can safely do the following // without screwing up future book windows - if (mDragAndDrop->mWasInInventory) + if (mDragAndDrop->mDraggedFrom == this) { mWindowManager.getBookWindow()->setTakeButtonShow(false); mWindowManager.getScrollWindow()->setTakeButtonShow(false); From 8cc49ae2b9a0976a8b88ace36c9710010bbb873b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 12:55:48 +0200 Subject: [PATCH 098/289] xml files update (layout tweak, added double quotation marks to font) --- files/mygui/openmw.font.xml | 1 + files/mygui/openmw_container_window_layout.xml | 6 +++--- files/mygui/openmw_inventory_window_layout.xml | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/files/mygui/openmw.font.xml b/files/mygui/openmw.font.xml index 252499a5f..73d491e04 100644 --- a/files/mygui/openmw.font.xml +++ b/files/mygui/openmw.font.xml @@ -13,6 +13,7 @@ + diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index 7b14f5b58..cb66fadc1 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -5,9 +5,9 @@ - - - + + + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index cd6e1469e..4d63b03c2 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -27,8 +27,9 @@ - - + + + From 630241c8e2c95c6c0ab01ea681e3cb6c796653ca Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 13:12:38 +0200 Subject: [PATCH 099/289] load the AIDT (AI data) for creatures in the ESM loader, which also contains the Services enum. --- apps/openmw/mwgui/dialogue.cpp | 2 ++ apps/openmw/mwgui/list.cpp | 7 ------- apps/openmw/mwgui/list.hpp | 2 +- components/esm/loadcrea.cpp | 12 +++++++++--- components/esm/loadcrea.hpp | 12 ++++++++++++ 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 45163017a..1116eb272 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -145,6 +145,7 @@ void DialogueWindow::setKeywords(std::list keyWords) { topicsList->addItem(*it); } + topicsList->adjustSize(); } void DialogueWindow::removeKeyword(std::string keyWord) @@ -154,6 +155,7 @@ void DialogueWindow::removeKeyword(std::string keyWord) topicsList->removeItem(keyWord); pTopicsText.erase(keyWord); } + topicsList->adjustSize(); } void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2) diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index d66cc6f89..33f5a6fd1 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -28,8 +28,6 @@ void MWList::initialiseOverride() void MWList::addItem(const std::string& name) { mItems.push_back(name); - - redraw(); } void MWList::adjustSize() @@ -67,7 +65,6 @@ void MWList::redraw(bool scrollbarShown) mItemHeight += height + spacing; } mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height)); - mScrollView->setViewOffset(MyGUI::IntPoint(0,0)); if (!scrollbarShown && mItemHeight > mClient->getSize().height) redraw(true); @@ -93,15 +90,11 @@ void MWList::removeItem(const std::string& name) { assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() ); mItems.erase( std::find(mItems.begin(), mItems.end(), name) ); - - redraw(); } void MWList::clear() { mItems.clear(); - - redraw(); } void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel) diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index a2e9afcd1..76ca5257f 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -26,7 +26,7 @@ namespace MWGui EventHandle_String eventItemSelected; /** - * Call after the size of the list changed + * Call after the size of the list changed, or items were inserted/removed */ void adjustSize(); diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 651d9a318..8af3526a0 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -19,9 +19,15 @@ void Creature::load(ESMReader &esm, const std::string& id) inventory.load(esm); - // More subrecords: + if (esm.isNextSub("AIDT")) + { + esm.getHExact(&AI, sizeof(AI)); + hasAI = true; + } + else + hasAI = false; - // AIDT - data (12 bytes, unknown) + // More subrecords: // AI_W - wander (14 bytes, i don't understand it) // short distance // byte duration @@ -33,8 +39,8 @@ void Creature::load(ESMReader &esm, const std::string& id) // AI_F - follow? // AI_E - escort? // AI_A - activate? - esm.skipRecord(); + } } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 3c334ebbd..c3c5b181e 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -51,6 +51,15 @@ struct Creature int gold; }; // 96 bytes + struct AIDTstruct + { + // These are probabilities + char hello, u1, fight, flee, alarm, u2, u3, u4; + // The last u's might be the skills that this NPC can train you + // in? + int services; // See the NPC::Services enum + }; // 12 bytes + NPDTstruct data; int flags; @@ -61,6 +70,9 @@ struct Creature // Defined in loadcont.hpp InventoryList inventory; + bool hasAI; + AIDTstruct AI; + std::string mId; void load(ESMReader &esm, const std::string& id); From 1fddbf9a4034fc83717e05608c9c5d3a1becd3b8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 May 2012 13:15:31 +0200 Subject: [PATCH 100/289] Issue #256: moved dynamic stats update from MechanicsManager to Actors --- apps/openmw/mwmechanics/actors.cpp | 19 +++++++++++++++++++ apps/openmw/mwmechanics/mechanicsmanager.cpp | 17 ----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 849ab8ea4..d7e879b22 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -8,11 +8,30 @@ #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" +#include "creaturestats.hpp" + namespace MWMechanics { void Actors::updateActor (const MWWorld::Ptr& ptr, float duration) { + MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + // calculate dynamic stats + int strength = creatureStats.mAttributes[0].getBase(); + int intelligence = creatureStats.mAttributes[1].getBase(); + int willpower = creatureStats.mAttributes[2].getBase(); + int agility = creatureStats.mAttributes[3].getBase(); + int endurance = creatureStats.mAttributes[5].getBase(); + + double magickaFactor = creatureStats.mMagicEffects.get (EffectKey (84)).mMagnitude*0.1 + 0.5; + + creatureStats.mDynamic[0].setBase (static_cast (0.5 * (strength + endurance))); + creatureStats.mDynamic[1].setBase (static_cast (intelligence + + magickaFactor * intelligence)); + creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance); + + for (int i=0; i<3; ++i) + creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified()); } void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 8bc408be6..073604b01 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -141,23 +141,6 @@ namespace MWMechanics // magic effects adjustMagicEffects (ptr); - - // calculate dynamic stats - int strength = creatureStats.mAttributes[0].getBase(); - int intelligence = creatureStats.mAttributes[1].getBase(); - int willpower = creatureStats.mAttributes[2].getBase(); - int agility = creatureStats.mAttributes[3].getBase(); - int endurance = creatureStats.mAttributes[5].getBase(); - - double magickaFactor = creatureStats.mMagicEffects.get (EffectKey (84)).mMagnitude*0.1 + 0.5; - - creatureStats.mDynamic[0].setBase (static_cast (0.5 * (strength + endurance))); - creatureStats.mDynamic[1].setBase (static_cast (intelligence + - magickaFactor * intelligence)); - creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance); - - for (int i=0; i<3; ++i) - creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified()); } void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature) From e56ff9283dfa6849ebb9caeb6758065ff39a5cc6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 May 2012 13:21:49 +0200 Subject: [PATCH 101/289] Issue #256: moved magic effects update from MechanicsManager to Actors --- apps/openmw/mwmechanics/actors.cpp | 20 +++++++++++++++++++- apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwmechanics/mechanicsmanager.cpp | 18 ------------------ apps/openmw/mwmechanics/mechanicsmanager.hpp | 2 -- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d7e879b22..b0bb1e3ef 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -14,7 +14,10 @@ namespace MWMechanics { void Actors::updateActor (const MWWorld::Ptr& ptr, float duration) { - MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + // magic effects + adjustMagicEffects (ptr); + + CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); // calculate dynamic stats int strength = creatureStats.mAttributes[0].getBase(); @@ -41,6 +44,21 @@ namespace MWMechanics MWWorld::Class::get (ptr).getNpcStats (ptr)); } + void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) + { + CreatureStats& creatureStats = MWWorld::Class::get (creature).getCreatureStats (creature); + + MagicEffects now = creatureStats.mSpells.getMagicEffects(); + + /// \todo add effects from active spells and equipment + + MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now); + + creatureStats.mMagicEffects = now; + + // TODO apply diff to other stats + } + Actors::Actors() : mDuration (0) {} void Actors::addActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index ae93fb52e..37a00deec 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -23,6 +23,8 @@ namespace MWMechanics void updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused); + void adjustMagicEffects (const MWWorld::Ptr& creature); + public: Actors(); diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 073604b01..66a850b05 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -138,26 +138,8 @@ namespace MWMechanics } } } - - // magic effects - adjustMagicEffects (ptr); } - void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature) - { - MWMechanics::CreatureStats& creatureStats = - MWWorld::Class::get (creature).getCreatureStats (creature); - - MagicEffects now = creatureStats.mSpells.getMagicEffects(); - - /// \todo add effects from active spells and equipment - - MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now); - - creatureStats.mMagicEffects = now; - - // TODO apply diff to other stats - } MechanicsManager::MechanicsManager() : mUpdatePlayer (true), mClassSelected (false), diff --git a/apps/openmw/mwmechanics/mechanicsmanager.hpp b/apps/openmw/mwmechanics/mechanicsmanager.hpp index a26fb98cd..62bb4cf7e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.hpp @@ -31,8 +31,6 @@ namespace MWMechanics ///< build player according to stored class/race/birthsign information. Will /// default to the values of the ESM::NPC object, if no explicit information is given. - void adjustMagicEffects (MWWorld::Ptr& creature); - public: MechanicsManager (); From 0c1d06d9f767b3860886478d61beb18f4da8fb63 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 13:36:25 +0200 Subject: [PATCH 102/289] added some trade window stuff, which does nothing yet. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 18 +--------- apps/openmw/mwgui/tradewindow.cpp | 10 ++++++ apps/openmw/mwgui/tradewindow.hpp | 41 ++++++++++++++++++++++ apps/openmw/mwgui/window_manager.hpp | 2 ++ files/mygui/openmw_trade_window_layout.xml | 24 +++++++++++++ 6 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 apps/openmw/mwgui/tradewindow.cpp create mode 100644 apps/openmw/mwgui/tradewindow.hpp create mode 100644 files/mygui/openmw_trade_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c105f28b1..9e5aeb684 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -26,7 +26,7 @@ add_openmw_dir (mwgui text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list - formatting itemwidget inventorywindow container hud countdialog + formatting itemwidget inventorywindow container hud countdialog tradewindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index ae0d80986..07aeeeafd 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -4,23 +4,6 @@ #include "container.hpp" #include "window_pinnable_base.hpp" -namespace MWWorld -{ - class Environment; -} - -namespace MyGUI -{ - class Gui; - class Widget; -} - -namespace MWGui -{ - class WindowManager; -} - - namespace MWGui { class InventoryWindow : public ContainerBase, public WindowPinnableBase @@ -60,4 +43,5 @@ namespace MWGui virtual void _unequipItem(MWWorld::Ptr item); }; } + #endif // Inventory_H diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp new file mode 100644 index 000000000..45a82eecb --- /dev/null +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -0,0 +1,10 @@ +#include "tradewindow.hpp" + +namespace MWGui +{ + TradeWindow::TradeWindow(WindowManager& parWindowManager) : + WindowBase("openmw_trade_window_layout.xml", parWindowManager), + ContainerBase(NULL) // no drag&drop + { + } +} diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp new file mode 100644 index 000000000..f04f83c0d --- /dev/null +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -0,0 +1,41 @@ +#ifndef MWGUI_TRADEWINDOW_H +#define MWGUI_TRADEWINDOW_H + +#include "container.hpp" +#include "window_base.hpp" + +namespace MyGUI +{ + class Gui; + class Widget; +} + +namespace MWGui +{ + class WindowManager; +} + + +namespace MWGui +{ + class TradeWindow : public ContainerBase, public WindowBase + { + public: + TradeWindow(WindowManager& parWindowManager); + + //virtual void Update(); + //virtual void notifyContentChanged(); + + protected: + MyGUI::Button* mFilterAll; + MyGUI::Button* mFilterWeapon; + MyGUI::Button* mFilterApparel; + MyGUI::Button* mFilterMagic; + MyGUI::Button* mFilterMisc; + + void onWindowResize(MyGUI::Window* _sender); + void onFilterChanged(MyGUI::Widget* _sender); + }; +} + +#endif diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 3f5df5789..8c9eec16d 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -72,6 +72,7 @@ namespace MWGui class DialogueWindow; class MessageBoxManager; class CountDialog; + class TradeWindow; struct ClassPoint { @@ -226,6 +227,7 @@ namespace MWGui ScrollWindow* mScrollWindow; BookWindow* mBookWindow; CountDialog* mCountDialog; + TradeWindow* mTradeWindow; CharacterCreation* mCharGen; diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml new file mode 100644 index 000000000..e5c45cdd0 --- /dev/null +++ b/files/mygui/openmw_trade_window_layout.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + From 66abfd17abd7719a7f5eae985e869802b0652604 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 14:13:35 +0200 Subject: [PATCH 103/289] check the container's "Organic" flag before trying to place items inside. --- apps/openmw/mwgui/container.cpp | 18 +++++++++++++++--- apps/openmw/mwgui/hud.cpp | 5 +++++ apps/openmw/mwgui/hud.hpp | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 3656a8919..978e10fc4 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -143,7 +143,7 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { - if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here + if(mDragAndDrop->mIsOnDragAndDrop) //drop item here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); @@ -152,6 +152,20 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { 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 (mContainer.getTypeName() == typeid(ESM::Container).name()) + { + ESMS::LiveCellRef* ref = mContainer.get(); + if (ref->base->flags & ESM::Container::Organic) + { + // user notification + MWBase::Environment::get().getWindowManager()-> + messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage2")->str, std::vector()); + return; + } + } + + int origCount = object.getRefData().getCount(); // check that we don't exceed the allowed weight (only for containers, not for inventory) if (!isInventory()) @@ -159,7 +173,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); // try adding the item, and if weight is exceeded, just remove it again. - int origCount = object.getRefData().getCount(); object.getRefData().setCount(mDragAndDrop->mDraggedCount); MWWorld::ContainerStoreIterator it = containerStore.add(object); @@ -181,7 +194,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) } else { - int origCount = object.getRefData().getCount(); object.getRefData().setCount (mDragAndDrop->mDraggedCount); containerStore.add(object); object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index c15801da4..395ca79c5 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -92,6 +92,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); + mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus); } void HUD::setFpsLevel(int level) @@ -321,3 +322,7 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) } } +void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) +{ + MyGUI::PointerManager::getInstance().setPointer("arrow"); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index cccfb0541..d588113dd 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -53,5 +53,6 @@ namespace MWGui void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); + void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); }; } From 0dc5e5919b11906d69fde2ec9a7a253f15c8900d Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 14:54:03 +0200 Subject: [PATCH 104/289] show the Barter entry in the dialogue gui for npcs/creatures that buy/sell stuff. doesn't work for the Creeper for some reason, but Mudcrab Merchant works. --- apps/openmw/mwdialogue/dialoguemanager.cpp | 30 +++++++++++++++++ apps/openmw/mwgui/dialogue.cpp | 13 +++++++- apps/openmw/mwgui/dialogue.hpp | 7 ++++ apps/openmw/mwgui/list.cpp | 39 ++++++++++++++++------ apps/openmw/mwgui/list.hpp | 3 +- 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 7baf589c4..496cc4f7f 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -767,6 +767,36 @@ namespace MWDialogue } } + // check the available services of this actor + int services = 0; + if (mActor.getTypeName() == typeid(ESM::NPC).name()) + { + ESMS::LiveCellRef* ref = mActor.get(); + if (ref->base->hasAI) + services = ref->base->AI.services; + } + else if (mActor.getTypeName() == typeid(ESM::Creature).name()) + { + ESMS::LiveCellRef* ref = mActor.get(); + if (ref->base->hasAI) + services = ref->base->AI.services; + } + + if (services & ESM::NPC::Weapon + || services & ESM::NPC::Armor + || services & ESM::NPC::Clothing + || services & ESM::NPC::Books + || services & ESM::NPC::Ingredients + || services & ESM::NPC::Picks + || services & ESM::NPC::Probes + || services & ESM::NPC::Lights + || services & ESM::NPC::Apparatus + || services & ESM::NPC::RepairItem + || services & ESM::NPC::Misc) + win->setShowTrade(true); + else + win->setShowTrade(false); + // sort again, because the previous sort was case-sensitive keywordList.sort(stringCompareNoCase); win->setKeywords(keywordList); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 1116eb272..3f6ec0376 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -40,6 +40,7 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su DialogueWindow::DialogueWindow(WindowManager& parWindowManager) : WindowBase("openmw_dialogue_window_layout.xml", parWindowManager) , mEnabled(true) + , mShowTrade(false) { // Centre dialog center(); @@ -141,6 +142,15 @@ void DialogueWindow::startDialogue(std::string npcName) void DialogueWindow::setKeywords(std::list keyWords) { topicsList->clear(); + + bool anyService = mShowTrade; + + if (mShowTrade) + topicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str); + + if (anyService) + topicsList->addSeparator(); + for(std::list::iterator it = keyWords.begin(); it != keyWords.end(); it++) { topicsList->addItem(*it); @@ -194,7 +204,8 @@ std::string DialogueWindow::parseText(std::string text) for(unsigned int i = 0;igetItemCount();i++) { std::string keyWord = topicsList->getItemNameAt(i); - addColorInString(text,keyWord,"#686EBA","#B29154"); + if (keyWord != "") + addColorInString(text,keyWord,"#686EBA","#B29154"); } return text; } diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index a29e73799..225ef37a4 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -47,6 +47,10 @@ namespace MWGui void askQuestion(std::string question); void goodbye(); + // various service button visibilities, depending if the npc/creature talked to has these services + // make sure to call these before setKeywords() + void setShowTrade(bool show) { mShowTrade = show; } + protected: void onSelectTopic(std::string topic); void onByeClicked(MyGUI::Widget* _sender); @@ -61,6 +65,9 @@ namespace MWGui */ std::string parseText(std::string text); + // various service button visibilities, depending if the npc/creature talked to has these services + bool mShowTrade; + bool mEnabled; DialogueHistory* history; diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index 33f5a6fd1..661fb2e68 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -30,6 +30,11 @@ void MWList::addItem(const std::string& name) mItems.push_back(name); } +void MWList::addSeparator() +{ + mItems.push_back(""); +} + void MWList::adjustSize() { redraw(); @@ -50,19 +55,31 @@ void MWList::redraw(bool scrollbarShown) for (std::vector::const_iterator it=mItems.begin(); it!=mItems.end(); ++it) { - MyGUI::Button* button = mScrollView->createWidget( - "MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), - MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it)); - button->setCaption((*it)); - button->getSubWidgetText()->setWordWrap(true); - button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left); - button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel); - button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected); + if (*it != "") + { + MyGUI::Button* button = mScrollView->createWidget( + "MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), + MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it)); + button->setCaption((*it)); + button->getSubWidgetText()->setWordWrap(true); + button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left); + button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel); + button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected); - int height = button->getTextSize().height; - button->setSize(MyGUI::IntSize(button->getSize().width, height)); + int height = button->getTextSize().height; + button->setSize(MyGUI::IntSize(button->getSize().width, height)); - mItemHeight += height + spacing; + mItemHeight += height + spacing; + } + else + { + MyGUI::ImageBox* separator = mScrollView->createWidget("MW_HLine", + MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth()-4, 18), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + separator->setNeedMouseFocus(false); + + mItemHeight += 18 + spacing; + } } mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height)); diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index 76ca5257f..2b765c2e1 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -31,10 +31,11 @@ namespace MWGui void adjustSize(); void addItem(const std::string& name); + void addSeparator(); ///< add a seperator between the current and the next item. void removeItem(const std::string& name); bool hasItem(const std::string& name); unsigned int getItemCount(); - std::string getItemNameAt(unsigned int at); + std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is void clear(); protected: From 6f87493df664996c7d4b07ba6b708dec45afad76 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 17 May 2012 15:46:38 +0200 Subject: [PATCH 105/289] fix collision bug i think. It disable collision for quiet a lot of objects (maybe a little to much) --- components/nifbullet/bullet_nif_loader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index e9aa626db..30cb4562d 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -139,6 +139,8 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,true); } + cShape->collide = hasCollisionNode&&cShape->collide; + struct TriangleMeshShape : public btBvhTriangleMeshShape { TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression) From 09ec1da0f6c02cdc5bc5ae3fc8707939525651b3 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 17 May 2012 16:12:55 +0200 Subject: [PATCH 106/289] fix the latest commit: objects activation works again. --- libs/openengine/bullet/physic.cpp | 41 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 42853d8cf..d30d5e9f1 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -22,7 +22,8 @@ namespace Physic COL_NOTHING = 0, //collide = shape->collide; return body; + } void PhysicEngine::addRigidBody(RigidBody* body) { - if(body->collide) + if(body) { - dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); - } - else - { - dynamicsWorld->addRigidBody(body,COL_WORLD,COL_NOTHING); - } - body->setActivationState(DISABLE_DEACTIVATION); - RigidBody* oldBody = RigidBodyMap[body->mName]; - if (oldBody != NULL) - { - dynamicsWorld->removeRigidBody(oldBody); - delete oldBody; - } + if(body->collide) + { + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + } + else + { + dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD); + } + body->setActivationState(DISABLE_DEACTIVATION); + RigidBody* oldBody = RigidBodyMap[body->mName]; + if (oldBody != NULL) + { + dynamicsWorld->removeRigidBody(oldBody); + delete oldBody; + } - RigidBodyMap[body->mName] = body; + RigidBodyMap[body->mName] = body; + } } void PhysicEngine::removeRigidBody(std::string name) @@ -460,7 +465,7 @@ namespace Physic float d1 = 10000.; btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); - resultCallback1.m_collisionFilterMask = COL_WORLD; + resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; dynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { @@ -489,7 +494,7 @@ namespace Physic std::vector< std::pair > PhysicEngine::rayTest2(btVector3& from, btVector3& to) { MyRayResultCallback resultCallback1; - resultCallback1.m_collisionFilterMask = COL_WORLD; + resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; dynamicsWorld->rayTest(from, to, resultCallback1); std::vector< std::pair > results = resultCallback1.results; From 6b74fec8ed4def2da942b57e6f836af94f369890 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 May 2012 17:13:41 +0200 Subject: [PATCH 107/289] don't do a half finished cell change, when trying to switch to an interior cell that does not exist --- apps/openmw/mwworld/scene.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 6f9f3ed3e..caaef5264 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -251,6 +251,9 @@ namespace MWWorld void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { std::cout << "Changing to interior\n"; + + Ptr::CellStore *cell = mWorld->getInterior(cellName); + // remove active CellStoreCollection::iterator active = mActiveCells.begin(); @@ -261,11 +264,9 @@ namespace MWWorld // Load cell. std::cout << "cellName:" << cellName << std::endl; - Ptr::CellStore *cell = mWorld->getInterior(cellName); loadCell (cell); - // adjust player mCurrentCell = cell; playerCellChange (cell, position); From 5da4da820e41df0d9fde8ef585188460db58140a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 17:15:44 +0200 Subject: [PATCH 108/289] beginnings of trade window layout. --- apps/openmw/mwdialogue/dialoguemanager.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 35 +++++++++++++++------- apps/openmw/mwgui/dialogue.hpp | 6 +++- apps/openmw/mwgui/tradewindow.cpp | 5 ++++ apps/openmw/mwgui/tradewindow.hpp | 4 +++ apps/openmw/mwgui/window_manager.cpp | 4 +++ apps/openmw/mwgui/window_manager.hpp | 1 + files/mygui/CMakeLists.txt | 1 + 8 files changed, 45 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 496cc4f7f..2c4de7be1 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -637,7 +637,7 @@ namespace MWDialogue //initialise the GUI MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Dialogue); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - win->startDialogue(MWWorld::Class::get (actor).getName (actor)); + win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI updateTopics(); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 3f6ec0376..953657565 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -1,11 +1,4 @@ #include "dialogue.hpp" -#include "dialogue_history.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "list.hpp" -#include "components/esm_store/store.hpp" -#include "../mwbase/environment.hpp" -#include "../mwdialogue/dialoguemanager.hpp" #include #include @@ -14,6 +7,17 @@ #include #include +#include + +#include "../mwbase/environment.hpp" +#include "../mwdialogue/dialoguemanager.hpp" + +#include "dialogue_history.hpp" +#include "window_manager.hpp" +#include "widgets.hpp" +#include "list.hpp" +#include "tradewindow.hpp" + using namespace MWGui; using namespace Widgets; @@ -59,9 +63,7 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager) //Topics list getWidget(topicsList, "TopicsList"); - //topicsList->eventListSelectAccept += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); topicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); - //topicsList->eventListChangePosition += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); MyGUI::ButtonPtr byeButton; getWidget(byeButton, "ByeButton"); @@ -117,6 +119,9 @@ void DialogueWindow::open() history->eraseText(0,history->getTextLength()); updateOptions(); setVisible(true); + + // hide all sub-dialogues of the dialog window (trade window, persuasion, etc) + mWindowManager.getTradeWindow()->setVisible(false); } void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) @@ -128,12 +133,20 @@ void DialogueWindow::onSelectTopic(std::string topic) { if (!mEnabled) return; - MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic)); + if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) + { + /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? + mWindowManager.getTradeWindow()->startTrade(mActor); + } + + else + MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic)); } -void DialogueWindow::startDialogue(std::string npcName) +void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) { mEnabled = true; + mActor = actor; topicsList->setEnabled(true); static_cast(mMainWidget)->setCaption(npcName); adjustWindowCaption(); diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 225ef37a4..7f69f972c 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -4,6 +4,8 @@ #include "window_base.hpp" #include +#include "../mwworld/ptr.hpp" + namespace MWGui { class WindowManager; @@ -38,7 +40,7 @@ namespace MWGui */ EventHandle_Void eventBye; - void startDialogue(std::string npcName); + void startDialogue(MWWorld::Ptr actor, std::string npcName); void stopDialogue(); void setKeywords(std::list keyWord); void removeKeyword(std::string keyWord); @@ -70,6 +72,8 @@ namespace MWGui bool mEnabled; + MWWorld::Ptr mActor; // actor being talked to + DialogueHistory* history; Widgets::MWList* topicsList; MyGUI::ProgressPtr pDispositionBar; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 45a82eecb..cd38aa731 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -7,4 +7,9 @@ namespace MWGui ContainerBase(NULL) // no drag&drop { } + + void TradeWindow::startTrade(MWWorld::Ptr actor) + { + ContainerBase::openContainer(actor); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index f04f83c0d..5fc5b98b6 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -4,6 +4,8 @@ #include "container.hpp" #include "window_base.hpp" +#include "../mwworld/ptr.hpp" + namespace MyGUI { class Gui; @@ -23,6 +25,8 @@ namespace MWGui public: TradeWindow(WindowManager& parWindowManager); + void startTrade(MWWorld::Ptr actor); + //virtual void Update(); //virtual void notifyContentChanged(); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 5c005835c..245b364c9 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -15,6 +15,7 @@ #include "hud.hpp" #include "mainmenu.hpp" #include "countdialog.hpp" +#include "tradewindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -48,6 +49,7 @@ WindowManager::WindowManager( , mBookWindow(NULL) , mScrollWindow(NULL) , mCountDialog(NULL) + , mTradeWindow(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -114,6 +116,7 @@ WindowManager::WindowManager( mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); + mTradeWindow = new TradeWindow(*this); // The HUD is always on hud->setVisible(true); @@ -153,6 +156,7 @@ WindowManager::~WindowManager() delete mDragAndDrop; delete mBookWindow; delete mScrollWindow; + delete mTradeWindow; cleanupGarbage(); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 8c9eec16d..52869ff55 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -136,6 +136,7 @@ namespace MWGui MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} MWGui::CountDialog* getCountDialog() {return mCountDialog;} + MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MyGUI::Gui* getGui() const { return gui; } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 2ee823d2a..cacfb7c5a 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -56,6 +56,7 @@ configure_file("${SDIR}/openmw_scroll_layout.xml" "${DDIR}/openmw_scroll_layout. configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" COPYONLY) configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) From ae77e7b0d84a0fa92e9a13f558d6ca0bf901efe0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 18:11:34 +0200 Subject: [PATCH 109/289] don't try to retrieve land data from non-predefined cells. --- apps/openmw/mwworld/scene.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index caaef5264..e4236b2f7 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -82,7 +82,11 @@ namespace MWWorld } if (!((*iter)->cell->data.flags & ESM::Cell::Interior)) - mPhysics->removeHeightField( (*iter)->cell->data.gridX, (*iter)->cell->data.gridY ); + { + ESM::Land* land = mWorld->getStore().lands.search((*iter)->cell->data.gridX,(*iter)->cell->data.gridY); + if (land) + mPhysics->removeHeightField( (*iter)->cell->data.gridX, (*iter)->cell->data.gridY ); + } } mRendering.removeCell(*iter); @@ -118,9 +122,10 @@ namespace MWWorld if (!(cell->cell->data.flags & ESM::Cell::Interior)) { ESM::Land* land = mWorld->getStore().lands.search(cell->cell->data.gridX,cell->cell->data.gridY); - mPhysics->addHeightField (land->landData->heights, - cell->cell->data.gridX, cell->cell->data.gridY, - 0, ( worldsize/(verts-1) ), verts); + if (land) + mPhysics->addHeightField (land->landData->heights, + cell->cell->data.gridX, cell->cell->data.gridY, + 0, ( worldsize/(verts-1) ), verts); } mRendering.configureAmbient(*cell); From 0afda15ce9f0e564abceef4773e724625d80fc40 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 18:14:33 +0200 Subject: [PATCH 110/289] fix for cells that have no region. --- apps/openmw/mwgui/window_manager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index dfac55beb..610f1b2f2 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -447,7 +447,8 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) else { const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->region); - name = region->name; + if (region) + name = region->name; } map->setCellName( name ); From 375c198ebd9d350dd3d137c3faf8af7382e3e032 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 18:21:05 +0200 Subject: [PATCH 111/289] WeatherManager: fix for cells that have no region. --- apps/openmw/mwworld/weather.cpp | 73 +++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index bcbb96eec..316463f53 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -499,51 +499,54 @@ void WeatherManager::update(float duration) mCurrentRegion = regionstr; mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*3600; - std::string weather; + std::string weather = "clear"; if (mRegionOverrides.find(regionstr) != mRegionOverrides.end()) weather = mRegionOverrides[regionstr]; else { // get weather probabilities for the current region - const ESM::Region *region = MWBase::Environment::get().getWorld()->getStore().regions.find (regionstr); + const ESM::Region *region = MWBase::Environment::get().getWorld()->getStore().regions.search (regionstr); - float clear = region->data.clear/255.f; - float cloudy = region->data.cloudy/255.f; - float foggy = region->data.foggy/255.f; - float overcast = region->data.overcast/255.f; - float rain = region->data.rain/255.f; - float thunder = region->data.thunder/255.f; - float ash = region->data.ash/255.f; - float blight = region->data.blight/255.f; - //float snow = region->data.a/255.f; - //float blizzard = region->data.b/255.f; + if (region != 0) + { + float clear = region->data.clear/255.f; + float cloudy = region->data.cloudy/255.f; + float foggy = region->data.foggy/255.f; + float overcast = region->data.overcast/255.f; + float rain = region->data.rain/255.f; + float thunder = region->data.thunder/255.f; + float ash = region->data.ash/255.f; + float blight = region->data.blight/255.f; + //float snow = region->data.a/255.f; + //float blizzard = region->data.b/255.f; - // re-scale to 100 percent - const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard; + // re-scale to 100 percent + const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard; - float random = ((rand()%100)/100.f) * total; + float random = ((rand()%100)/100.f) * total; - //if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear) - // weather = "blizzard"; - //else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear) - // weather = "snow"; - /*else*/ if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear) - weather = "blight"; - else if (random >= thunder+rain+overcast+foggy+cloudy+clear) - weather = "ashstorm"; - else if (random >= rain+overcast+foggy+cloudy+clear) - weather = "thunderstorm"; - else if (random >= overcast+foggy+cloudy+clear) - weather = "rain"; - else if (random >= foggy+cloudy+clear) - weather = "overcast"; - else if (random >= cloudy+clear) - weather = "foggy"; - else if (random >= clear) - weather = "cloudy"; - else - weather = "clear"; + //if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear) + // weather = "blizzard"; + //else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear) + // weather = "snow"; + /*else*/ if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear) + weather = "blight"; + else if (random >= thunder+rain+overcast+foggy+cloudy+clear) + weather = "ashstorm"; + else if (random >= rain+overcast+foggy+cloudy+clear) + weather = "thunderstorm"; + else if (random >= overcast+foggy+cloudy+clear) + weather = "rain"; + else if (random >= foggy+cloudy+clear) + weather = "overcast"; + else if (random >= cloudy+clear) + weather = "foggy"; + else if (random >= clear) + weather = "cloudy"; + else + weather = "clear"; + } } setWeather(weather, false); From 4213b4370ff87a7986df41eabd7e9757325b8d88 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 19:53:04 +0200 Subject: [PATCH 112/289] trade window shows up and shows the vendor's inventory items. --- apps/openmw/mwgui/container.cpp | 53 ++++++++-------- apps/openmw/mwgui/inventorywindow.cpp | 7 --- apps/openmw/mwgui/tradewindow.cpp | 72 ++++++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 2 +- files/mygui/openmw_trade_window_layout.xml | 21 ++++--- 5 files changed, 115 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 978e10fc4..eb02c5826 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -88,31 +88,34 @@ ContainerBase::~ContainerBase() void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { - if(!mDragAndDrop->mIsOnDragAndDrop) + if (mDragAndDrop) { - mSelectedItem = _sender; - - MWWorld::Ptr object = (*_sender->getUserData()); - int count = object.getRefData().getCount(); - - if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) + if(!mDragAndDrop->mIsOnDragAndDrop) { - onSelectedItemImpl(_sender, count); - } - else if (MyGUI::InputManager::getInstance().isControlPressed()) - { - onSelectedItemImpl(_sender, 1); + mSelectedItem = _sender; + + MWWorld::Ptr object = (*_sender->getUserData()); + int count = object.getRefData().getCount(); + + if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) + { + onSelectedItemImpl(_sender, count); + } + else if (MyGUI::InputManager::getInstance().isControlPressed()) + { + onSelectedItemImpl(_sender, 1); + } + else + { + CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); + dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl); + } } else - { - CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), count); - dialog->eventOkClicked.clear(); - dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl); - } + onContainerClicked(mContainerWidget); } - else - onContainerClicked(mContainerWidget); } void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) @@ -143,6 +146,8 @@ void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { + if (mDragAndDrop == NULL) return; + if(mDragAndDrop->mIsOnDragAndDrop) //drop item here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); @@ -323,7 +328,7 @@ void ContainerBase::drawItems() const MWWorld::Ptr* iter = &((*it).first); int displayCount = iter->getRefData().getCount(); - if (mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) + if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) { displayCount -= mDragAndDrop->mDraggedCount; } @@ -402,7 +407,7 @@ std::string ContainerBase::getCountString(const int count) void ContainerBase::Update() { - if(mDragAndDrop->mIsOnDragAndDrop) + if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop) { if(mDragAndDrop->mDraggedWidget) mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); @@ -462,7 +467,7 @@ void ContainerWindow::open(MWWorld::Ptr container) void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { - if(!mDragAndDrop->mIsOnDragAndDrop) + if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); setVisible(false); @@ -471,7 +476,7 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) { - if(!mDragAndDrop->mIsOnDragAndDrop) + if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { // transfer everything into the player's inventory MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4f16152ea..92c0553f6 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -16,13 +16,6 @@ #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" -#include "../mwscript/scriptmanager.hpp" -#include "../mwscript/compilercontext.hpp" -#include "../mwscript/interpretercontext.hpp" -#include "../mwscript/extensions.hpp" -#include "../mwscript/globalscripts.hpp" - - #include "window_manager.hpp" #include "widgets.hpp" #include "bookwindow.hpp" diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index cd38aa731..09557b196 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -1,15 +1,87 @@ #include "tradewindow.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + namespace MWGui { TradeWindow::TradeWindow(WindowManager& parWindowManager) : WindowBase("openmw_trade_window_layout.xml", parWindowManager), ContainerBase(NULL) // no drag&drop { + getWidget(mFilterAll, "AllButton"); + getWidget(mFilterWeapon, "WeaponButton"); + getWidget(mFilterApparel, "ApparelButton"); + getWidget(mFilterMagic, "MagicButton"); + getWidget(mFilterMisc, "MiscButton"); + + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + + mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); + mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); + mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); + mFilterMagic->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMagicTab")->str); + mFilterMisc->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMiscTab")->str); + + // adjust size of buttons to fit text + int curX = 0; + mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height ); + curX += mFilterAll->getTextSize().width + 24 + 4; + + mFilterWeapon->setPosition(curX, mFilterWeapon->getPosition().top); + mFilterWeapon->setSize( mFilterWeapon->getTextSize().width + 24, mFilterWeapon->getSize().height ); + curX += mFilterWeapon->getTextSize().width + 24 + 4; + + mFilterApparel->setPosition(curX, mFilterApparel->getPosition().top); + mFilterApparel->setSize( mFilterApparel->getTextSize().width + 24, mFilterApparel->getSize().height ); + curX += mFilterApparel->getTextSize().width + 24 + 4; + + mFilterMagic->setPosition(curX, mFilterMagic->getPosition().top); + mFilterMagic->setSize( mFilterMagic->getTextSize().width + 24, mFilterMagic->getSize().height ); + curX += mFilterMagic->getTextSize().width + 24 + 4; + + mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top); + mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height ); + + mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); + mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); + mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); + mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); + mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); + + mFilterAll->setStateSelected(true); } void TradeWindow::startTrade(MWWorld::Ptr actor) { ContainerBase::openContainer(actor); + + setVisible(true); + } + + void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) + { + if (_sender == mFilterAll) + setFilter(ContainerBase::Filter_All); + else if (_sender == mFilterWeapon) + setFilter(ContainerBase::Filter_Weapon); + else if (_sender == mFilterApparel) + setFilter(ContainerBase::Filter_Apparel); + else if (_sender == mFilterMagic) + setFilter(ContainerBase::Filter_Magic); + else if (_sender == mFilterMisc) + setFilter(ContainerBase::Filter_Misc); + + mFilterAll->setStateSelected(false); + mFilterWeapon->setStateSelected(false); + mFilterApparel->setStateSelected(false); + mFilterMagic->setStateSelected(false); + mFilterMisc->setStateSelected(false); + + static_cast(_sender)->setStateSelected(true); } } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index f6e48a28a..1593c6b19 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -108,6 +108,7 @@ WindowManager::WindowManager( console = new Console(w,h, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); + mTradeWindow = new TradeWindow(*this); mDialogueWindow = new DialogueWindow(*this); mContainerWindow = new ContainerWindow(*this,mDragAndDrop); mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); @@ -116,7 +117,6 @@ WindowManager::WindowManager( mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); - mTradeWindow = new TradeWindow(*this); // The HUD is always on hud->setVisible(true); diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index e5c45cdd0..15d313c4d 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -2,16 +2,10 @@ - - - - - - - + - + @@ -19,6 +13,17 @@ + + + + + + + + + + + From c9aa0ca1f42300c73155f618bab8deb52bd5cd95 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 19:54:09 +0200 Subject: [PATCH 113/289] don't create terrain if there is no land data, also fixes a water disappearing issue and a sound exception if cells with no region --- apps/openmw/mwrender/renderingmanager.cpp | 7 +++- apps/openmw/mwrender/terrain.cpp | 49 +++++++++-------------- apps/openmw/mwsound/soundmanager.cpp | 5 ++- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a95a179c6..18d512ac8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -11,6 +11,7 @@ #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwworld/ptr.hpp" +#include "../mwbase/environment.hpp" #include #include @@ -229,7 +230,10 @@ void RenderingManager::update (float duration){ mWater->update(); } void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ - if(store->cell->data.flags & store->cell->HasWater){ + if(store->cell->data.flags & store->cell->HasWater + || ((!(store->cell->data.flags & ESM::Cell::Interior)) + && !MWBase::Environment::get().getWorld()->getStore().lands.search(store->cell->data.gridX,store->cell->data.gridY) )) // always use water, if the cell does not have land. + { if(mWater == 0) mWater = new MWRender::Water(mRendering.getCamera(), mSkyManager, store->cell); else @@ -238,7 +242,6 @@ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ } else removeWater(); - } void RenderingManager::setWaterHeight(const float height) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 90d853f75..56eff4a9a 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -110,12 +110,12 @@ namespace MWRender const int cellY = store->cell->getGridY(); ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); - if ( land != NULL ) + if (land == NULL) // no land data means we're not going to create any terrain. + return; + + if (!land->dataLoaded) { - if (!land->dataLoaded) - { - land->loadData(); - } + land->loadData(); } //split the cell terrain into four segments @@ -138,25 +138,18 @@ namespace MWRender mLandSize*mLandSize, MEMCATEGORY_GEOMETRY); - if ( land != NULL ) + //copy the height data row by row + for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ ) { - //copy the height data row by row - for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ ) - { - //the offset of the current segment - const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE + - //offset of the row - terrainCopyY * ESM::Land::LAND_SIZE; - const size_t xOffset = x * (mLandSize-1); + //the offset of the current segment + const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE + + //offset of the row + terrainCopyY * ESM::Land::LAND_SIZE; + const size_t xOffset = x * (mLandSize-1); - memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize], - &land->landData->heights[yOffset + xOffset], - mLandSize*sizeof(float)); - } - } - else - { - memset(terrainData.inputFloat, 0, mLandSize*mLandSize*sizeof(float)); + memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize], + &land->landData->heights[yOffset + xOffset], + mLandSize*sizeof(float)); } std::map indexes; @@ -179,7 +172,7 @@ namespace MWRender terrain->setVisibilityFlags(RV_Terrain); terrain->setRenderQueueGroup(RQG_Main); - if ( land && land->landData->usingColours ) + if ( land->landData->usingColours ) { // disable or enable global colour map (depends on available vertex colours) mActiveProfile->setGlobalColourMapEnabled(true); @@ -196,10 +189,6 @@ namespace MWRender //mat = terrain->_getCompositeMapMaterial(); //mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() ); } - else - { - mActiveProfile->setGlobalColourMapEnabled(false); - } } } } @@ -215,8 +204,10 @@ namespace MWRender { for ( int y = 0; y < 2; y++ ) { - mTerrainGroup.unloadTerrain(store->cell->getGridX() * 2 + x, - store->cell->getGridY() * 2 + y); + int terrainX = store->cell->getGridX() * 2 + x; + int terrainY = store->cell->getGridY() * 2 + y; + if (mTerrainGroup.getTerrain(terrainX, terrainY) != NULL) + mTerrainGroup.unloadTerrain(terrainX, terrainY); } } } diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 9eefc7a28..8deab3c04 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -433,7 +433,10 @@ namespace MWSound total = 0; } - const ESM::Region *regn = MWBase::Environment::get().getWorld()->getStore().regions.find(regionName); + const ESM::Region *regn = MWBase::Environment::get().getWorld()->getStore().regions.search(regionName); + if (regn == NULL) + return; + std::vector::const_iterator soundIter; if(total == 0) { From 6ae642aa069efabd7eb3d643e9906eb5ffa4d8ec Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 21:15:48 +0200 Subject: [PATCH 114/289] complete trade window layout --- apps/openmw/mwgui/container.cpp | 2 - apps/openmw/mwgui/dialogue.cpp | 2 + apps/openmw/mwgui/tradewindow.cpp | 77 +++++++++++++++++++--- apps/openmw/mwgui/tradewindow.hpp | 15 +++++ apps/openmw/mwgui/window_manager.cpp | 6 ++ apps/openmw/mwgui/window_manager.hpp | 3 +- files/mygui/openmw_trade_window_layout.xml | 36 ++++++++-- 7 files changed, 122 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index eb02c5826..078a5e370 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -470,7 +470,6 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); - setVisible(false); } } @@ -502,6 +501,5 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) containerStore.clear(); MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); - setVisible(false); } } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 953657565..e8db4b6d1 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -17,6 +17,7 @@ #include "widgets.hpp" #include "list.hpp" #include "tradewindow.hpp" +#include "inventorywindow.hpp" using namespace MWGui; using namespace Widgets; @@ -137,6 +138,7 @@ void DialogueWindow::onSelectTopic(std::string topic) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? mWindowManager.getTradeWindow()->startTrade(mActor); + mWindowManager.setGuiMode(GM_Barter); } else diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 09557b196..31e0722aa 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -3,24 +3,49 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" +#include "window_manager.hpp" + namespace MWGui { TradeWindow::TradeWindow(WindowManager& parWindowManager) : WindowBase("openmw_trade_window_layout.xml", parWindowManager), ContainerBase(NULL) // no drag&drop { - getWidget(mFilterAll, "AllButton"); - getWidget(mFilterWeapon, "WeaponButton"); - getWidget(mFilterApparel, "ApparelButton"); - getWidget(mFilterMagic, "MagicButton"); - getWidget(mFilterMisc, "MiscButton"); - MyGUI::ScrollView* itemView; MyGUI::Widget* containerWidget; getWidget(containerWidget, "Items"); getWidget(itemView, "ItemView"); setWidgets(containerWidget, itemView); + getWidget(mFilterAll, "AllButton"); + getWidget(mFilterWeapon, "WeaponButton"); + getWidget(mFilterApparel, "ApparelButton"); + getWidget(mFilterMagic, "MagicButton"); + getWidget(mFilterMisc, "MiscButton"); + + getWidget(mMaxSaleButton, "MaxSaleButton"); + getWidget(mCancelButton, "CancelButton"); + getWidget(mOfferButton, "OfferButton"); + getWidget(mPlayerGold, "PlayerGold"); + getWidget(mMerchantGold, "MerchantGold"); + getWidget(mIncreaseButton, "IncreaseButton"); + getWidget(mDecreaseButton, "DecreaseButton"); + getWidget(mTotalBalance, "TotalBalance"); + getWidget(mTotalBalanceLabel, "TotalBalanceLabel"); + getWidget(mBottomPane, "BottomPane"); + + // this GMST doesn't seem to get retrieved - even though i can clearly see it in the CS !??!? + mMaxSaleButton->setCaption(mWindowManager.getGameSettingString("sMaxSale", "Max. Sale")); + + mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); + mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOffer")->str); +/* + mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalCost")->str); + mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalSold")->str); + mPlayerGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sYourGold")->str); + mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str); + +*/ mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); @@ -47,20 +72,42 @@ namespace MWGui mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top); mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height ); + mFilterAll->setStateSelected(true); + mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged); - mFilterAll->setStateSelected(true); + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked); + mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked); + + mMaxSaleButton->setSize(MyGUI::IntSize(mMaxSaleButton->getTextSize().width + 24, mMaxSaleButton->getHeight())); + + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(mBottomPane->getWidth()-cancelButtonWidth, + mCancelButton->getTop(), + cancelButtonWidth, + mCancelButton->getHeight()); + + int offerButtonWidth = mOfferButton->getTextSize().width + 24; + mOfferButton->setCoord(mBottomPane->getWidth()-cancelButtonWidth-offerButtonWidth-8, + mOfferButton->getTop(), + offerButtonWidth, + mOfferButton->getHeight()); + + setCoord(400, 0, 400, 300); + + static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &TradeWindow::onWindowResize); } void TradeWindow::startTrade(MWWorld::Ptr actor) { ContainerBase::openContainer(actor); - setVisible(true); + setTitle(MWWorld::Class::get(actor).getName(actor)); + adjustWindowCaption(); } void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) @@ -84,4 +131,18 @@ namespace MWGui static_cast(_sender)->setStateSelected(true); } + + void TradeWindow::onWindowResize(MyGUI::Window* _sender) + { + drawItems(); + } + + void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) + { + } + + void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) + { + mWindowManager.setGuiMode(GM_Game); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 5fc5b98b6..1f937d06e 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -37,8 +37,23 @@ namespace MWGui MyGUI::Button* mFilterMagic; MyGUI::Button* mFilterMisc; + MyGUI::Button* mIncreaseButton; + MyGUI::Button* mDecreaseButton; + MyGUI::TextBox* mTotalBalanceLabel; + MyGUI::TextBox* mTotalBalance; + + MyGUI::Widget* mBottomPane; + + MyGUI::Button* mMaxSaleButton; + MyGUI::Button* mCancelButton; + MyGUI::Button* mOfferButton; + MyGUI::TextBox* mPlayerGold; + MyGUI::TextBox* mMerchantGold; + void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); + void onOfferButtonClicked(MyGUI::Widget* _sender); + void onCancelButtonClicked(MyGUI::Widget* _sender); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 1593c6b19..e970de2e6 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -215,6 +215,7 @@ void WindowManager::updateVisible() mInventoryWindow->setVisible(false); mScrollWindow->setVisible(false); mBookWindow->setVisible(false); + mTradeWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -273,6 +274,11 @@ void WindowManager::updateVisible() case GM_Dialogue: mDialogueWindow->open(); break; + case GM_Barter: + mInventoryWindow->setVisible(true); + mInventoryWindow->openInventory(); + mTradeWindow->setVisible(true); + break; case GM_InterMessageBox: if(!mMessageBoxManager->isInteractiveMessageBox()) { setGuiMode(GM_Game); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 52869ff55..82c494191 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -130,9 +130,8 @@ namespace MWGui } MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} - MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} - + MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;} MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} MWGui::CountDialog* getCountDialog() {return mCountDialog;} diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index 15d313c4d..076924322 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -1,11 +1,11 @@ - + - + @@ -14,14 +14,36 @@ - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + From 41efea4c1d637b61e3f6be6757d2ae5478f5fcf1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 21:56:16 +0200 Subject: [PATCH 115/289] in the trade window, don't show items that the merchant has equipped. --- apps/openmw/mwgui/container.cpp | 9 ++-- apps/openmw/mwgui/container.hpp | 3 ++ apps/openmw/mwgui/inventorywindow.cpp | 19 ++++++-- apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwgui/tradewindow.cpp | 52 +++++++++++++++++++--- apps/openmw/mwgui/tradewindow.hpp | 8 ++++ apps/openmw/mwgui/window_manager.cpp | 2 +- files/mygui/openmw_trade_window_layout.xml | 4 +- 8 files changed, 85 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 078a5e370..6f8ca4730 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -300,10 +300,13 @@ void ContainerBase::drawItems() equippedItems.erase(found); } // and add the items that are left (= have the correct category) - for (std::vector::const_iterator it=equippedItems.begin(); - it != equippedItems.end(); ++it) + if (!ignoreEquippedItems()) { - items.push_back( std::make_pair(*it, ItemState_Equipped) ); + 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 diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index fe4ffc285..956382f23 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -98,6 +98,9 @@ namespace MWGui virtual bool isInventory() { return false; } virtual std::vector getEquippedItems() { return std::vector(); } virtual void _unequipItem(MWWorld::Ptr item) { ; } + + // to be reimplemented by TradeWindow + virtual bool ignoreEquippedItems() { return false; } }; class ContainerWindow : public ContainerBase, public WindowBase diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 92c0553f6..ebba395ff 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -84,13 +84,13 @@ namespace MWGui mFilterAll->setStateSelected(true); setCoord(0, 342, 600, 258); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + openContainer(player); } void InventoryWindow::openInventory() { - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - openContainer(player); - onWindowResize(static_cast(mMainWidget)); updateEncumbranceBar(); @@ -232,4 +232,17 @@ namespace MWGui ContainerBase::Update(); } + + int InventoryWindow::getPlayerGold() + { + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + + for (MWWorld::ContainerStoreIterator it = invStore.begin(); + it != invStore.end(); ++it) + { + if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + return it->getRefData().getCount(); + } + return 0; + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 07aeeeafd..e53402bbd 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -16,6 +16,8 @@ namespace MWGui virtual void Update(); virtual void notifyContentChanged(); + int getPlayerGold(); + protected: MyGUI::Widget* mAvatar; MyGUI::TextBox* mArmorRating; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 31e0722aa..8348b6066 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -1,15 +1,20 @@ #include "tradewindow.hpp" +#include + #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwworld/inventorystore.hpp" #include "window_manager.hpp" +#include "inventorywindow.hpp" namespace MWGui { TradeWindow::TradeWindow(WindowManager& parWindowManager) : - WindowBase("openmw_trade_window_layout.xml", parWindowManager), - ContainerBase(NULL) // no drag&drop + WindowBase("openmw_trade_window_layout.xml", parWindowManager) + , ContainerBase(NULL) // no drag&drop + , mCurrentBalance(0) { MyGUI::ScrollView* itemView; MyGUI::Widget* containerWidget; @@ -40,9 +45,6 @@ namespace MWGui mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOffer")->str); /* - mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalCost")->str); - mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalSold")->str); - mPlayerGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sYourGold")->str); mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str); */ @@ -108,6 +110,10 @@ namespace MWGui setTitle(MWWorld::Class::get(actor).getName(actor)); adjustWindowCaption(); + + mCurrentBalance = 0; + + updateLabels(); } void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) @@ -145,4 +151,40 @@ namespace MWGui { mWindowManager.setGuiMode(GM_Game); } + + void TradeWindow::updateLabels() + { + mPlayerGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sYourGold")->str + + " " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + + if (mCurrentBalance > 0) + { + mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalSold")->str); + mTotalBalance->setCaption(boost::lexical_cast(mCurrentBalance)); + } + else + { + mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalCost")->str); + mTotalBalance->setCaption(boost::lexical_cast(-mCurrentBalance)); + } + } + + + std::vector TradeWindow::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()) + { + items.push_back(*it); + } + } + + return items; + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 1f937d06e..dd28fcb8b 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -50,10 +50,18 @@ namespace MWGui MyGUI::TextBox* mPlayerGold; MyGUI::TextBox* mMerchantGold; + int mCurrentBalance; + void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); void onOfferButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender); + + // don't show items that the NPC has equipped in his trade-window. + virtual bool ignoreEquippedItems() { return true; } + virtual std::vector getEquippedItems(); + + void updateLabels(); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index e970de2e6..e12fb851e 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -108,10 +108,10 @@ WindowManager::WindowManager( console = new Console(w,h, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); + mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); mTradeWindow = new TradeWindow(*this); mDialogueWindow = new DialogueWindow(*this); mContainerWindow = new ContainerWindow(*this,mDragAndDrop); - mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); hud = new HUD(w,h, showFPSLevel, mDragAndDrop); mToolTips = new ToolTips(this); mScrollWindow = new ScrollWindow(*this); diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index 076924322..b6a93e697 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -22,10 +22,10 @@ - + - + From 9a3fd96a0cc8a86ae31add0539778a586800fba6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 22:24:47 +0200 Subject: [PATCH 116/289] display the merchant gold. --- apps/openmw/mwgui/tradewindow.cpp | 43 +++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 8348b6066..c6b677d8b 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -44,10 +44,7 @@ namespace MWGui mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOffer")->str); -/* - mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str); -*/ mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); @@ -167,15 +164,51 @@ namespace MWGui mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalCost")->str); mTotalBalance->setCaption(boost::lexical_cast(-mCurrentBalance)); } - } + // retrieve merchant gold + int gold = 0; + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + for (MWWorld::ContainerStoreIterator it = invStore.begin(); + it != invStore.end(); ++it) + { + if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + gold = it->getRefData().getCount(); + } + + int merchantgold; + if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + { + ESMS::LiveCellRef* ref = mContainer.get(); + if (ref->base->npdt52.gold == -10) + merchantgold = ref->base->npdt12.gold; + else + merchantgold = ref->base->npdt52.gold; + } + else // ESM::Creature + { + ESMS::LiveCellRef* ref = mContainer.get(); + merchantgold = ref->base->data.gold; + } + gold += merchantgold; + + mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str + + " " + boost::lexical_cast(gold)); + } std::vector TradeWindow::getEquippedItems() { - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + std::vector items; + if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + { + // creatures don't have equipment slots. + return items; + } + + 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); From 3cacc8feec26ef71d117d53a098b73e571c6f685 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 23:22:41 +0200 Subject: [PATCH 117/289] add re-stocking items to containers (though restocking isn't implemented) --- apps/openmw/mwworld/containerstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 5dfc9a177..b32bcd5d9 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -150,7 +150,7 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const ESMS: continue; } - ref.getPtr().getRefData().setCount (iter->count); + ref.getPtr().getRefData().setCount (std::abs(iter->count)); /// \todo implement item restocking (indicated by negative count) add (ref.getPtr()); } From 52e5e14654ed786776d595538bc21335f1c4464a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 May 2012 23:42:09 +0200 Subject: [PATCH 118/289] use GMST sDefaultCellname for the map window when cell has no region or name. --- apps/openmw/mwgui/window_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 610f1b2f2..2200448e6 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -449,6 +449,8 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->region); if (region) name = region->name; + else + name = getGameSettingString("sDefaultCellname", "Wilderness"); } map->setCellName( name ); From adf055029219ec9525820b9996cdafa4d376d73e Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 00:14:31 +0200 Subject: [PATCH 119/289] fixed a wrong label. --- apps/openmw/mwgui/tradewindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index c6b677d8b..97c66b9dc 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -43,7 +43,7 @@ namespace MWGui mMaxSaleButton->setCaption(mWindowManager.getGameSettingString("sMaxSale", "Max. Sale")); mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); - mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOffer")->str); + mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog8")->str); mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); From e1997b7f04396cc55bbb50132a945b0560d43b13 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 13:17:35 +0200 Subject: [PATCH 120/289] Issue #256: added MagicEffects::add overload for EffectLists --- apps/openmw/mwmechanics/magiceffects.cpp | 19 +++++++++++++++++++ apps/openmw/mwmechanics/magiceffects.hpp | 3 +++ apps/openmw/mwmechanics/spells.cpp | 8 +------- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 1c73bf1b1..52811084f 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -1,6 +1,8 @@ #include "magiceffects.hpp" +#include + #include #include @@ -66,6 +68,23 @@ namespace MWMechanics } } + void MagicEffects::add (const ESM::EffectList& list) + { + for (std::vector::const_iterator iter (list.list.begin()); iter!=list.list.end(); + ++iter) + { + EffectParam param; + + if (iter->magnMin>=iter->magnMax) + param.mMagnitude = iter->magnMin; + else + param.mMagnitude = static_cast ( + (iter->magnMax-iter->magnMin+1)*(std::rand() / RAND_MAX) + iter->magnMin); + + add (*iter, param); + } + } + EffectParam MagicEffects::get (const EffectKey& key) const { Collection::const_iterator iter = mCollection.find (key); diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 3d36ea813..d47101d45 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -6,6 +6,7 @@ namespace ESM { struct ENAMstruct; + struct EffectList; } namespace MWMechanics @@ -66,6 +67,8 @@ namespace MWMechanics void add (const EffectKey& key, const EffectParam& param); + void add (const ESM::EffectList& list); + EffectParam get (const EffectKey& key) const; ///< This function can safely be used for keys that are not present. diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index a53c75dc2..af43cdfb5 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -13,13 +13,7 @@ namespace MWMechanics { void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const { - for (std::vector::const_iterator iter = spell->effects.list.begin(); - iter!=spell->effects.list.end(); ++iter) - { - EffectParam param; - param.mMagnitude = iter->magnMax; /// \todo calculate magnitude - effects.add (EffectKey (*iter), param); - } + effects.add (spell->effects); } Spells::TIterator Spells::begin() const From 79055e281d882ee68ba2d2ef2abef65120254ed4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 13:54:07 +0200 Subject: [PATCH 121/289] Issue #256: Force update after building the player character --- apps/openmw/mwmechanics/actors.cpp | 3 --- apps/openmw/mwmechanics/actors.hpp | 7 +++++-- apps/openmw/mwmechanics/mechanicsmanager.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b0bb1e3ef..c527a645c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -32,9 +32,6 @@ namespace MWMechanics creatureStats.mDynamic[1].setBase (static_cast (intelligence + magickaFactor * intelligence)); creatureStats.mDynamic[2].setBase (strength+willpower+agility+endurance); - - for (int i=0; i<3; ++i) - creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified()); } void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 37a00deec..30e73ccf7 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -19,8 +19,6 @@ namespace MWMechanics std::set mActors; float mDuration; - void updateActor (const MWWorld::Ptr& ptr, float duration); - void updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused); void adjustMagicEffects (const MWWorld::Ptr& creature); @@ -41,6 +39,11 @@ namespace MWMechanics void update (std::vector >& movement, float duration, bool paused); ///< Update actor stats and store desired velocity vectors in \a movement + + void updateActor (const MWWorld::Ptr& ptr, float duration); + ///< This function is normally called automatically during the update process, but it can + /// also be called explicitly at any time to force an update. + }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 66a850b05..0c48d8894 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -138,6 +138,12 @@ namespace MWMechanics } } } + + // forced update and current value adjustments + mActors.updateActor (ptr, 0); + + for (int i=0; i<3; ++i) + creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified()); } From 5236bcb557923406edf234dbb3c4bb3a3d39f46e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 15:12:11 +0200 Subject: [PATCH 122/289] Issue #256: added operator+= for MagicEffects --- apps/openmw/mwmechanics/magiceffects.cpp | 24 ++++++++++++++++++++++++ apps/openmw/mwmechanics/magiceffects.hpp | 2 ++ 2 files changed, 26 insertions(+) diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 52811084f..41d898ca8 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -85,6 +85,30 @@ namespace MWMechanics } } + MagicEffects& MagicEffects::operator+= (const MagicEffects& effects) + { + if (this==&effects) + { + MagicEffects temp (effects); + *this += temp; + return *this; + } + + for (Collection::const_iterator iter (effects.Begin()); iter!=effects.End(); ++iter) + { + Collection::iterator result = mCollection.find (iter->first); + + if (result!=mCollection.end()) + { + result->second.mMagnitude += iter->second.mMagnitude; + } + else + mCollection.insert (*iter); + } + + return *this; + } + EffectParam MagicEffects::get (const EffectKey& key) const { Collection::const_iterator iter = mCollection.find (key); diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index d47101d45..26f78ec8a 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -69,6 +69,8 @@ namespace MWMechanics void add (const ESM::EffectList& list); + MagicEffects& operator+= (const MagicEffects& effects); + EffectParam get (const EffectKey& key) const; ///< This function can safely be used for keys that are not present. From 40c58c1bb79da8794862ff7f93806f4ff16d5ce6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 15:26:08 +0200 Subject: [PATCH 123/289] Issue #256: fixed a capitalisation mistake --- apps/openmw/mwmechanics/magiceffects.cpp | 11 +++++------ apps/openmw/mwmechanics/magiceffects.hpp | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 41d898ca8..97c2ec8c8 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -94,7 +94,7 @@ namespace MWMechanics return *this; } - for (Collection::const_iterator iter (effects.Begin()); iter!=effects.End(); ++iter) + for (Collection::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) { Collection::iterator result = mCollection.find (iter->first); @@ -128,11 +128,11 @@ namespace MWMechanics MagicEffects result; // adding/changing - for (Collection::const_iterator iter (now.Begin()); iter!=now.End(); ++iter) + for (Collection::const_iterator iter (now.begin()); iter!=now.end(); ++iter) { Collection::const_iterator other = prev.mCollection.find (iter->first); - if (other==prev.End()) + if (other==prev.end()) { // adding result.add (iter->first, iter->second); @@ -145,17 +145,16 @@ namespace MWMechanics } // removing - for (Collection::const_iterator iter (prev.Begin()); iter!=prev.End(); ++iter) + for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter) { Collection::const_iterator other = now.mCollection.find (iter->first); - if (other==prev.End()) + if (other==prev.end()) { result.add (iter->first, EffectParam() - iter->second); } } return result; - } } diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 26f78ec8a..2f61d7eeb 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -61,9 +61,9 @@ namespace MWMechanics public: - Collection::const_iterator Begin() const { return mCollection.begin(); } + Collection::const_iterator begin() const { return mCollection.begin(); } - Collection::const_iterator End() const { return mCollection.end(); } + Collection::const_iterator end() const { return mCollection.end(); } void add (const EffectKey& key, const EffectParam& param); From 372efaafd718a4f878d6d96ad273d39be8580835 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 15:27:41 +0200 Subject: [PATCH 124/289] Issue #256: changed implementation of MagicEffects::operator+= --- apps/openmw/mwmechanics/magiceffects.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 97c2ec8c8..f71e070d2 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -99,9 +99,7 @@ namespace MWMechanics Collection::iterator result = mCollection.find (iter->first); if (result!=mCollection.end()) - { - result->second.mMagnitude += iter->second.mMagnitude; - } + result->second += iter->second; else mCollection.insert (*iter); } From 124ea7761214497f8be57309f046f2333c94b415 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 15:48:55 +0200 Subject: [PATCH 125/289] Issue #256: consider equipped items when calculating magic effects --- apps/openmw/mwmechanics/actors.cpp | 8 ++++- apps/openmw/mwworld/containerstore.hpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 42 ++++++++++++++++++++++++-- apps/openmw/mwworld/inventorystore.hpp | 14 +++++++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c527a645c..cd2dbaddf 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -47,7 +47,13 @@ namespace MWMechanics MagicEffects now = creatureStats.mSpells.getMagicEffects(); - /// \todo add effects from active spells and equipment + if (creature.getTypeName()==typeid (ESM::NPC).name()) + { + MWWorld::InventoryStore& store = MWWorld::Class::get (creature).getInventoryStore (creature); + now += store.getMagicEffects(); + } + + /// \todo add effects from active spells MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now); diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 3cb3f3bdc..f677e0dcb 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -90,7 +90,7 @@ namespace MWWorld void clear(); ///< Empty container. - void flagAsModified(); + virtual void flagAsModified(); ///< \attention This function is internal to the world model and should not be called from /// outside. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 3e535793c..6981aea02 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -4,6 +4,12 @@ #include #include +#include + +#include "../mwbase/environment.hpp" + +#include "../mwworld/world.hpp" + #include "../mwmechanics/npcstats.hpp" #include "class.hpp" @@ -32,13 +38,13 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots) slots.push_back (end()); } -MWWorld::InventoryStore::InventoryStore() +MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false) { initSlots (mSlots); } MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) -: ContainerStore (store) +: ContainerStore (store), mMagicEffectsUpToDate (false) { copySlots (store); } @@ -201,6 +207,38 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) } } +const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() +{ + if (!mMagicEffectsUpToDate) + { + mMagicEffects = MWMechanics::MagicEffects(); + + for (TSlots::const_iterator iter (mSlots.begin()); iter!=mSlots.end(); ++iter) + if (*iter!=end()) + { + std::string enchantmentId = MWWorld::Class::get (**iter).getEnchantment (**iter); + + if (!enchantmentId.empty()) + { + const ESM::Enchantment& enchantment = + *MWBase::Environment::get().getWorld()->getStore().enchants.find (enchantmentId); + + if (enchantment.data.type==ESM::Enchantment::ConstantEffect) + mMagicEffects.add (enchantment.effects); + } + } + + mMagicEffectsUpToDate = true; + } + + return mMagicEffects; +} + +void MWWorld::InventoryStore::flagAsModified() +{ + mMagicEffectsUpToDate = false; +} + bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2); diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 05fc651ee..dcfb21f30 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -3,6 +3,8 @@ #include "containerstore.hpp" +#include "../mwmechanics/magiceffects.hpp" + namespace MWMechanics { struct NpcStats; @@ -41,6 +43,9 @@ namespace MWWorld private: + mutable MWMechanics::MagicEffects mMagicEffects; + mutable bool mMagicEffectsUpToDate; + typedef std::vector TSlots; mutable TSlots mSlots; @@ -65,6 +70,15 @@ namespace MWWorld void autoEquip (const MWMechanics::NpcStats& stats); ///< Auto equip items according to stats and item value. + const MWMechanics::MagicEffects& getMagicEffects(); + ///< Return magic effects from worn items. + /// + /// \todo make this const again, after the constness of Ptrs and iterators has been addressed. + + virtual void flagAsModified(); + ///< \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); From e2400ca7b2949f0238a24d5ebe7bd657b2f362f7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 15:51:33 +0200 Subject: [PATCH 126/289] only show items in the trade window that the NPC actually trades (services enum) --- apps/openmw/mwgui/container.cpp | 5 ++- apps/openmw/mwgui/container.hpp | 3 +- apps/openmw/mwgui/tradewindow.cpp | 59 +++++++++++++++++++++++++++++-- apps/openmw/mwgui/tradewindow.hpp | 4 +++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6f8ca4730..9ff4b8d4a 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -309,11 +309,14 @@ void ContainerBase::drawItems() } } + std::vector ignoreItems = itemsToIgnore(); + // now add the regular items std::vector regularItems; for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { - if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()) + if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() + && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()) regularItems.push_back(*iter); } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 956382f23..563b22bc3 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -94,13 +94,12 @@ 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) { ; } - // to be reimplemented by TradeWindow virtual bool ignoreEquippedItems() { return false; } + virtual std::vector itemsToIgnore() { return std::vector(); } }; class ContainerWindow : public ContainerBase, public WindowBase diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 97c66b9dc..e5fc47764 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -197,8 +197,6 @@ namespace MWGui std::vector TradeWindow::getEquippedItems() { - - std::vector items; if (mContainer.getTypeName() == typeid(ESM::Creature).name()) @@ -220,4 +218,61 @@ namespace MWGui return items; } + + bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) + { + int services = 0; + if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + { + ESMS::LiveCellRef* ref = mContainer.get(); + if (ref->base->hasAI) + services = ref->base->AI.services; + } + else if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + { + ESMS::LiveCellRef* ref = mContainer.get(); + if (ref->base->hasAI) + services = ref->base->AI.services; + } + + if (item.getTypeName() == typeid(ESM::Weapon).name()) + return services & ESM::NPC::Weapon; + else if (item.getTypeName() == typeid(ESM::Armor).name()) + return services & ESM::NPC::Armor; + else if (item.getTypeName() == typeid(ESM::Clothing).name()) + return services & ESM::NPC::Clothing; + else if (item.getTypeName() == typeid(ESM::Book).name()) + return services & ESM::NPC::Books; + else if (item.getTypeName() == typeid(ESM::Ingredient).name()) + return services & ESM::NPC::Ingredients; + else if (item.getTypeName() == typeid(ESM::Tool).name()) + return services & ESM::NPC::Picks; + else if (item.getTypeName() == typeid(ESM::Probe).name()) + return services & ESM::NPC::Probes; + else if (item.getTypeName() == typeid(ESM::Light).name()) + return services & ESM::NPC::Lights; + else if (item.getTypeName() == typeid(ESM::Apparatus).name()) + return services & ESM::NPC::Apparatus; + else if (item.getTypeName() == typeid(ESM::Repair).name()) + return services & ESM::NPC::RepairItem; + else if (item.getTypeName() == typeid(ESM::Miscellaneous).name()) + return services & ESM::NPC::Misc; + + return false; + } + + std::vector TradeWindow::itemsToIgnore() + { + std::vector items; + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + + for (MWWorld::ContainerStoreIterator it = invStore.begin(); + it != invStore.end(); ++it) + { + if (!npcAcceptsItem(*it)) + items.push_back(*it); + } + + return items; + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index dd28fcb8b..5e762cbe5 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -30,6 +30,8 @@ namespace MWGui //virtual void Update(); //virtual void notifyContentChanged(); + bool npcAcceptsItem(MWWorld::Ptr item); + protected: MyGUI::Button* mFilterAll; MyGUI::Button* mFilterWeapon; @@ -61,6 +63,8 @@ namespace MWGui virtual bool ignoreEquippedItems() { return true; } virtual std::vector getEquippedItems(); + virtual std::vector itemsToIgnore(); + void updateLabels(); }; } From 50a8eb05d96d975f702a4d3cfced0a0b37929acb Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 17:27:55 +0200 Subject: [PATCH 127/289] transfering items between player and merchant works and shows a red frame for bought/sold items. --- apps/openmw/mwgui/container.cpp | 162 ++++++++++++++++++++++++-- apps/openmw/mwgui/container.hpp | 22 +++- apps/openmw/mwgui/dialogue.cpp | 8 +- apps/openmw/mwgui/inventorywindow.cpp | 10 ++ apps/openmw/mwgui/inventorywindow.hpp | 6 + apps/openmw/mwgui/map_window.cpp | 3 +- apps/openmw/mwgui/stats_window.cpp | 3 +- apps/openmw/mwgui/tradewindow.cpp | 10 +- apps/openmw/mwgui/tradewindow.hpp | 3 + 9 files changed, 201 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 9ff4b8d4a..e51e22ecd 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -21,6 +21,8 @@ #include "window_manager.hpp" #include "widgets.hpp" #include "countdialog.hpp" +#include "tradewindow.hpp" +#include "inventorywindow.hpp" using namespace MWGui; using namespace Widgets; @@ -88,37 +90,120 @@ ContainerBase::~ContainerBase() void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { - if (mDragAndDrop) + mSelectedItem = _sender; + + if (mDragAndDrop && !isTrading()) { if(!mDragAndDrop->mIsOnDragAndDrop) { - mSelectedItem = _sender; - MWWorld::Ptr object = (*_sender->getUserData()); int count = object.getRefData().getCount(); if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) { - onSelectedItemImpl(_sender, count); + startDragItem(_sender, count); } else if (MyGUI::InputManager::getInstance().isControlPressed()) { - onSelectedItemImpl(_sender, 1); + startDragItem(_sender, 1); } else { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); dialog->open(MWWorld::Class::get(object).getName(object), count); dialog->eventOkClicked.clear(); - dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem); } } else onContainerClicked(mContainerWidget); } + else + { + MWWorld::Ptr object = (*_sender->getUserData()); + int count = object.getRefData().getCount(); + + 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), 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), count); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem); + } + } + } } -void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) +void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) +{ + MWWorld::Ptr object = *mSelectedItem->getUserData(); + assert( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end() ); + + if (count == object.getRefData().getCount()) + mBoughtItems.erase( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) ); + + if (isInventory()) + { + MWBase::Environment::get().getWindowManager()->getTradeWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); + } + else + { + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); + } + + drawItems(); +} + +void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) +{ + MWWorld::Ptr newPtr; + if (isInventory()) + { + newPtr = MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); + } + else + { + newPtr = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); + } + + drawItems(); +} + +void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count) { mDragAndDrop->mIsOnDragAndDrop = true; mSelectedItem->detachFromWidget(); @@ -281,6 +366,14 @@ void ContainerBase::drawItems() std::vector equippedItems = getEquippedItems(); + // add bartered items (always at the beginning) + std::sort(mBoughtItems.begin(), mBoughtItems.end(), sortItems); + for (std::vector::iterator it=mBoughtItems.begin(); + it != mBoughtItems.end(); ++it) + { + items.push_back( std::make_pair(*it, ItemState_Barter) ); + } + // 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) @@ -316,7 +409,8 @@ void ContainerBase::drawItems() for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() - && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()) + && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end() + && std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end()) regularItems.push_back(*iter); } @@ -338,7 +432,7 @@ void ContainerBase::drawItems() { displayCount -= mDragAndDrop->mDraggedCount; } - if(displayCount > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) + if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); @@ -361,10 +455,17 @@ void ContainerBase::drawItems() { backgroundTex += "_equip"; } + else if (it->second == ItemState_Barter) + { + backgroundTex += "_barter"; + } backgroundTex += ".dds"; backgroundWidget->setImageTexture(backgroundTex); - backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); + 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); @@ -421,6 +522,47 @@ void ContainerBase::Update() } } +MWWorld::Ptr ContainerBase::readdBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + int origCount = item.getRefData().getCount(); + item.getRefData().setCount(count); + MWWorld::ContainerStoreIterator it = containerStore.add(item); + item.getRefData().setCount(origCount - count); + + if (origCount - count == 0) + mSoldItems.erase( std::find(mSoldItems.begin(), mSoldItems.end(), item) ); + + return *it; +} + +MWWorld::Ptr ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + int origCount = item.getRefData().getCount(); + item.getRefData().setCount(count); + MWWorld::ContainerStoreIterator it = containerStore.add(item); + item.getRefData().setCount(origCount - count); + + mBoughtItems.push_back(*it); + return *it; +} + +void ContainerBase::removeBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + for (MWWorld::ContainerStoreIterator it(containerStore.begin()); it != containerStore.end(); ++it) + { + if (*it == item) + { + item.getRefData().setCount(item.getRefData().getCount() - count); + } + } +} + // ------------------------------------------------------------------------------------------------ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 563b22bc3..43a04ae70 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -62,13 +62,15 @@ namespace MWGui { ItemState_Normal = 0x01, ItemState_Equipped = 0x02, - - // unimplemented ItemState_Barter = 0x03 }; void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once + MWWorld::Ptr addBarteredItem(MWWorld::Ptr item, int count); + MWWorld::Ptr readdBarteredItem(MWWorld::Ptr item, int count); + void removeBarteredItem(MWWorld::Ptr item, int count); + void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter virtual void Update(); @@ -87,17 +89,31 @@ namespace MWGui Filter mFilter; + std::vector mBoughtItems; + std::vector mSoldItems; + void onSelectedItem(MyGUI::Widget* _sender); - void onSelectedItemImpl(MyGUI::Widget* _sender, int count); 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 getEquippedItems() { return std::vector(); } virtual void _unequipItem(MWWorld::Ptr item) { ; } + virtual bool isTrading() { return false; } + virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } }; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index e8db4b6d1..9f5e252fd 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -120,9 +120,6 @@ void DialogueWindow::open() history->eraseText(0,history->getTextLength()); updateOptions(); setVisible(true); - - // hide all sub-dialogues of the dialog window (trade window, persuasion, etc) - mWindowManager.getTradeWindow()->setVisible(false); } void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) @@ -137,8 +134,8 @@ void DialogueWindow::onSelectTopic(std::string topic) if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? - mWindowManager.getTradeWindow()->startTrade(mActor); mWindowManager.setGuiMode(GM_Barter); + mWindowManager.getTradeWindow()->startTrade(mActor); } else @@ -150,8 +147,7 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) mEnabled = true; mActor = actor; topicsList->setEnabled(true); - static_cast(mMainWidget)->setCaption(npcName); - adjustWindowCaption(); + setTitle(npcName); } void DialogueWindow::setKeywords(std::list keyWords) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ebba395ff..856ff1896 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -27,6 +27,7 @@ namespace MWGui InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) , WindowPinnableBase("openmw_inventory_window_layout.xml", parWindowManager) + , mTrading(false) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); @@ -94,6 +95,8 @@ namespace MWGui onWindowResize(static_cast(mMainWidget)); updateEncumbranceBar(); + + mTrading = false; } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) @@ -245,4 +248,11 @@ namespace MWGui } return 0; } + + void InventoryWindow::startTrade() + { + mTrading = true; + mBoughtItems.clear(); + mSoldItems.clear(); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index e53402bbd..e544b788a 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -13,6 +13,9 @@ namespace MWGui void openInventory(); + /// start trading, disables item drag&drop + void startTrade(); + virtual void Update(); virtual void notifyContentChanged(); @@ -33,6 +36,8 @@ namespace MWGui MyGUI::Button* mFilterMagic; MyGUI::Button* mFilterMisc; + bool mTrading; + void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); void onAvatarClicked(MyGUI::Widget* _sender); @@ -40,6 +45,7 @@ namespace MWGui void updateEncumbranceBar(); + virtual bool isTrading() { return mTrading; } virtual bool isInventory() { return true; } virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index d3541f774..9000d2fcb 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -121,8 +121,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : void MapWindow::setCellName(const std::string& cellName) { - static_cast(mMainWidget)->setCaption(cellName); - adjustWindowCaption(); + setTitle(cellName); } void MapWindow::setPlayerPos(const float x, const float y) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 186668222..43099e936 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -128,8 +128,7 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int void StatsWindow::setPlayerName(const std::string& playerName) { - static_cast(mMainWidget)->setCaption(playerName); - adjustWindowCaption(); + setTitle(playerName); } void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index e5fc47764..9f491242b 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -103,13 +103,17 @@ namespace MWGui void TradeWindow::startTrade(MWWorld::Ptr actor) { - ContainerBase::openContainer(actor); - setTitle(MWWorld::Class::get(actor).getName(actor)); - adjustWindowCaption(); mCurrentBalance = 0; + mWindowManager.getInventoryWindow()->startTrade(); + + mBoughtItems.clear(); + mSoldItems.clear(); + + ContainerBase::openContainer(actor); + updateLabels(); } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 5e762cbe5..5ab2d0d79 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -63,6 +63,9 @@ namespace MWGui virtual bool ignoreEquippedItems() { return true; } virtual std::vector getEquippedItems(); + virtual bool isTrading() { return true; } + virtual bool isTradeWindow() { return true; } + virtual std::vector itemsToIgnore(); void updateLabels(); From 342a244e31a5a59713cc0b58ee17d8152761db42 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 17:36:20 +0200 Subject: [PATCH 128/289] NPC now doesn't buy items of types that he shouldn't accept. --- apps/openmw/mwgui/container.cpp | 12 ++++++++++++ apps/openmw/mwgui/inventorywindow.cpp | 9 +++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index e51e22ecd..7d9fd4363 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -123,6 +123,18 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) MWWorld::Ptr object = (*_sender->getUserData()); 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(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog4")->str, std::vector()); + return; + } + } + if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end()) { if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 856ff1896..e08a2ba4f 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -92,11 +92,14 @@ namespace MWGui void InventoryWindow::openInventory() { - onWindowResize(static_cast(mMainWidget)); - updateEncumbranceBar(); mTrading = false; + + mBoughtItems.clear(); + mSoldItems.clear(); + + onWindowResize(static_cast(mMainWidget)); } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) @@ -252,7 +255,5 @@ namespace MWGui void InventoryWindow::startTrade() { mTrading = true; - mBoughtItems.clear(); - mSoldItems.clear(); } } From fb47681fbd61310037f29ca0095cda55615e451e Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 17:58:33 +0200 Subject: [PATCH 129/289] fix a bug, some cleanup --- apps/openmw/mwgui/container.cpp | 33 ++++++++++++--------------- apps/openmw/mwgui/container.hpp | 3 --- apps/openmw/mwgui/countdialog.cpp | 5 ++-- apps/openmw/mwgui/countdialog.hpp | 2 +- apps/openmw/mwgui/hud.cpp | 1 - apps/openmw/mwgui/inventorywindow.cpp | 8 +------ apps/openmw/mwgui/inventorywindow.hpp | 3 +-- apps/openmw/mwgui/tradewindow.hpp | 3 --- apps/openmw/mwgui/window_manager.cpp | 12 +++++++--- 9 files changed, 30 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 7d9fd4363..d0fd06a70 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -109,8 +109,9 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) } else { + std::string message = MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTake")->str; CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->open(MWWorld::Class::get(object).getName(object), message, count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem); } @@ -135,6 +136,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) } } + bool buying = isTradeWindow(); // buying or selling? + std::string message = buying ? MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage02")->str + : MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage01")->str; + if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end()) { if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) @@ -148,7 +153,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) else { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->open(MWWorld::Class::get(object).getName(object), message, count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellAlreadyBoughtItem); } @@ -166,7 +171,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) else { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->open(MWWorld::Class::get(object).getName(object), message, count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem); } @@ -202,13 +207,15 @@ void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) if (isInventory()) { newPtr = MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); - mSoldItems.push_back(newPtr); + if (std::find(mSoldItems.begin(), mSoldItems.end(), newPtr) == mSoldItems.end()) + mSoldItems.push_back(newPtr); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { newPtr = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); - mSoldItems.push_back(newPtr); + if (std::find(mSoldItems.begin(), mSoldItems.end(), newPtr) == mSoldItems.end()) + mSoldItems.push_back(newPtr); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } @@ -510,8 +517,6 @@ void ContainerBase::drawItems() 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) @@ -524,16 +529,6 @@ std::string ContainerBase::getCountString(const int count) return boost::lexical_cast(count); } -void ContainerBase::Update() -{ - if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop) - { - if(mDragAndDrop->mDraggedWidget) - mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); - else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug. - } -} - MWWorld::Ptr ContainerBase::readdBarteredItem(MWWorld::Ptr item, int count) { MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); @@ -558,7 +553,9 @@ MWWorld::Ptr ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) MWWorld::ContainerStoreIterator it = containerStore.add(item); item.getRefData().setCount(origCount - count); - mBoughtItems.push_back(*it); + if (std::find(mBoughtItems.begin(), mBoughtItems.end(), *it) == mBoughtItems.end()) + mBoughtItems.push_back(*it); + return *it; } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 43a04ae70..58d4548ee 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -73,11 +73,8 @@ namespace MWGui void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter - virtual void Update(); void drawItems(); - virtual void notifyContentChanged() { } - protected: MyGUI::ScrollView* mItemView; MyGUI::Widget* mContainerWidget; diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index dc7e75e0e..16e3f9aab 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -19,7 +19,6 @@ namespace MWGui mOkButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOk")->str); mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); - mLabelText->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTake")->str); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); @@ -27,10 +26,12 @@ namespace MWGui mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved); } - void CountDialog::open(const std::string& item, const int maxCount) + void CountDialog::open(const std::string& item, const std::string& message, const int maxCount) { setVisible(true); + mLabelText->setCaption(message); + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); mSlider->setScrollRange(maxCount); diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index b6c836c9d..aac17b846 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -9,7 +9,7 @@ namespace MWGui { public: CountDialog(WindowManager& parWindowManager); - void open(const std::string& item, const int maxCount); + void open(const std::string& item, const std::string& message, const int maxCount); typedef MyGUI::delegates::CMultiDelegate2 EventHandle_WidgetInt; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 395ca79c5..34d5ece98 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -285,7 +285,6 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) // remove object from the container it was coming from object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); - mDragAndDrop->mDraggedFrom->notifyContentChanged(); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e08a2ba4f..ca629d51d 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -228,15 +228,9 @@ namespace MWGui mEncumbranceText->setCaption( boost::lexical_cast(int(encumbrance)) + "/" + boost::lexical_cast(int(capacity)) ); } - void InventoryWindow::notifyContentChanged() - { - } - - void InventoryWindow::Update() + void InventoryWindow::update() { updateEncumbranceBar(); - - ContainerBase::Update(); } int InventoryWindow::getPlayerGold() diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index e544b788a..59aaf7859 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -16,8 +16,7 @@ namespace MWGui /// start trading, disables item drag&drop void startTrade(); - virtual void Update(); - virtual void notifyContentChanged(); + void update(); int getPlayerGold(); diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 5ab2d0d79..b96abc7e2 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -27,9 +27,6 @@ namespace MWGui void startTrade(MWWorld::Ptr actor); - //virtual void Update(); - //virtual void notifyContentChanged(); - bool npcAcceptsItem(MWWorld::Ptr item); protected: diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index e12fb851e..abbdcbcc1 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -97,7 +97,7 @@ WindowManager::WindowManager( MyGUI::Widget* dragAndDropWidget = gui->createWidgetT("Widget","",0,0,w,h,MyGUI::Align::Default,"DragAndDrop","DragAndDropWidget"); dragAndDropWidget->setVisible(false); - DragAndDrop* mDragAndDrop = new DragAndDrop(); + mDragAndDrop = new DragAndDrop(); mDragAndDrop->mIsOnDragAndDrop = false; mDragAndDrop->mDraggedWidget = 0; mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; @@ -468,9 +468,15 @@ void WindowManager::onDialogueWindowBye() void WindowManager::onFrame (float frameDuration) { mMessageBoxManager->onFrame(frameDuration); - mInventoryWindow->Update(); - mContainerWindow->Update(); mToolTips->onFrame(frameDuration); + + if (mDragAndDrop->mIsOnDragAndDrop) + { + assert(mDragAndDrop->mDraggedWidget); + mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); + } + + mInventoryWindow->update(); } const ESMS::ESMStore& WindowManager::getStore() const From db49e2c04668744a9d3372a7b7c4c67972a009b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 20:53:24 +0200 Subject: [PATCH 130/289] bought/sold items now use a separate ContainerStore, this fixes a stacking issue among other things --- apps/openmw/mwgui/container.cpp | 76 +++++++++++++-------------- apps/openmw/mwgui/container.hpp | 14 +++-- apps/openmw/mwgui/inventorywindow.cpp | 1 - apps/openmw/mwgui/tradewindow.cpp | 23 ++++---- 4 files changed, 56 insertions(+), 58 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index d0fd06a70..14a500b69 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -182,19 +182,15 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) { MWWorld::Ptr object = *mSelectedItem->getUserData(); - assert( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end() ); - - if (count == object.getRefData().getCount()) - mBoughtItems.erase( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) ); if (isInventory()) { - MWBase::Environment::get().getWindowManager()->getTradeWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { - MWBase::Environment::get().getWindowManager()->getInventoryWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } @@ -203,19 +199,14 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) { - MWWorld::Ptr newPtr; if (isInventory()) { - newPtr = MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); - if (std::find(mSoldItems.begin(), mSoldItems.end(), newPtr) == mSoldItems.end()) - mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { - newPtr = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); - if (std::find(mSoldItems.begin(), mSoldItems.end(), newPtr) == mSoldItems.end()) - mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } @@ -385,10 +376,16 @@ void ContainerBase::drawItems() std::vector equippedItems = getEquippedItems(); - // add bartered items (always at the beginning) - std::sort(mBoughtItems.begin(), mBoughtItems.end(), sortItems); - for (std::vector::iterator it=mBoughtItems.begin(); - it != mBoughtItems.end(); ++it) + // add bought items (always at the beginning) + std::vector 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::iterator it=boughtItems.begin(); + it != boughtItems.end(); ++it) { items.push_back( std::make_pair(*it, ItemState_Barter) ); } @@ -529,49 +526,50 @@ std::string ContainerBase::getCountString(const int count) return boost::lexical_cast(count); } -MWWorld::Ptr ContainerBase::readdBarteredItem(MWWorld::Ptr item, int count) +void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) { - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - int origCount = item.getRefData().getCount(); item.getRefData().setCount(count); - MWWorld::ContainerStoreIterator it = containerStore.add(item); + MWWorld::ContainerStoreIterator it = mBoughtItems.add(item); item.getRefData().setCount(origCount - count); - - if (origCount - count == 0) - mSoldItems.erase( std::find(mSoldItems.begin(), mSoldItems.end(), item) ); - - return *it; } -MWWorld::Ptr ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) +void ContainerBase::addItem(MWWorld::Ptr item, int count) { MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - int origCount = item.getRefData().getCount(); + int origCount = item.getRefData().getCount(); + item.getRefData().setCount(count); MWWorld::ContainerStoreIterator it = containerStore.add(item); + item.getRefData().setCount(origCount - count); - - if (std::find(mBoughtItems.begin(), mBoughtItems.end(), *it) == mBoughtItems.end()) - mBoughtItems.push_back(*it); - - return *it; } -void ContainerBase::removeBarteredItem(MWWorld::Ptr item, int count) +void ContainerBase::transferBoughtItems() { MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); - for (MWWorld::ContainerStoreIterator it(containerStore.begin()); it != containerStore.end(); ++it) + for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) { - if (*it == item) - { - item.getRefData().setCount(item.getRefData().getCount() - count); - } + containerStore.add(*it); } } +void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) +{ + for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) + { + store.add(*it); + } +} + +MWWorld::ContainerStore& ContainerBase::getContainerStore() +{ + MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + return store; +} + // ------------------------------------------------------------------------------------------------ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 58d4548ee..d300f4497 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -67,9 +67,13 @@ namespace MWGui void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once - MWWorld::Ptr addBarteredItem(MWWorld::Ptr item, int count); - MWWorld::Ptr readdBarteredItem(MWWorld::Ptr item, int count); - void removeBarteredItem(MWWorld::Ptr item, int count); + 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(); void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter @@ -86,8 +90,8 @@ namespace MWGui Filter mFilter; - std::vector mBoughtItems; - std::vector mSoldItems; + // 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); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ca629d51d..8bc9661e4 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -97,7 +97,6 @@ namespace MWGui mTrading = false; mBoughtItems.clear(); - mSoldItems.clear(); onWindowResize(static_cast(mMainWidget)); } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 9f491242b..fb70e0045 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -110,7 +110,6 @@ namespace MWGui mWindowManager.getInventoryWindow()->startTrade(); mBoughtItems.clear(); - mSoldItems.clear(); ContainerBase::openContainer(actor); @@ -146,10 +145,19 @@ namespace MWGui void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) { + transferBoughtItems(); + mWindowManager.getInventoryWindow()->transferBoughtItems(); + + mWindowManager.setGuiMode(GM_Game); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { + // i give you back your stuff! + returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore()); + // now gimme back my stuff! + mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + mWindowManager.setGuiMode(GM_Game); } @@ -169,16 +177,6 @@ namespace MWGui mTotalBalance->setCaption(boost::lexical_cast(-mCurrentBalance)); } - // retrieve merchant gold - int gold = 0; - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - for (MWWorld::ContainerStoreIterator it = invStore.begin(); - it != invStore.end(); ++it) - { - if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - gold = it->getRefData().getCount(); - } - int merchantgold; if (mContainer.getTypeName() == typeid(ESM::NPC).name()) { @@ -193,10 +191,9 @@ namespace MWGui ESMS::LiveCellRef* ref = mContainer.get(); merchantgold = ref->base->data.gold; } - gold += merchantgold; mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str - + " " + boost::lexical_cast(gold)); + + " " + boost::lexical_cast(merchantgold)); } std::vector TradeWindow::getEquippedItems() From a4343bfa18212591f3ebf25b97d5b40d4fce685e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 22:04:22 +0200 Subject: [PATCH 131/289] Issue #256: added TimeStamp class --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwworld/timestamp.cpp | 108 ++++++++++++++++++++++++++++++ apps/openmw/mwworld/timestamp.hpp | 44 ++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 apps/openmw/mwworld/timestamp.cpp create mode 100644 apps/openmw/mwworld/timestamp.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index d7c229cf9..7e5dcc1e2 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,6 +48,7 @@ add_openmw_dir (mwworld refdata world physicssystem scene globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors cells localscripts customdata weather inventorystore ptr actionread + timestamp ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwworld/timestamp.cpp b/apps/openmw/mwworld/timestamp.cpp new file mode 100644 index 000000000..e2f3d6c63 --- /dev/null +++ b/apps/openmw/mwworld/timestamp.cpp @@ -0,0 +1,108 @@ + +#include "timestamp.hpp" + +#include + +#include + +namespace MWWorld +{ + TimeStamp::TimeStamp (float hour, int day) + : mHour (hour), mDay (day) + { + if (hour<0 || hour>=24 || day<0) + throw std::runtime_error ("invalid time stamp"); + } + + float TimeStamp::getHour() const + { + return mHour; + } + + int TimeStamp::getDay() const + { + return mDay; + } + + TimeStamp& TimeStamp::operator+= (double hours) + { + if (hours<0) + throw std::runtime_error ("can't move time stamp backwards in time"); + + hours += mHour; + + mHour = static_cast (std::fmod (hours, 24)); + + mDay += hours / 24; + + return *this; + } + + bool operator== (const TimeStamp& left, const TimeStamp& right) + { + return left.getHour()==right.getHour() && left.getDay()==right.getDay(); + } + + bool operator!= (const TimeStamp& left, const TimeStamp& right) + { + return !(left==right); + } + + bool operator< (const TimeStamp& left, const TimeStamp& right) + { + if (left.getDay()right.getDay()) + return false; + + return left.getHour() (const TimeStamp& left, const TimeStamp& right) + { + return !(left<=right); + } + + bool operator>= (const TimeStamp& left, const TimeStamp& right) + { + return !(left=0 + + float getHour() const; + + int getDay() const; + + TimeStamp& operator+= (double hours); + ///< \param hours >=0 + }; + + bool operator== (const TimeStamp& left, const TimeStamp& right); + bool operator!= (const TimeStamp& left, const TimeStamp& right); + + bool operator< (const TimeStamp& left, const TimeStamp& right); + bool operator<= (const TimeStamp& left, const TimeStamp& right); + + bool operator> (const TimeStamp& left, const TimeStamp& right); + bool operator>= (const TimeStamp& left, const TimeStamp& right); + + TimeStamp operator+ (const TimeStamp& stamp, double hours); + TimeStamp operator+ (double hours, const TimeStamp& stamp); + + double operator- (const TimeStamp& left, const TimeStamp& right); + ///< Returns the difference between \a left and \a right in in-game hours. +} + +#endif From c004f5d570bc387b3c7b8910254b295a7f360391 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 22:06:25 +0200 Subject: [PATCH 132/289] adjust the "total cost"/"total sold" value when trading items, added some checks with respective user notifications --- apps/openmw/mwgui/container.cpp | 10 +++- apps/openmw/mwgui/container.hpp | 1 + apps/openmw/mwgui/tradewindow.cpp | 76 ++++++++++++++++++++++++++ apps/openmw/mwgui/tradewindow.hpp | 3 + apps/openmw/mwworld/containerstore.hpp | 2 +- 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 14a500b69..710e30b74 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -186,11 +186,13 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) if (isInventory()) { MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } @@ -199,14 +201,18 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) { + MWWorld::Ptr object = *mSelectedItem->getUserData(); + if (isInventory()) { - MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { - MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index d300f4497..66cac82ce 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -74,6 +74,7 @@ namespace MWGui 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(Filter filter); ///< set category filter diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index fb70e0045..06e91d787 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -145,6 +145,64 @@ namespace MWGui void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) { + // were there any items traded at all? + MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems(); + MWWorld::ContainerStore& merchantBought = getBoughtItems(); + + bool traded=false; + for (MWWorld::ContainerStoreIterator it = playerBought.begin(); + it != playerBought.end(); ++it) + { + if (it->getRefData().getCount() > 0) + traded = true; + } + for (MWWorld::ContainerStoreIterator it = merchantBought.begin(); + it != merchantBought.end(); ++it) + { + if (it->getRefData().getCount() > 0) + traded = true; + } + if (!traded) + { + // user notification + MWBase::Environment::get().getWindowManager()-> + messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog11")->str, std::vector()); + return; + } + + // check if the player can afford this + if (mCurrentBalance < 0 && mWindowManager.getInventoryWindow()->getPlayerGold() < std::abs(mCurrentBalance)) + { + // user notification + MWBase::Environment::get().getWindowManager()-> + messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog1")->str, std::vector()); + return; + } + + // check if the merchant can afford this + int merchantgold; + if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + { + ESMS::LiveCellRef* ref = mContainer.get(); + if (ref->base->npdt52.gold == -10) + merchantgold = ref->base->npdt12.gold; + else + merchantgold = ref->base->npdt52.gold; + } + else // ESM::Creature + { + ESMS::LiveCellRef* ref = mContainer.get(); + merchantgold = ref->base->data.gold; + } + if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) + { + // user notification + MWBase::Environment::get().getWindowManager()-> + messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog2")->str, std::vector()); + return; + } + + // success! make the item transfer. transferBoughtItems(); mWindowManager.getInventoryWindow()->transferBoughtItems(); @@ -276,4 +334,22 @@ namespace MWGui return items; } + + void TradeWindow::sellToNpc(MWWorld::Ptr item, int count) + { + /// \todo price adjustment depending on merchantile skill + + mCurrentBalance -= MWWorld::Class::get(item).getValue(item) * count; + + updateLabels(); + } + + void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count) + { + /// \todo price adjustment depending on merchantile skill + + mCurrentBalance += MWWorld::Class::get(item).getValue(item) * count; + + updateLabels(); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index b96abc7e2..8da96d37e 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -27,6 +27,9 @@ namespace MWGui void startTrade(MWWorld::Ptr actor); + void sellToNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance + void buyFromNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance + bool npcAcceptsItem(MWWorld::Ptr item); protected: diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 96c97415d..f850b01fa 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -74,7 +74,7 @@ namespace MWWorld /// \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 + /// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item. protected: ContainerStoreIterator addImpl (const Ptr& ptr); From c30b9e4bb91fa3e6fa98f072b79b000fecd13f49 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 22:21:44 +0200 Subject: [PATCH 133/289] add/remove gold from the player at the end of the transaction. --- apps/openmw/mwgui/tradewindow.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 06e91d787..641ffa833 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/manualref.hpp" #include "window_manager.hpp" #include "inventorywindow.hpp" @@ -206,6 +207,31 @@ namespace MWGui transferBoughtItems(); mWindowManager.getInventoryWindow()->transferBoughtItems(); + // add or remove gold from the player. + bool goldFound = false; + MWWorld::Ptr gold; + MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore(); + for (MWWorld::ContainerStoreIterator it = playerStore.begin(); + it != playerStore.end(); ++it) + { + if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + goldFound = true; + gold = *it; + } + } + if (goldFound) + { + gold.getRefData().setCount(gold.getRefData().getCount() + mCurrentBalance); + } + else + { + assert(mCurrentBalance > 0); + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001"); + ref.getPtr().getRefData().setCount(mCurrentBalance); + playerStore.add(ref.getPtr()); + } + mWindowManager.setGuiMode(GM_Game); } From 498530fad7244b8fe39f96003ab676f344a99bc7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 18 May 2012 22:24:19 +0200 Subject: [PATCH 134/289] container iterator fix --- apps/openmw/mwworld/containerstore.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index ee1b620cd..44eb0ac70 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -228,6 +228,11 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor : mType (0), mMask (mask), mContainer (container) { nextType(); + + if (mType==-1 || (**this).getRefData().getCount()) + return; + + ++*this; } void MWWorld::ContainerStoreIterator::incType() @@ -249,7 +254,7 @@ void MWWorld::ContainerStoreIterator::nextType() { incType(); - if (mType & mMask) + if ((mType & mMask) && mType>0) if (resetIterator()) break; } From f28f36f2621e9803e1a830120e31609b8994548f Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 22:27:27 +0200 Subject: [PATCH 135/289] added sounds to trade window --- apps/openmw/mwgui/container.cpp | 6 ++++++ apps/openmw/mwgui/tradewindow.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 710e30b74..871989fab 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -196,6 +196,9 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) 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(); } @@ -216,6 +219,9 @@ void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) 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(); } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 641ffa833..b1beccc26 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -6,6 +6,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/manualref.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "inventorywindow.hpp" @@ -232,6 +233,9 @@ namespace MWGui playerStore.add(ref.getPtr()); } + std::string sound = "Item Gold Up"; + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); + mWindowManager.setGuiMode(GM_Game); } From 656b08f6209bb496bc158e7ae151b9288df57c08 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 22:32:06 +0200 Subject: [PATCH 136/289] removed the workaround for the ContainerStore bug. --- apps/openmw/mwgui/tradewindow.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index b1beccc26..047d1da1e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -150,21 +150,7 @@ namespace MWGui // were there any items traded at all? MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems(); MWWorld::ContainerStore& merchantBought = getBoughtItems(); - - bool traded=false; - for (MWWorld::ContainerStoreIterator it = playerBought.begin(); - it != playerBought.end(); ++it) - { - if (it->getRefData().getCount() > 0) - traded = true; - } - for (MWWorld::ContainerStoreIterator it = merchantBought.begin(); - it != merchantBought.end(); ++it) - { - if (it->getRefData().getCount() > 0) - traded = true; - } - if (!traded) + if (playerBought.begin() == playerBought.end() && merchantBought.begin() == merchantBought.end()) { // user notification MWBase::Environment::get().getWindowManager()-> From 41466fc5fc38bba602ce8c2115a078811ae97a53 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 23:00:31 +0200 Subject: [PATCH 137/289] gold label fix, and don't allow selling gold --- apps/openmw/mwgui/container.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 871989fab..85a399450 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -127,7 +127,9 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) if (isInventory()) { // the player is trying to sell an item, check if the merchant accepts it - if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) + // also, don't allow selling gold (let's be better than Morrowind at this, can we?) + if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object) + || MWWorld::Class::get(object).getName(object) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) { // user notification "i don't buy this item" MWBase::Environment::get().getWindowManager()-> @@ -533,7 +535,7 @@ std::string ContainerBase::getCountString(const int count) if (count == 1) return ""; if (count > 9999) - return boost::lexical_cast(count/1000.f) + "k"; + return boost::lexical_cast(int(count/1000.f)) + "k"; else return boost::lexical_cast(count); } From 1006411c0200de3259608fc70f1e1cf5df7d225b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 00:06:11 +0200 Subject: [PATCH 138/289] small fix for mygui log being spammed with errors --- apps/openmw/mwgui/container.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 85a399450..5595825fc 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -489,7 +489,8 @@ void ContainerBase::drawItems() { backgroundTex += "_barter"; } - backgroundTex += ".dds"; + if (backgroundTex != "") + backgroundTex += ".dds"; backgroundWidget->setImageTexture(backgroundTex); if (it->second == ItemState_Barter && !isMagic) From 9ca579ba63de52d8590692dd96dd5c57dc93c699 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 00:36:01 +0200 Subject: [PATCH 139/289] slightly revamped gold stacking, now always uses the gold_001 base object to be script-friendly --- apps/openmw/mwworld/containerstore.cpp | 48 +++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index ada5b444a..b669508b2 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include "../mwbase/environment.hpp" @@ -32,6 +34,12 @@ namespace return sum; } + + bool compare_string_ci(std::string str1, std::string str2) + { + boost::algorithm::to_lower(str1); + return str1 == str2; + } } MWWorld::ContainerStore::ContainerStore() : mStateId (0), mCachedWeight (0), mWeightUpToDate (false) {} @@ -65,35 +73,35 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) { int type = getType(ptr); - // gold needs special treatment because it uses several different meshes + // gold needs special handling: when it is inserted into a container, the base object automatically becomes Gold_001 + // this ensures that gold piles of different sizes stack with each other (also, several scripts rely on Gold_001 for detecting player gold) if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) { ESMS::LiveCellRef *gold = ptr.get(); - int goldValue = (ptr.getRefData().getCount() == 1) ? gold->base->data.value : ptr.getRefData().getCount(); - - for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) + if (compare_string_ci(gold->ref.refID, "gold_001") + || compare_string_ci(gold->ref.refID, "gold_005") + || compare_string_ci(gold->ref.refID, "gold_010") + || compare_string_ci(gold->ref.refID, "gold_025") + || compare_string_ci(gold->ref.refID, "gold_100")) { - if (MWWorld::Class::get(*iter).getName(*iter) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str - && MWWorld::Class::get(*iter).getScript(*iter) == "" && MWWorld::Class::get(ptr).getScript(ptr) == "") + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001"); + + int count = (ptr.getRefData().getCount() == 1) ? gold->base->data.value : ptr.getRefData().getCount(); + ref.getPtr().getRefData().setCount(count); + for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - ESMS::LiveCellRef *ref = - iter->get(); - - if (iter->getRefData().getCount() == 1) - iter->getRefData().setCount(ref->base->data.value + goldValue); - else - iter->getRefData().setCount(iter->getRefData().getCount() + goldValue); - - flagAsModified(); - return iter; + if (compare_string_ci((*iter).get()->ref.refID, "gold_001")) + { + (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); + flagAsModified(); + return iter; + } } - } - // if we get here, no already existing gold was found in the container - // we still need special handling because gold in a container should always have the real gold value as reference count. - ptr.getRefData().setCount(goldValue); + return addImpl(ref.getPtr()); + } } // determine whether to stack or not From 74ae3605e0f8eb742ebe7b4b03438b62bff57d54 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 19 May 2012 09:31:45 +0200 Subject: [PATCH 140/289] Issue #256: added getTimeStamp function to World --- apps/openmw/mwworld/world.cpp | 6 ++++++ apps/openmw/mwworld/world.hpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 4adaf7918..eeda92277 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -471,6 +471,12 @@ namespace MWWorld mRendering->skySetDate (mGlobalVariables->getInt ("day"), month); } + TimeStamp World::getTimeStamp() const + { + return TimeStamp (mGlobalVariables->getFloat ("gamehour"), + mGlobalVariables->getInt ("dayspassed")); + } + bool World::toggleSky() { if (mSky) diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 7359f8b90..49a3cf029 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -18,6 +18,7 @@ #include "physicssystem.hpp" #include "cells.hpp" #include "localscripts.hpp" +#include "timestamp.hpp" #include #include @@ -185,6 +186,9 @@ namespace MWWorld void setDay (int day); ///< Set in-game time day. + TimeStamp getTimeStamp() const; + ///< Return current in-game time stamp. + bool toggleSky(); ///< \return Resulting mode From ee884634b993b4c5322804b9e4265d319da1dcf4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 13:19:26 +0200 Subject: [PATCH 141/289] fixed item refID handling in the dialogue manager and container script extensions. --- apps/openmw/mwdialogue/dialoguemanager.cpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 7baf589c4..295a50526 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -363,7 +363,7 @@ namespace MWDialogue int sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (iter->getCellRef().refID==name) + if (toLower(iter->getCellRef().refID) == toLower(name)) sum += iter->getRefData().getCount(); if(!selectCompare(comp,sum,select.i)) return false; } diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 3e8658bf8..b916ba72c 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -18,6 +18,19 @@ #include "interpretercontext.hpp" #include "ref.hpp" +namespace +{ + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } +} + namespace MWScript { namespace Container @@ -65,7 +78,7 @@ namespace MWScript Interpreter::Type_Integer sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (iter->getCellRef().refID==item) + if (toLower(iter->getCellRef().refID) == toLower(item)) sum += iter->getRefData().getCount(); runtime.push (sum); @@ -95,7 +108,7 @@ namespace MWScript for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) { - if (iter->getCellRef().refID==item) + if (toLower(iter->getCellRef().refID) == toLower(item)) { if (iter->getRefData().getCount()<=count) { From 24ce88de2a2c871bf06ca4d7c8d30167d5afe8df Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 14:19:21 +0200 Subject: [PATCH 142/289] working mygui tag replacement system for GMST strings --- apps/openmw/mwgui/stats_window.cpp | 45 +++++++++++++++----- apps/openmw/mwgui/stats_window.hpp | 12 ++++-- apps/openmw/mwgui/tradewindow.cpp | 6 --- apps/openmw/mwgui/window_manager.cpp | 48 ++++++++++++---------- apps/openmw/mwgui/window_manager.hpp | 13 +++++- files/mygui/openmw_trade_window_layout.xml | 24 +++++++---- 6 files changed, 98 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 43099e936..fac2a05f9 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -1,13 +1,19 @@ #include "stats_window.hpp" -#include "../mwmechanics/mechanicsmanager.hpp" -#include "window_manager.hpp" - #include #include #include + #include +#include "../mwmechanics/mechanicsmanager.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwbase/environment.hpp" + +#include "window_manager.hpp" + + using namespace MWGui; const int StatsWindow::lineHeight = 18; @@ -24,11 +30,12 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) , skillValues() , skillWidgetMap() , factionWidgetMap() - , factions() + , mFactions() , birthSignId() , reputation(0) , bounty(0) , skillWidgets() + , mChanged(true) { setCoord(0,0,498, 342); @@ -128,7 +135,8 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int void StatsWindow::setPlayerName(const std::string& playerName) { - setTitle(playerName); + static_cast(mMainWidget)->setCaption(playerName); + adjustWindowCaption(); } void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) @@ -235,9 +243,24 @@ void StatsWindow::configureSkills (const std::vector& major, const std::vec } } -void StatsWindow::setFactions (const std::vector& factions) +void StatsWindow::onFrame () { - this->factions = factions; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); + + setFactions(PCstats.mFactionRank); + + if (mChanged) + updateSkillArea(); +} + +void StatsWindow::setFactions (const FactionList& factions) +{ + if (mFactions != factions) + { + mFactions = factions; + mChanged = true; + } } void StatsWindow::setBirthSign (const std::string& signId) @@ -345,6 +368,8 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, void StatsWindow::updateSkillArea() { + mChanged = false; + for (std::vector::iterator it = skillWidgets.begin(); it != skillWidgets.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); @@ -366,15 +391,15 @@ void StatsWindow::updateSkillArea() const ESMS::ESMStore &store = mWindowManager.getStore(); - if (!factions.empty()) + if (!mFactions.empty()) { // Add a line separator if there are items above if (!skillWidgets.empty()) addSeparator(coord1, coord2); addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2); - FactionList::const_iterator end = factions.end(); - for (FactionList::const_iterator it = factions.begin(); it != end; ++it) + FactionList::const_iterator end = mFactions.end(); + for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) { const ESM::Faction *faction = store.factions.find(it->first); addItem(faction->name, coord1, coord2); diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 08c5148ec..ecda22ee0 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -18,13 +18,15 @@ namespace MWGui class StatsWindow : public WindowPinnableBase { public: - typedef std::pair Faction; - typedef std::vector FactionList; + typedef std::map FactionList; typedef std::vector SkillList; StatsWindow(WindowManager& parWindowManager); + /// automatically updates all the data in the stats window, but only if it has changed. + void onFrame(); + void setBar(const std::string& name, const std::string& tname, int val, int max); void setPlayerName(const std::string& playerName); @@ -36,7 +38,7 @@ namespace MWGui void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); void configureSkills (const SkillList& major, const SkillList& minor); - void setFactions (const std::vector& factions); + void setFactions (const FactionList& factions); void setBirthSign (const std::string &signId); void setReputation (int reputation) { this->reputation = reputation; } void setBounty (int bounty) { this->bounty = bounty; } @@ -69,11 +71,13 @@ namespace MWGui std::map > skillValues; std::map skillWidgetMap; std::map factionWidgetMap; - FactionList factions; ///< Stores a list of factions and the current rank + FactionList mFactions; ///< Stores a list of factions and the current rank std::string birthSignId; int reputation, bounty; std::vector skillWidgets; //< Skills and other information + bool mChanged; + protected: virtual void onPinToggled(); }; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 047d1da1e..2dcf7c7f8 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -47,12 +47,6 @@ namespace MWGui mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog8")->str); - mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); - mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); - mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); - mFilterMagic->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMagicTab")->str); - mFilterMisc->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMiscTab")->str); - // adjust size of buttons to fit text int curX = 0; mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height ); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index f447c78e4..9246af1fe 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -40,7 +40,7 @@ WindowManager::WindowManager( , hud(NULL) , map(NULL) , menu(NULL) - , stats(NULL) + , mStatsWindow(NULL) , mToolTips(NULL) , mMessageBoxManager(NULL) , console(NULL) @@ -89,6 +89,8 @@ WindowManager::WindowManager( MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); + // Get size info from the Gui object assert(gui); int w = MyGUI::RenderManager::getInstance().getViewSize().width; @@ -104,7 +106,7 @@ WindowManager::WindowManager( menu = new MainMenu(w,h); map = new MapWindow(*this); - stats = new StatsWindow(*this); + mStatsWindow = new StatsWindow(*this); console = new Console(w,h, extensions); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); @@ -146,7 +148,7 @@ WindowManager::~WindowManager() delete hud; delete map; delete menu; - delete stats; + delete mStatsWindow; delete mJournal; delete mDialogueWindow; delete mContainerWindow; @@ -207,7 +209,7 @@ void WindowManager::updateVisible() // Start out by hiding everything except the HUD map->setVisible(false); menu->setVisible(false); - stats->setVisible(false); + mStatsWindow->setVisible(false); console->disable(); mJournal->setVisible(false); mDialogueWindow->setVisible(false); @@ -261,7 +263,7 @@ void WindowManager::updateVisible() // Show the windows we want map -> setVisible( (eff & GW_Map) != 0 ); - stats -> setVisible( (eff & GW_Stats) != 0 ); + mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); mInventoryWindow->setVisible(true); mInventoryWindow->openInventory(); break; @@ -299,7 +301,7 @@ void WindowManager::updateVisible() void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { - stats->setValue (id, value); + mStatsWindow->setValue (id, value); static const char *ids[] = { @@ -329,13 +331,13 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { - stats->setValue(parSkill, value); + mStatsWindow->setValue(parSkill, value); playerSkillValues[parSkill] = value; } void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat& value) { - stats->setValue (id, value); + mStatsWindow->setValue (id, value); hud->setValue (id, value); if (id == "HBar") { @@ -368,7 +370,7 @@ MWMechanics::DynamicStat WindowManager::getValue(const std::string& id) void WindowManager::setValue (const std::string& id, const std::string& value) { - stats->setValue (id, value); + mStatsWindow->setValue (id, value); if (id=="name") playerName = value; else if (id=="race") @@ -377,46 +379,41 @@ void WindowManager::setValue (const std::string& id, const std::string& value) void WindowManager::setValue (const std::string& id, int value) { - stats->setValue (id, value); + mStatsWindow->setValue (id, value); } void WindowManager::setPlayerClass (const ESM::Class &class_) { playerClass = class_; - stats->setValue("class", playerClass.name); + mStatsWindow->setValue("class", playerClass.name); } void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) { - stats->configureSkills (major, minor); + mStatsWindow->configureSkills (major, minor); playerMajorSkills = major; playerMinorSkills = minor; } -void WindowManager::setFactions (const FactionList& factions) -{ - stats->setFactions (factions); -} - void WindowManager::setBirthSign (const std::string &signId) { - stats->setBirthSign (signId); + mStatsWindow->setBirthSign (signId); playerBirthSignId = signId; } void WindowManager::setReputation (int reputation) { - stats->setReputation (reputation); + mStatsWindow->setReputation (reputation); } void WindowManager::setBounty (int bounty) { - stats->setBounty (bounty); + mStatsWindow->setBounty (bounty); } void WindowManager::updateSkillArea() { - stats->updateSkillArea(); + mStatsWindow->updateSkillArea(); } void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) @@ -477,6 +474,8 @@ void WindowManager::onFrame (float frameDuration) } mInventoryWindow->update(); + + mStatsWindow->onFrame(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -598,3 +597,10 @@ void WindowManager::setDragDrop(bool dragDrop) mToolTips->setEnabled(!dragDrop); MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); } + +void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) +{ + const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(_tag); + if (setting && setting->type == ESM::VT_String) + _result = setting->str; +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 82c494191..cdcace85d 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -14,11 +14,15 @@ #include #include +#include "MyGUI_UString.h" + #include #include #include + #include "../mwmechanics/stat.hpp" #include "../mwworld/ptr.hpp" + #include "mode.hpp" namespace MyGUI @@ -157,7 +161,6 @@ namespace MWGui void setPlayerClass (const ESM::Class &class_); ///< set current class of player void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. - void setFactions (const FactionList& factions); ///< set faction and rank to display on stat window, use an empty vector to disable void setBirthSign (const std::string &signId); ///< set birth sign to display on stat window, use an empty string to disable. void setReputation (int reputation); ///< set the current reputation value void setBounty (int bounty); ///< set the current bounty value @@ -216,7 +219,7 @@ namespace MWGui MapWindow *map; MainMenu *menu; ToolTips *mToolTips; - StatsWindow *stats; + StatsWindow *mStatsWindow; MessageBoxManager *mMessageBoxManager; Console *console; JournalWindow* mJournal; @@ -270,6 +273,12 @@ namespace MWGui size_t 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 + */ + void onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result); }; template diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index b6a93e697..8a4e00433 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -6,11 +6,21 @@ - - - - - + + + + + + + + + + + + + + + @@ -36,8 +46,8 @@ - - + + From 635a89c35cc17053a40ec6cec0efb804c5c4185c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 19 May 2012 14:43:02 +0200 Subject: [PATCH 143/289] Issue #256: RNG fix --- apps/openmw/mwmechanics/magiceffects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index f71e070d2..a77e19966 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -79,7 +79,8 @@ namespace MWMechanics param.mMagnitude = iter->magnMin; else param.mMagnitude = static_cast ( - (iter->magnMax-iter->magnMin+1)*(std::rand() / RAND_MAX) + iter->magnMin); + (iter->magnMax-iter->magnMin+1)* + (static_cast (std::rand()) / RAND_MAX) + iter->magnMin); add (*iter, param); } From 7ef0ad4e39c46d514681fac994a5ccbcf8d26e72 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 14:55:09 +0200 Subject: [PATCH 144/289] show faction & birthsign in the stats window --- apps/openmw/mwgui/charactercreation.cpp | 2 -- apps/openmw/mwgui/inventorywindow.cpp | 11 ++++------ apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/stats_window.cpp | 15 +++++++++++++- apps/openmw/mwgui/stats_window.hpp | 5 +++-- apps/openmw/mwgui/window_manager.cpp | 9 +-------- apps/openmw/mwgui/window_manager.hpp | 2 -- .../mygui/openmw_inventory_window_layout.xml | 20 ++++++++++++++----- 8 files changed, 38 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 7a86ba9ac..afb168d32 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -173,7 +173,6 @@ void CharacterCreation::spawnDialog(const char id) mWM->removeDialog(mBirthSignDialog); mBirthSignDialog = new BirthDialog(*mWM); mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen); - mBirthSignDialog->setBirthId(mPlayerBirthSignId); mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone); mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack); mBirthSignDialog->open(); @@ -414,7 +413,6 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) if (mBirthSignDialog) { mPlayerBirthSignId = mBirthSignDialog->getBirthId(); - mWM->setBirthSign(mPlayerBirthSignId); if (!mPlayerBirthSignId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId); mWM->removeDialog(mBirthSignDialog); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 8bc9661e4..a0326debc 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -50,12 +50,6 @@ namespace MWGui getWidget(itemView, "ItemView"); setWidgets(containerWidget, itemView); - mFilterAll->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sAllTab")->str); - mFilterWeapon->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sWeaponTab")->str); - mFilterApparel->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sApparelTab")->str); - mFilterMagic->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMagicTab")->str); - mFilterMisc->setCaption (MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sMiscTab")->str); - // adjust size of buttons to fit text int curX = 0; mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height ); @@ -227,8 +221,11 @@ namespace MWGui mEncumbranceText->setCaption( boost::lexical_cast(int(encumbrance)) + "/" + boost::lexical_cast(int(capacity)) ); } - void InventoryWindow::update() + void InventoryWindow::onFrame() { + if (!mMainWidget->getVisible()) + return; + updateEncumbranceBar(); } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 59aaf7859..fdb443829 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -16,7 +16,7 @@ namespace MWGui /// start trading, disables item drag&drop void startTrade(); - void update(); + void onFrame(); int getPlayerGold(); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index fac2a05f9..30d63033b 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -245,11 +245,16 @@ void StatsWindow::configureSkills (const std::vector& major, const std::vec void StatsWindow::onFrame () { + if (mMainWidget->getVisible()) + return; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); setFactions(PCstats.mFactionRank); + setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); + if (mChanged) updateSkillArea(); } @@ -265,7 +270,11 @@ void StatsWindow::setFactions (const FactionList& factions) void StatsWindow::setBirthSign (const std::string& signId) { - birthSignId = signId; + if (signId != birthSignId) + { + birthSignId = signId; + mChanged = true; + } } void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) @@ -376,6 +385,10 @@ void StatsWindow::updateSkillArea() } skillWidgets.clear(); + skillScrollerWidget->setScrollPosition(0); + onScrollChangePosition(skillScrollerWidget, 0); + clientHeight = 0; + const int valueSize = 40; MyGUI::IntCoord coord1(10, 0, skillClientWidget->getWidth() - (10 + valueSize), 18); MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index ecda22ee0..677b32935 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -38,8 +38,6 @@ namespace MWGui void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); void configureSkills (const SkillList& major, const SkillList& minor); - void setFactions (const FactionList& factions); - void setBirthSign (const std::string &signId); void setReputation (int reputation) { this->reputation = reputation; } void setBounty (int bounty) { this->bounty = bounty; } void updateSkillArea(); @@ -54,6 +52,9 @@ namespace MWGui void setupToolTips(); + void setFactions (const FactionList& factions); + void setBirthSign (const std::string &signId); + void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onWindowResize(MyGUI::Window* window); void onMouseWheel(MyGUI::Widget* _sender, int _rel); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 9246af1fe..2cacf2346 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -54,7 +54,6 @@ WindowManager::WindowManager( , playerClass() , playerName() , playerRaceId() - , playerBirthSignId() , playerAttributes() , playerMajorSkills() , playerMinorSkills() @@ -395,12 +394,6 @@ void WindowManager::configureSkills (const SkillList& major, const SkillList& mi playerMinorSkills = minor; } -void WindowManager::setBirthSign (const std::string &signId) -{ - mStatsWindow->setBirthSign (signId); - playerBirthSignId = signId; -} - void WindowManager::setReputation (int reputation) { mStatsWindow->setReputation (reputation); @@ -473,7 +466,7 @@ void WindowManager::onFrame (float frameDuration) mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition()); } - mInventoryWindow->update(); + mInventoryWindow->onFrame(); mStatsWindow->onFrame(); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index cdcace85d..22fe973a5 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -161,7 +161,6 @@ namespace MWGui void setPlayerClass (const ESM::Class &class_); ///< set current class of player void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. - void setBirthSign (const std::string &signId); ///< set birth sign to display on stat window, use an empty string to disable. void setReputation (int reputation); ///< set the current reputation value void setBounty (int bounty); ///< set the current bounty value void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty @@ -238,7 +237,6 @@ namespace MWGui ESM::Class playerClass; std::string playerName; std::string playerRaceId; - std::string playerBirthSignId; std::map > playerAttributes; SkillList playerMajorSkills, playerMinorSkills; std::map > playerSkillValues; diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index 4d63b03c2..86ef65324 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -35,11 +35,21 @@ - - - - - + + + + + + + + + + + + + + + From 9f1919a230e5d6dbb0a2cf2491569169cf2bed25 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 19 May 2012 15:01:07 +0200 Subject: [PATCH 145/289] Issue #256: added active spell management (completely untested) --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwmechanics/activespells.cpp | 162 ++++++++++++++++++++++ apps/openmw/mwmechanics/activespells.hpp | 58 ++++++++ apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/creaturestats.hpp | 2 + 5 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwmechanics/activespells.cpp create mode 100644 apps/openmw/mwmechanics/activespells.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7e5dcc1e2..ca2355346 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -58,6 +58,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells + activespells ) add_openmw_dir (mwbase diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp new file mode 100644 index 000000000..ced2a5c3f --- /dev/null +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -0,0 +1,162 @@ + +#include "activespells.hpp" + +#include + +#include "../mwbase/environment.hpp" + +#include "../mwworld/world.hpp" + +namespace MWMechanics +{ + void ActiveSpells::update() const + { + bool rebuild = false; + + MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp(); + + if (mLastUpdate!=now) + { + TContainer::iterator iter (mSpells.begin()); + while (iter!=mSpells.end()) + if (!timeToExpire (iter)) + { + mSpells.erase (iter++); + rebuild = true; + } + else + ++iter; + + mLastUpdate = now; + } + + if (mSpellsChanged) + { + mSpellsChanged = false; + rebuild = true; + } + + if (rebuild) + { + mEffects = MagicEffects(); + + for (TIterator iter (begin()); iter!=end(); ++iter) + { + const ESM::Spell& spell = + *MWBase::Environment::get().getWorld()->getStore().spells.find (iter->first); + + const MWWorld::TimeStamp& start = iter->second.first; + float magnitude = iter->second.second; + + for (std::vector::const_iterator iter (spell.effects.list.begin()); + iter!=spell.effects.list.end(); ++iter) + { + if (iter->duration) + { + MWWorld::TimeStamp end = start; + end += static_cast (iter->duration)* + MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); + + if (end>now) + { + EffectParam param; + param.mMagnitude = static_cast ( + (iter->magnMax-iter->magnMin+1)*magnitude + iter->magnMin); + mEffects.add (*iter, param); + } + } + } + } + } + } + + ActiveSpells::ActiveSpells() + : mSpellsChanged (false), mLastUpdate (MWBase::Environment::get().getWorld()->getTimeStamp()) + {} + + void ActiveSpells::addSpell (const std::string& id) + { + const ESM::Spell& spell = *MWBase::Environment::get().getWorld()->getStore().spells.find (id); + + bool found = false; + + for (std::vector::const_iterator iter (spell.effects.list.begin()); + iter!=spell.effects.list.end(); ++iter) + { + if (iter->duration) + { + found = true; + break; + } + } + + if (!found) + return; + + TContainer::iterator iter = mSpells.find (id); + + float random = static_cast (std::rand()) / RAND_MAX; + + if (iter==mSpells.end()) + mSpells.insert (std::make_pair (id, + std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random))); + else + iter->second = std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random); + + mSpellsChanged = true; + } + + void ActiveSpells::removeSpell (const std::string& id) + { + TContainer::iterator iter = mSpells.find (id); + + if (iter!=mSpells.end()) + { + mSpells.erase (iter); + mSpellsChanged = true; + } + } + + const MagicEffects& ActiveSpells::getMagicEffects() const + { + update(); + return mEffects; + } + + ActiveSpells::TIterator ActiveSpells::begin() const + { + update(); + return mSpells.begin(); + } + + ActiveSpells::TIterator ActiveSpells::end() const + { + update(); + return mSpells.end(); + } + + double ActiveSpells::timeToExpire (const TIterator& iterator) const + { + const ESM::Spell& spell = + *MWBase::Environment::get().getWorld()->getStore().spells.find (iterator->first); + + int duration = 0; + + for (std::vector::const_iterator iter (spell.effects.list.begin()); + iter!=spell.effects.list.end(); ++iter) + { + if (iter->duration>duration) + duration = iter->duration; + } + + double scaledDuration = duration * + MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); + + double usedUp = MWBase::Environment::get().getWorld()->getTimeStamp()-iterator->second.first; + + if (usedUp>=scaledDuration) + return 0; + + return scaledDuration-usedUp; + } +} diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp new file mode 100644 index 000000000..179321c58 --- /dev/null +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -0,0 +1,58 @@ +#ifndef GAME_MWMECHANICS_ACTIVESPELLS_H +#define GAME_MWMECHANICS_ACTIVESPELLS_H + +#include +#include +#include + +#include "../mwworld/timestamp.hpp" + +#include "magiceffects.hpp" + +namespace ESM +{ + struct Spell; +} + +namespace MWMechanics +{ + /// \brief Lasting spell effects + class ActiveSpells + { + public: + + typedef std::map > TContainer; + typedef TContainer::const_iterator TIterator; + + private: + + mutable TContainer mSpells; // spellId, (time of casting, relative magnitude) + mutable MagicEffects mEffects; + mutable bool mSpellsChanged; + mutable MWWorld::TimeStamp mLastUpdate; + + void update() const; + + public: + + ActiveSpells(); + + void addSpell (const std::string& id); + ///< Overwrites an existing spell with the same ID. If the spell does not have any + /// non-instant effects, it is ignored. + + void removeSpell (const std::string& id); + + const MagicEffects& getMagicEffects() const; + + TIterator begin() const; + + TIterator end() const; + + double timeToExpire (const TIterator& iterator) const; + ///< Returns time (in in-game hours) until the spell pointed to by \a iterator + /// expires. + }; +} + +#endif diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index cd2dbaddf..5a17d50e4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -53,7 +53,7 @@ namespace MWMechanics now += store.getMagicEffects(); } - /// \todo add effects from active spells + now += creatureStats.mActiveSpells.getMagicEffects(); MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now); diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index ab008da9e..cc3c409da 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -7,6 +7,7 @@ #include "stat.hpp" #include "magiceffects.hpp" #include "spells.hpp" +#include "activespells.hpp" namespace MWMechanics { @@ -16,6 +17,7 @@ namespace MWMechanics DynamicStat mDynamic[3]; // health, magicka, fatigue int mLevel; Spells mSpells; + ActiveSpells mActiveSpells; MagicEffects mMagicEffects; }; } From 7a4de0ed1d527c018bc5f565ed9d007b8a6a82bb Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 15:32:32 +0200 Subject: [PATCH 146/289] changed more gui stuff to use the new tag system --- apps/openmw/mwgui/birth.cpp | 1 - apps/openmw/mwgui/class.cpp | 3 -- apps/openmw/mwgui/race.cpp | 1 - apps/openmw/mwgui/review.cpp | 5 ---- apps/openmw/mwgui/stats_window.cpp | 6 ---- apps/openmw/mwgui/tradewindow.cpp | 6 ---- files/mygui/openmw_chargen_birth_layout.xml | 2 +- files/mygui/openmw_chargen_class_layout.xml | 2 +- .../openmw_chargen_create_class_layout.xml | 2 +- ...w_chargen_generate_class_result_layout.xml | 2 +- files/mygui/openmw_chargen_race_layout.xml | 2 +- files/mygui/openmw_chargen_review_layout.xml | 30 ++++++++++++++----- .../mygui/openmw_inventory_window_layout.xml | 6 +--- files/mygui/openmw_stats_window_layout.xml | 24 +++++++++++---- files/mygui/openmw_trade_window_layout.xml | 12 ++++++-- 15 files changed, 55 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index cb15eaf15..49f90d1a0 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -27,7 +27,6 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager) MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked); MyGUI::ButtonPtr okButton; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index e654f7c90..3e41fa6b1 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -28,7 +28,6 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked); MyGUI::ButtonPtr okButton; @@ -111,7 +110,6 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager) MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); @@ -432,7 +430,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 275759c9f..f18bdb41f 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -71,7 +71,6 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager) MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked); MyGUI::ButtonPtr okButton; diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 81a87b07b..5059efb34 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -27,25 +27,21 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) ButtonPtr button; getWidget(nameWidget, "NameText"); getWidget(button, "NameButton"); - button->setCaption(mWindowManager.getGameSettingString("sName", "")); adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);; getWidget(raceWidget, "RaceText"); getWidget(button, "RaceButton"); - button->setCaption(mWindowManager.getGameSettingString("sRace", "")); adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);; getWidget(classWidget, "ClassText"); getWidget(button, "ClassButton"); - button->setCaption(mWindowManager.getGameSettingString("sClass", "")); adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);; getWidget(birthSignWidget, "SignText"); getWidget(button, "SignButton"); - button->setCaption(mWindowManager.getGameSettingString("sBirthSign", "")); adjustButtonSize(button); button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);; @@ -92,7 +88,6 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) MyGUI::ButtonPtr backButton; getWidget(backButton, "BackButton"); - backButton->setCaption(mWindowManager.getGameSettingString("sBack", "")); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked); MyGUI::ButtonPtr okButton; diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 30d63033b..06576b42b 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -49,12 +49,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) { "Attrib6", "sAttributeEndurance" }, { "Attrib7", "sAttributePersonality" }, { "Attrib8", "sAttributeLuck" }, - { "Health_str", "sHealth" }, - { "Magicka_str", "sMagic" }, - { "Fatigue_str", "sFatigue" }, - { "Level_str", "sLevel" }, - { "Race_str", "sRace" }, - { "Class_str", "sClass" }, { 0, 0 } }; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 2dcf7c7f8..3570ea6a3 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -41,12 +41,6 @@ namespace MWGui getWidget(mTotalBalanceLabel, "TotalBalanceLabel"); getWidget(mBottomPane, "BottomPane"); - // this GMST doesn't seem to get retrieved - even though i can clearly see it in the CS !??!? - mMaxSaleButton->setCaption(mWindowManager.getGameSettingString("sMaxSale", "Max. Sale")); - - mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); - mOfferButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog8")->str); - // adjust size of buttons to fit text int curX = 0; mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height ); diff --git a/files/mygui/openmw_chargen_birth_layout.xml b/files/mygui/openmw_chargen_birth_layout.xml index bce3f585d..0599ab863 100644 --- a/files/mygui/openmw_chargen_birth_layout.xml +++ b/files/mygui/openmw_chargen_birth_layout.xml @@ -15,7 +15,7 @@ - + diff --git a/files/mygui/openmw_chargen_class_layout.xml b/files/mygui/openmw_chargen_class_layout.xml index bf49810c8..38fa606ab 100644 --- a/files/mygui/openmw_chargen_class_layout.xml +++ b/files/mygui/openmw_chargen_class_layout.xml @@ -55,7 +55,7 @@ - + diff --git a/files/mygui/openmw_chargen_create_class_layout.xml b/files/mygui/openmw_chargen_create_class_layout.xml index 3b7d91b00..be6a10e0c 100644 --- a/files/mygui/openmw_chargen_create_class_layout.xml +++ b/files/mygui/openmw_chargen_create_class_layout.xml @@ -56,7 +56,7 @@ - + diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml index 26ebe17e1..9a6ed4f2e 100644 --- a/files/mygui/openmw_chargen_generate_class_result_layout.xml +++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml @@ -21,7 +21,7 @@ - + diff --git a/files/mygui/openmw_chargen_race_layout.xml b/files/mygui/openmw_chargen_race_layout.xml index 6887b12c5..a9b072f5e 100644 --- a/files/mygui/openmw_chargen_race_layout.xml +++ b/files/mygui/openmw_chargen_race_layout.xml @@ -61,7 +61,7 @@ - + diff --git a/files/mygui/openmw_chargen_review_layout.xml b/files/mygui/openmw_chargen_review_layout.xml index c713eb477..57bb3b124 100644 --- a/files/mygui/openmw_chargen_review_layout.xml +++ b/files/mygui/openmw_chargen_review_layout.xml @@ -5,10 +5,18 @@ - - - - + + + + + + + + + + + + @@ -17,9 +25,15 @@ - - - + + + + + + + + + @@ -42,7 +56,7 @@ - + diff --git a/files/mygui/openmw_inventory_window_layout.xml b/files/mygui/openmw_inventory_window_layout.xml index 86ef65324..b38e15fc7 100644 --- a/files/mygui/openmw_inventory_window_layout.xml +++ b/files/mygui/openmw_inventory_window_layout.xml @@ -7,11 +7,7 @@ - - - - - + diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 9406fe6bd..8b6080227 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -7,9 +7,15 @@ - - - + + + + + + + + + @@ -20,9 +26,15 @@ - - - + + + + + + + + + diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index 8a4e00433..83d7557d9 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -51,9 +51,15 @@ - - - + + + + + + + + + From 4fb30544d4b101437dc0411c57cc62afd0a9cb02 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 16:00:00 +0200 Subject: [PATCH 147/289] more gui files cleanup --- apps/openmw/mwgui/container.cpp | 3 --- apps/openmw/mwgui/dialogue.cpp | 1 - apps/openmw/mwgui/hud.cpp | 3 --- apps/openmw/mwgui/map_window.cpp | 5 ----- files/mygui/openmw_container_window_layout.xml | 8 ++++++-- files/mygui/openmw_dialogue_window_layout.xml | 2 +- files/mygui/openmw_hud_layout.xml | 11 +++++++---- files/mygui/openmw_map_window_layout.xml | 4 +++- files/mygui/openmw_trade_window_layout.xml | 2 +- 9 files changed, 18 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5595825fc..be21987ef 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -603,9 +603,6 @@ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dr mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); - setText("CloseButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sClose")->str); - setText("TakeButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTakeAll")->str); - // adjust buttons size to fit text int closeButtonWidth = mCloseButton->getTextSize().width+24; int takeButtonWidth = mTakeButton->getTextSize().width+24; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 9f5e252fd..53ab98aeb 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -69,7 +69,6 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager) MyGUI::ButtonPtr byeButton; getWidget(byeButton, "ByeButton"); byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked); - byeButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGoodbye")->str); getWidget(pDispositionBar, "Disposition"); getWidget(pDispositionText,"DispositionText"); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 34d5ece98..4a65458df 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -77,9 +77,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(trianglecounter, "TriangleCounter"); getWidget(batchcounter, "BatchCounter"); - compass->setImageTexture("textures\\compass.dds"); - crosshair->setImageTexture("textures\\target.dds"); - // These are just demo values, you should replace these with // real calls from outside the class later. setWeapIcon("icons\\w\\tx_knife_iron.dds"); diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 9000d2fcb..78ca70798 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -95,11 +95,6 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : mGlobal(false) { setCoord(500,0,320,300); - setText("WorldButton", "World"); - setImage("Compass", "textures\\compass.dds"); - - // Obviously you should override this later on - setCellName("No Cell Loaded"); getWidget(mLocalMap, "LocalMap"); getWidget(mGlobalMap, "GlobalMap"); diff --git a/files/mygui/openmw_container_window_layout.xml b/files/mygui/openmw_container_window_layout.xml index cb66fadc1..ae9b0bfdf 100644 --- a/files/mygui/openmw_container_window_layout.xml +++ b/files/mygui/openmw_container_window_layout.xml @@ -12,8 +12,12 @@ - - + + + + + + diff --git a/files/mygui/openmw_dialogue_window_layout.xml b/files/mygui/openmw_dialogue_window_layout.xml index d45de4bd4..1271a287b 100644 --- a/files/mygui/openmw_dialogue_window_layout.xml +++ b/files/mygui/openmw_dialogue_window_layout.xml @@ -24,7 +24,7 @@ - + diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 2dafa7298..0c5ffba6a 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -62,7 +62,10 @@ - + + + + @@ -85,9 +88,9 @@ - - + + + - + + + diff --git a/files/mygui/openmw_trade_window_layout.xml b/files/mygui/openmw_trade_window_layout.xml index 83d7557d9..c8a9f2523 100644 --- a/files/mygui/openmw_trade_window_layout.xml +++ b/files/mygui/openmw_trade_window_layout.xml @@ -58,7 +58,7 @@ - + From 2a4c55f1abd5cd00b62ce920bf954d66dc745fc2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 16:04:34 +0200 Subject: [PATCH 148/289] use Class::getInventoryStore instead of casting ContainerStore. --- apps/openmw/mwgui/inventorywindow.cpp | 8 ++++---- apps/openmw/mwgui/tradewindow.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index a0326debc..49b441af3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -142,7 +142,7 @@ namespace MWGui if (mDragAndDrop->mDraggedFrom != this) { // add item to the player's inventory - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStoreIterator it = invStore.begin(); int origCount = ptr.getRefData().getCount(); @@ -179,7 +179,7 @@ namespace MWGui std::vector InventoryWindow::getEquippedItems() { - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); std::vector items; @@ -197,7 +197,7 @@ namespace MWGui void InventoryWindow::_unequipItem(MWWorld::Ptr item) { - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -231,7 +231,7 @@ namespace MWGui int InventoryWindow::getPlayerGold() { - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 3570ea6a3..60cc06cb8 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -268,7 +268,7 @@ namespace MWGui return items; } - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -327,7 +327,7 @@ namespace MWGui std::vector TradeWindow::itemsToIgnore() { std::vector items; - MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) From 92d9e070fb6e2cc634f9cde03b807544457a8b37 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 16:10:13 +0200 Subject: [PATCH 149/289] small tweak to getPlayerGold() method --- apps/openmw/mwgui/inventorywindow.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 49b441af3..59be6a495 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -21,6 +21,19 @@ #include "bookwindow.hpp" #include "scrollwindow.hpp" +namespace +{ + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } +} + namespace MWGui { @@ -236,7 +249,7 @@ namespace MWGui for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + if (toLower(it->getCellRef().refID) == "gold_001") return it->getRefData().getCount(); } return 0; From 876b369ca544d8a3321fe6448329e3c089e5b6c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 19 May 2012 16:28:10 +0200 Subject: [PATCH 150/289] minor tooltip fix --- apps/openmw/mwgui/tooltips.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 6f8434535..e986b59be 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -298,6 +298,9 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) const int chargeTextWidth = chargeText->getTextSize().width + 5; const int chargeAndTextWidth = chargeWidth + chargeTextWidth; + + totalSize.width = std::max(totalSize.width, chargeAndTextWidth); + chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18); IntCoord chargeCoord; From be46f5a59cdb8c2c8220ea25d2b70ef5d05f8629 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 19 May 2012 17:39:24 +0200 Subject: [PATCH 151/289] various fixes --- apps/openmw/mwworld/inventorystore.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 6981aea02..98ab1665b 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -44,13 +44,17 @@ MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false) } MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) -: ContainerStore (store), mMagicEffectsUpToDate (false) +: ContainerStore (store) { + mMagicEffects = store.mMagicEffects; + mMagicEffectsUpToDate = store.mMagicEffectsUpToDate; copySlots (store); } MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store) { + mMagicEffects = store.mMagicEffects; + mMagicEffectsUpToDate = store.mMagicEffectsUpToDate; ContainerStore::operator= (store); mSlots.clear(); copySlots (store); @@ -236,6 +240,7 @@ const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() void MWWorld::InventoryStore::flagAsModified() { + ContainerStore::flagAsModified(); mMagicEffectsUpToDate = false; } From 8d52ee27dcaa8b70841eaa0f127d97afb031b565 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 May 2012 22:06:54 +0200 Subject: [PATCH 152/289] attribute tooltips now use a new system that allows complex tooltips to be defined entirely through layout files --- apps/openmw/mwgui/stats_window.cpp | 146 ++++++++++++++++------------- apps/openmw/mwgui/tooltips.cpp | 64 +++++++++++-- files/mygui/openmw_tooltips.xml | 20 ++++ 3 files changed, 160 insertions(+), 70 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 06576b42b..480b85265 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -459,91 +459,109 @@ void StatsWindow::setupToolTips() const ESMS::ESMStore &store = mWindowManager.getStore(); MyGUI::Widget* widget; + /// \todo move this into the .layout file! + getWidget(widget, "Attrib1"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_strength.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); getWidget(widget, "AttribVal1"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_strength.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); getWidget(widget, "Attrib2"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_int.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); getWidget(widget, "AttribVal2"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_int.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); getWidget(widget, "Attrib3"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); getWidget(widget, "AttribVal3"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); getWidget(widget, "Attrib4"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_agility.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); getWidget(widget, "AttribVal4"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_agility.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); getWidget(widget, "Attrib5"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_speed.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); getWidget(widget, "AttribVal5"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_speed.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); getWidget(widget, "Attrib6"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); getWidget(widget, "AttribVal6"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); getWidget(widget, "Attrib7"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_personality.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); getWidget(widget, "AttribVal7"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_personality.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); getWidget(widget, "Attrib8"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_luck.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); getWidget(widget, "AttribVal8"); - widget->setUserString("ToolTipType", "ImageCaptionText"); - widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ToolTipImage", "k\\attribute_luck.dds"); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); + widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); + widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index e986b59be..edb93320d 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -42,11 +42,16 @@ void ToolTips::onFrame(float frameDuration) IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), Align::Stretch, "DynamicToolTipBox"); + // start by hiding everything + for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i) + { + mMainWidget->getChildAt(i)->setVisible(false); + } + const IntSize &viewSize = RenderManager::getInstance().getViewSize(); if (!mEnabled) { - mDynamicToolTipBox->setVisible(false); return; } @@ -55,7 +60,6 @@ void ToolTips::onFrame(float frameDuration) Widget* focus = InputManager::getInstance().getMouseFocusWidget(); if (focus == 0) { - mDynamicToolTipBox->setVisible(false); return; } @@ -67,7 +71,6 @@ void ToolTips::onFrame(float frameDuration) ToolTipInfo info; if (type == "") { - mDynamicToolTipBox->setVisible(false); return; } else if (type == "Text") @@ -98,6 +101,54 @@ void ToolTips::onFrame(float frameDuration) mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); } + else if (type == "Layout") + { + // tooltip defined in the layout + MyGUI::Widget* tooltip; + getWidget(tooltip, focus->getUserString("ToolTipLayout")); + + tooltip->setVisible(true); + tooltip->setCoord(0, 0, 300, 300); + + tooltipSize = MyGUI::IntSize(0,0); + + std::map userStrings = focus->getUserStrings(); + for (std::map::iterator it = userStrings.begin(); + it != userStrings.end(); ++it) + { + if (it->first == "ToolTipType" + || it->first == "ToolTipLayout") + continue; + + + size_t underscorePos = it->first.find("_"); + std::string propertyKey = it->first.substr(0, underscorePos); + std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); + + MyGUI::Widget* w; + getWidget(w, widgetName); + w->setProperty(propertyKey, it->second); + } + + for (unsigned int i=0; igetChildCount(); ++i) + { + MyGUI::Widget* w = tooltip->getChildAt(i); + + if (w->isUserString("AutoResizeHorizontal")) + { + MyGUI::TextBox* text = w->castType(); + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); + } + + if (w->isUserString("AutoResizeVertical")) + { + MyGUI::TextBox* text = w->castType(); + tooltipSize.height = std::max(tooltipSize.height, w->getTop() + text->getTextSize().height + 8); + } + } + + tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); + } IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); @@ -112,7 +163,6 @@ void ToolTips::onFrame(float frameDuration) } setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); - mDynamicToolTipBox->setVisible(true); } else { @@ -124,9 +174,9 @@ void ToolTips::onFrame(float frameDuration) std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)), tooltipSize.width, tooltipSize.height); + + mDynamicToolTipBox->setVisible(true); } - else - mDynamicToolTipBox->setVisible(false); } } @@ -186,6 +236,8 @@ void ToolTips::findImageExtension(std::string& image) IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) { + mDynamicToolTipBox->setVisible(true); + std::string caption = info.caption; std::string image = info.icon; int imageSize = (image != "") ? 32 : 0; diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 2d5a5da9f..3c6c98ea9 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -8,6 +8,26 @@ + + + + + + + + + + + + + + + + + + + + From 1c7110fbf5022a7f3025866c51ebc91a1957105b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 May 2012 22:45:30 +0200 Subject: [PATCH 153/289] birthsign tooltip --- apps/openmw/mwgui/stats_window.cpp | 61 +++++++++++++++++++++++++++++- apps/openmw/mwgui/stats_window.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 4 ++ files/mygui/openmw_text.skin.xml | 3 ++ files/mygui/openmw_tooltips.xml | 18 +++++++++ 5 files changed, 85 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 480b85265..092ceaeb6 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -322,7 +322,7 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st return skillValueWidget; } -void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::Widget* StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* skillNameWidget; @@ -334,6 +334,8 @@ void StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI coord1.top += lineHeight; coord2.top += lineHeight; + + return skillNameWidget; } void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) @@ -422,7 +424,62 @@ void StatsWindow::updateSkillArea() addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); - addItem(sign->name, coord1, coord2); + MyGUI::Widget* w = addItem(sign->name, coord1, coord2); + w->setUserString("ToolTipType", "Layout"); + w->setUserString("ToolTipLayout", "BirthSignToolTip"); + std::string image = sign->texture; + image.replace(image.size()-3, 3, "dds"); + w->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); + std::string text; + + text += sign->name; + text += "\n#BF9959" + sign->description; + + std::vector abilities, powers, spells; + + std::vector::const_iterator it = sign->powers.list.begin(); + std::vector::const_iterator end = sign->powers.list.end(); + for (; it != end; ++it) + { + const std::string &spellId = *it; + const ESM::Spell *spell = store.spells.search(spellId); + if (!spell) + continue; // Skip spells which cannot be found + ESM::Spell::SpellType type = static_cast(spell->data.type); + if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) + continue; // We only want spell, ability and powers. + + if (type == ESM::Spell::ST_Ability) + abilities.push_back(spellId); + else if (type == ESM::Spell::ST_Power) + powers.push_back(spellId); + else if (type == ESM::Spell::ST_Spell) + spells.push_back(spellId); + } + + struct{ const std::vector &spells; std::string label; } categories[3] = { + {abilities, "sBirthsignmenu1"}, + {powers, "sPowers"}, + {spells, "sBirthsignmenu2"} + }; + + for (int category = 0; category < 3; ++category) + { + for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) + { + if (it == categories[category].spells.begin()) + { + text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; + } + + const std::string &spellId = *it; + + const ESM::Spell *spell = store.spells.search(spellId); + text += "\n#BF9959" + spell->name; + } + } + + w->setUserString("Caption_BirthSignText", text); } // Add a line separator if there are items above diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 677b32935..fe7be0459 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -47,7 +47,7 @@ namespace MWGui void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); void setupToolTips(); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index edb93320d..47907ec94 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -139,12 +139,16 @@ void ToolTips::onFrame(float frameDuration) MyGUI::TextBox* text = w->castType(); tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); } + else + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); if (w->isUserString("AutoResizeVertical")) { MyGUI::TextBox* text = w->castType(); tooltipSize.height = std::max(tooltipSize.height, w->getTop() + text->getTextSize().height + 8); } + else + tooltipSize.height = std::max(tooltipSize.height, w->getTop() + w->getHeight() + 8); } tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 36d97e153..6b62f618d 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -1,6 +1,8 @@ + + @@ -15,6 +17,7 @@ + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 3c6c98ea9..1913095a8 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -28,6 +28,24 @@ + + + + + + + + + + + + + + + + + + From 6518eb7794a6e4a7bbe0291c9780e81e0a5b97f2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 May 2012 22:55:14 +0200 Subject: [PATCH 154/289] some cleanup --- apps/openmw/mwgui/stats_window.cpp | 10 ++++++---- apps/openmw/mwgui/tooltips.cpp | 25 ++----------------------- files/mygui/openmw_tooltips.xml | 13 +++++++++++++ 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 092ceaeb6..33d9f02c8 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -302,13 +302,15 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); skillNameWidget->setCaption(text); - skillNameWidget->setUserString("ToolTipType", "Text"); - skillNameWidget->setUserString("ToolTipText", tooltip); + skillNameWidget->setUserString("ToolTipType", "Layout"); + skillNameWidget->setUserString("ToolTipLayout", "TextToolTip"); + skillNameWidget->setUserString("Caption_Text", tooltip); skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); - skillValueWidget->setUserString("ToolTipType", "Text"); - skillValueWidget->setUserString("ToolTipText", tooltip); + skillNameWidget->setUserString("ToolTipType", "Layout"); + skillNameWidget->setUserString("ToolTipLayout", "TextToolTip"); + skillNameWidget->setUserString("Caption_Text", tooltip); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 47907ec94..df06bd93e 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -72,29 +72,6 @@ void ToolTips::onFrame(float frameDuration) if (type == "") { return; - } - else if (type == "Text") - { - info.text = text; - tooltipSize = createToolTip(info); - } - else if (type == "CaptionText") - { - std::string caption = focus->getUserString("ToolTipCaption"); - info.caption = caption; - info.text = text; - tooltipSize = createToolTip(info); - } - else if (type == "ImageCaptionText") - { - std::string caption = focus->getUserString("ToolTipCaption"); - std::string image = focus->getUserString("ToolTipImage"); - std::string sizeString = focus->getUserString("ToolTipImageSize"); - - info.text = text; - info.caption = caption; - info.icon = image; - tooltipSize = createToolTip(info); } else if (type == "ItemPtr") { @@ -153,6 +130,8 @@ void ToolTips::onFrame(float frameDuration) tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); } + else + throw std::runtime_error ("unknown tooltip type"); IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 1913095a8..414991664 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -8,6 +8,19 @@ + + + + + + + + + + + + + From 8ce472742485c586a04635714bf4205741fdd6cf Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 01:58:11 +0200 Subject: [PATCH 155/289] skill tooltips --- apps/openmw/mwgui/stats_window.cpp | 48 +++++++++++++++++++++++------- apps/openmw/mwgui/stats_window.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 14 ++++++--- components/esm/loadskil.cpp | 29 ++++++++++++++++++ components/esm/loadskil.hpp | 1 + files/mygui/openmw_tooltips.xml | 37 +++++++++++++++++++++++ 6 files changed, 116 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 33d9f02c8..fbc439b23 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -296,21 +296,15 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My coord2.top += lineHeight; } -MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox *skillNameWidget, *skillValueWidget; skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); skillNameWidget->setCaption(text); - skillNameWidget->setUserString("ToolTipType", "Layout"); - skillNameWidget->setUserString("ToolTipLayout", "TextToolTip"); - skillNameWidget->setUserString("Caption_Text", tooltip); skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); - skillNameWidget->setUserString("ToolTipType", "Layout"); - skillNameWidget->setUserString("ToolTipLayout", "TextToolTip"); - skillNameWidget->setUserString("Caption_Text", tooltip); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); @@ -362,13 +356,34 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, float base = stat.getBase(); float modified = stat.getModified(); + const ESM::Skill* skill = mWindowManager.getStore().skills.search(skillId); + assert(skill); + + std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; + + const ESM::Attribute* attr = mWindowManager.getStore().attributes.search(skill->data.attribute); + assert(attr); + std::string state = "normal"; if (modified > base) state = "increased"; else if (modified < base) state = "decreased"; - MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "", + MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + + for (int i=0; i<2; ++i) + { + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "SkillToolTip"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillName", "#{"+skillNameId+"}"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->description); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", "0/100"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100"); + } + skillWidgetMap[skillId] = widget; } } @@ -489,12 +504,25 @@ void StatsWindow::updateSkillArea() addSeparator(coord1, coord2); addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), - mWindowManager.getGameSettingString("sSkillsMenuReputationHelp", ""), boost::lexical_cast(static_cast(reputation)), "normal", coord1, coord2); + + for (int i=0; i<2; ++i) + { + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sSkillsMenuReputationHelp}"); + } + addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), - mWindowManager.getGameSettingString("sCrimeHelp", ""), boost::lexical_cast(static_cast(bounty)), "normal", coord1, coord2); + for (int i=0; i<2; ++i) + { + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sCrimeHelp}"); + } + clientHeight = coord1.top; updateScroller(); } diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index fe7be0459..50a83bb29 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -46,7 +46,7 @@ namespace MWGui void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index df06bd93e..52ba391a6 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -87,7 +87,7 @@ void ToolTips::onFrame(float frameDuration) tooltip->setVisible(true); tooltip->setCoord(0, 0, 300, 300); - tooltipSize = MyGUI::IntSize(0,0); + tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); std::map userStrings = focus->getUserStrings(); for (std::map::iterator it = userStrings.begin(); @@ -122,10 +122,16 @@ void ToolTips::onFrame(float frameDuration) if (w->isUserString("AutoResizeVertical")) { MyGUI::TextBox* text = w->castType(); - tooltipSize.height = std::max(tooltipSize.height, w->getTop() + text->getTextSize().height + 8); + int height = text->getTextSize().height; + if (height > w->getHeight()) + { + tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); + } + if (height < w->getHeight()) + { + tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); + } } - else - tooltipSize.height = std::max(tooltipSize.height, w->getTop() + w->getHeight() + 8); } tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index aa7103efc..52869f440 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -31,6 +31,35 @@ namespace ESM "sSkillSpeechcraft", "sSkillHandtohand", }; + const std::string Skill::sIconNames[Length] = { + "combat_block.dds", + "combat_armor.dds", + "combat_mediumarmor.dds", + "combat_heavyarmor.dds", + "combat_blunt.dds", + "combat_longblade.dds", + "combat_axe.dds", + "combat_spear.dds", + "combat_athletics.dds", + "magic_enchant.dds", + "magic_destruction.dds", + "magic_alteration.dds", + "magic_illusion.dds", + "magic_conjuration.dds", + "magic_mysticism.dds", + "magic_restoration.dds", + "magic_alchemy.dds", + "magic_unarmored.dds", + "stealth_security.dds", + "stealth_sneak.dds", + "stealth_acrobatics.dds", + "stealth_lightarmor.dds", + "stealth_shortblade.dds", + "stealth_marksman.dds", + "stealth_mercantile.dds", + "stealth_speechcraft.dds", + "stealth_handtohand.dds", + }; const boost::array Skill::skillIds = {{ Block, Armorer, diff --git a/components/esm/loadskil.hpp b/components/esm/loadskil.hpp index 836f70205..f56ec2fcb 100644 --- a/components/esm/loadskil.hpp +++ b/components/esm/loadskil.hpp @@ -64,6 +64,7 @@ struct Skill Length }; static const std::string sSkillNameIds[Length]; + static const std::string sIconNames[Length]; static const boost::array skillIds; void load(ESMReader &esm); diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 414991664..af4d26775 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -41,6 +41,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4a009fc2bbe625b33de6c9635a831163afc3aa8a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 02:58:06 +0200 Subject: [PATCH 156/289] faction tooltip (doesn't handle player having max. rank) --- apps/openmw/mwgui/stats_window.cpp | 44 ++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index fbc439b23..de12559ca 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -428,8 +428,48 @@ void StatsWindow::updateSkillArea() for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) { const ESM::Faction *faction = store.factions.find(it->first); - addItem(faction->name, coord1, coord2); - // TODO: Faction rank should be placed in tooltip + MyGUI::Widget* w = addItem(faction->name, coord1, coord2); + + std::string text; + + text += std::string("#DDC79E") + faction->name; + text += std::string("\n#BF9959") + faction->ranks[it->second]; + + if (it->second < 10) + { + // player doesn't have max rank yet + text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->ranks[it->second+1]; + + ESM::RankData rankData = faction->data.rankData[it->second+1]; + const ESM::Attribute* attr1 = mWindowManager.getStore().attributes.search(faction->data.attribute1); + const ESM::Attribute* attr2 = mWindowManager.getStore().attributes.search(faction->data.attribute2); + assert(attr1 && attr2); + + text += "\n#BF9959#{" + attr1->name + "}: " + boost::lexical_cast(rankData.attribute1) + + ", #{" + attr2->name + "}: " + boost::lexical_cast(rankData.attribute2); + + text += "\n\n#DDC79E#{sFavoriteSkills}"; + text += "\n#BF9959"; + for (int i=0; i<6; ++i) + { + const ESM::Skill* skill = mWindowManager.getStore().skills.search(faction->data.skillID[i]); + assert(skill); + text += "#{"+ESM::Skill::sSkillNameIds[faction->data.skillID[i]]+"}"; + if (i<5) + text += ", "; + } + + text += "\n"; + + if (rankData.skill1 > 0) + text += "\n#{sNeedOneSkill} " + boost::lexical_cast(rankData.skill1); + if (rankData.skill2 > 0) + text += "\n#{sNeedTwoSkills} " + boost::lexical_cast(rankData.skill2); + } + + w->setUserString("ToolTipType", "Layout"); + w->setUserString("ToolTipLayout", "TextToolTip"); + w->setUserString("Caption_Text", text); } } From 76d71f86bcab17a547c8515d7b40acb7b2a0f43a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 03:10:55 +0200 Subject: [PATCH 157/289] fixed a faction case folding issue --- apps/openmw/mwclass/npc.cpp | 8 ++++++-- apps/openmw/mwdialogue/dialoguemanager.cpp | 6 +++--- apps/openmw/mwmechanics/npcstats.hpp | 1 + apps/openmw/mwscript/statsextensions.cpp | 6 ++++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index db0a6460c..e7f6cc527 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -3,6 +3,8 @@ #include +#include + #include #include @@ -56,13 +58,15 @@ namespace MWClass // NPC stats if (!ref->base->faction.empty()) { + std::string faction = ref->base->faction; + boost::algorithm::to_lower(faction); if(ref->base->npdt52.gold != -10) { - data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt52.rank; + data->mNpcStats.mFactionRank[faction] = (int)ref->base->npdt52.rank; } else { - data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt12.rank; + data->mNpcStats.mFactionRank[faction] = (int)ref->base->npdt12.rank; } } diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 2c4de7be1..dbd826127 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -206,7 +206,7 @@ namespace MWDialogue if(!NPCstats.mFactionRank.empty()) { std::string NPCFaction = NPCstats.mFactionRank.begin()->first; - if(PCstats.mFactionRank.find(NPCFaction) != PCstats.mFactionRank.end()) sameFaction = 1; + if(PCstats.mFactionRank.find(toLower(NPCFaction)) != PCstats.mFactionRank.end()) sameFaction = 1; } if(!selectCompare(comp,sameFaction,select.i)) return false; } @@ -525,7 +525,7 @@ namespace MWDialogue //MWWorld::Class npcClass = MWWorld::Class::get(actor); MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); - std::map::iterator it = stats.mFactionRank.find(info.npcFaction); + std::map::iterator it = stats.mFactionRank.find(toLower(info.npcFaction)); if(it!=stats.mFactionRank.end()) { //check rank @@ -542,7 +542,7 @@ namespace MWDialogue if(!info.pcFaction.empty()) { MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::map::iterator it = stats.mFactionRank.find(info.pcFaction); + std::map::iterator it = stats.mFactionRank.find(toLower(info.pcFaction)); if(it!=stats.mFactionRank.end()) { //check rank diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index feac5d4d3..972863b72 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -20,6 +20,7 @@ namespace MWMechanics { // NPCs other than the player can only have one faction. But for the sake of consistency // we use the same data structure for the PC and the NPCs. + /// \note the faction key must be in lowercase std::map mFactionRank; Stat mSkill[27]; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index cad52e593..d23519281 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1,6 +1,8 @@ #include "statsextensions.hpp" +#include + #include #include @@ -362,6 +364,7 @@ namespace MWScript factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } + boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); @@ -390,6 +393,7 @@ namespace MWScript factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } + boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); @@ -422,6 +426,7 @@ namespace MWScript factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } + boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); @@ -459,6 +464,7 @@ namespace MWScript factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.begin()->first; } } + boost::algorithm::to_lower(factionID); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(factionID!="") { From 1079bb26778afcf454b7aa0f01e0edee6574e53b Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 05:14:07 +0200 Subject: [PATCH 158/289] finished tooltips for everything in the stats window, some gui refactoring --- apps/openmw/mwgui/hud.cpp | 18 ++--- apps/openmw/mwgui/hud.hpp | 1 - apps/openmw/mwgui/stats_window.cpp | 52 +++++++++++++ apps/openmw/mwgui/tooltips.cpp | 12 ++- files/mygui/openmw_hud_layout.xml | 30 ++++++-- files/mygui/openmw_stats_window_layout.xml | 88 ++++++++++++++++++---- files/mygui/openmw_tooltips.xml | 79 ++++++++++++++++++- 7 files changed, 242 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 4a65458df..892bd6c7a 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -129,16 +129,6 @@ void HUD::setBatchCount(size_t count) batchcounter->setCaption(boost::lexical_cast(count)); } -void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax) -{ - health->setProgressRange(hmax); - health->setProgressPosition(h); - magicka->setProgressRange(mmax); - magicka->setProgressPosition(m); - stamina->setProgressRange(smax); - stamina->setProgressPosition(s); -} - void HUD::setWeapIcon(const char *str) { weapImage->setImageTexture(str); @@ -176,19 +166,27 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& v for (int i=0; ids[i]; ++i) if (ids[i]==id) { + MyGUI::Widget* w; + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); switch (i) { case 0: health->setProgressRange (value.getModified()); health->setProgressPosition (value.getCurrent()); + getWidget(w, "HealthFrame"); + w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); break; case 1: magicka->setProgressRange (value.getModified()); magicka->setProgressPosition (value.getCurrent()); + getWidget(w, "MagickaFrame"); + w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); break; case 2: stamina->setProgressRange (value.getModified()); stamina->setProgressPosition (value.getCurrent()); + getWidget(w, "FatigueFrame"); + w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); break; } } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index d588113dd..81f64ee50 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -12,7 +12,6 @@ namespace MWGui { public: HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); - void setStats(int h, int hmax, int m, int mmax, int s, int smax); void setWeapIcon(const char *str); void setSpellIcon(const char *str); void setWeapStatus(int s, int smax); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index de12559ca..eba51c26f 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -172,11 +172,32 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta }; for (int i=0; ids[i]; ++i) + { if (ids[i]==id) { std::string id (ids[i]); setBar (id, id + "T", value.getCurrent(), value.getModified()); + + // health, magicka, fatigue tooltip + MyGUI::Widget* w; + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + if (i==0) + { + getWidget(w, "Health"); + w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); + } + else if (i==1) + { + getWidget(w, "Magicka"); + w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); + } + else if (i==2) + { + getWidget(w, "Fatigue"); + w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); + } } + } } void StatsWindow::setValue (const std::string& id, const std::string& value) @@ -417,6 +438,37 @@ void StatsWindow::updateSkillArea() const ESMS::ESMStore &store = mWindowManager.getStore(); + // race tooltip + const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); + MyGUI::Widget* raceWidget; + getWidget(raceWidget, "RaceText"); + raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); + raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + getWidget(raceWidget, "Race_str"); + raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); + raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + + // class tooltip + MyGUI::Widget* classWidget; + const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); + int spec = playerClass.data.specialization; + std::string specStr; + if (spec == 0) + specStr = "#{sSpecializationCombat}"; + else if (spec == 1) + specStr = "#{sSpecializationMagic}"; + else if (spec == 2) + specStr = "#{sSpecializationStealth}"; + + getWidget(classWidget, "ClassText"); + classWidget->setUserString("Caption_ClassName", playerClass.name); + classWidget->setUserString("Caption_ClassDescription", playerClass.description); + classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + getWidget(classWidget, "Class_str"); + classWidget->setUserString("Caption_ClassName", playerClass.name); + classWidget->setUserString("Caption_ClassDescription", playerClass.description); + classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + if (!mFactions.empty()) { // Add a line separator if there are items above diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 52ba391a6..3ade598ba 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -85,9 +85,14 @@ void ToolTips::onFrame(float frameDuration) getWidget(tooltip, focus->getUserString("ToolTipLayout")); tooltip->setVisible(true); - tooltip->setCoord(0, 0, 300, 300); + if (!tooltip->isUserString("DontResize")) + { + tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping - tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + } + else + tooltipSize = tooltip->getSize(); std::map userStrings = focus->getUserStrings(); for (std::map::iterator it = userStrings.begin(); @@ -116,7 +121,7 @@ void ToolTips::onFrame(float frameDuration) MyGUI::TextBox* text = w->castType(); tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); } - else + else if (!tooltip->isUserString("DontResize")) tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); if (w->isUserString("AutoResizeVertical")) @@ -133,7 +138,6 @@ void ToolTips::onFrame(float frameDuration) } } } - tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); } else diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 0c5ffba6a..0aabc3e3e 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -3,12 +3,30 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 8b6080227..4729e3bca 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -7,37 +7,95 @@ - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + - - - diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index af4d26775..a1673d346 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -21,6 +21,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -78,6 +134,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -88,8 +165,6 @@ - - From 40c52c5d09eb9e16c2bdc371e4bfb26ac8a91793 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 05:19:20 +0200 Subject: [PATCH 159/289] max faction rank crashfix --- apps/openmw/mwgui/stats_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index eba51c26f..1dd82cf6a 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -487,7 +487,7 @@ void StatsWindow::updateSkillArea() text += std::string("#DDC79E") + faction->name; text += std::string("\n#BF9959") + faction->ranks[it->second]; - if (it->second < 10) + if (it->second < 9) { // player doesn't have max rank yet text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->ranks[it->second+1]; From b2d207130d88d17f4b944b44c9e9609092bcf778 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 08:14:22 +0200 Subject: [PATCH 160/289] vastly improved look of the GUI, skin background textures now use tiling instead of stretching --- files/mygui/openmw_box.skin.xml | 32 ++++++++--- files/mygui/openmw_button.skin.xml | 32 ++++++++--- files/mygui/openmw_hud_box.skin.xml | 36 ++++++++++--- files/mygui/openmw_list.skin.xml | 25 +++++++-- files/mygui/openmw_windows.skin.xml | 82 ++++++++++++++++++++--------- 5 files changed, 156 insertions(+), 51 deletions(-) diff --git a/files/mygui/openmw_box.skin.xml b/files/mygui/openmw_box.skin.xml index c1952794c..2a54edd60 100644 --- a/files/mygui/openmw_box.skin.xml +++ b/files/mygui/openmw_box.skin.xml @@ -6,23 +6,39 @@ as around the sections of the stats window, or around popup info windows --> - - + + + + + + - - + + + + + + - - + + + + + + - - + + + + + + diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml index 9efcf776f..491b3f47b 100644 --- a/files/mygui/openmw_button.skin.xml +++ b/files/mygui/openmw_button.skin.xml @@ -3,23 +3,39 @@ - - + + + + + + - - + + + + + + - - + + + + + + - - + + + + + + diff --git a/files/mygui/openmw_hud_box.skin.xml b/files/mygui/openmw_hud_box.skin.xml index bf1b0056a..86b63fcf6 100644 --- a/files/mygui/openmw_hud_box.skin.xml +++ b/files/mygui/openmw_hud_box.skin.xml @@ -3,18 +3,38 @@ - - + + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 213e8470f..e1fbc49b6 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -6,13 +6,32 @@ - - + + + + + + + + + + + + + + + + + + + + + @@ -144,7 +163,7 @@ - + diff --git a/files/mygui/openmw_windows.skin.xml b/files/mygui/openmw_windows.skin.xml index 7c194ea5d..b379f84ce 100644 --- a/files/mygui/openmw_windows.skin.xml +++ b/files/mygui/openmw_windows.skin.xml @@ -17,14 +17,22 @@ - - + + + + + + - - + + + + + + @@ -66,29 +74,45 @@ - - + + + + + + - - + + + + + + - - + + + + + + - - + + + + + + @@ -120,20 +144,32 @@ - - + + + + + + - - + + + + + + - - + + + + + + @@ -171,12 +207,8 @@ - - - - - - + + @@ -218,6 +250,7 @@ + @@ -294,6 +327,7 @@ + From 789dfe1c8865e24f1b398735521f3d48e83e0631 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 09:50:02 +0200 Subject: [PATCH 161/289] fix a bug with water reflection plane height --- apps/openmw/mwrender/water.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index c81f23f54..840b94e41 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -155,10 +155,10 @@ void Water::changeCell(const ESM::Cell* cell) { mTop = cell->water; + setHeight(mTop); + if(!(cell->data.flags & cell->Interior)) mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY)); - else - setHeight(mTop); } void Water::setHeight(const float height) From 5f6e8224f44ef47e69f71fd363532a1733755c5b Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:48:25 +0200 Subject: [PATCH 162/289] skill progress --- apps/openmw/mwgui/stats_window.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 1dd82cf6a..cdf6a5871 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -376,6 +376,7 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const MWMechanics::Stat &stat = skillValues.find(skillId)->second; float base = stat.getBase(); float modified = stat.getModified(); + int progressPercent = (modified - float(static_cast(modified))) * 100; const ESM::Skill* skill = mWindowManager.getStore().skills.search(skillId); assert(skill); @@ -401,8 +402,9 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->description); skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); skillWidgets[skillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon); - skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", "0/100"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", boost::lexical_cast(progressPercent)+"/100"); skillWidgets[skillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("RangePosition_SkillProgress", boost::lexical_cast(progressPercent)); } skillWidgetMap[skillId] = widget; From 157dd81524cd83c820d640f25e6439aa16bbec7c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:57:49 +0200 Subject: [PATCH 163/289] removed script instruction, will be in the settings window later --- apps/openmw/mwscript/docs/vmformat.txt | 1 - apps/openmw/mwscript/miscextensions.cpp | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 06e9a0ca7..de7248c0c 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -146,5 +146,4 @@ op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye -op 0x2000153: ToggleCompositors opcodes 0x2000154-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 1467b0aeb..fe1a642fd 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -194,22 +194,6 @@ namespace MWScript } }; - class OpToggleCompositors : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - InterpreterContext& context = - static_cast (runtime.getContext()); - - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode(MWWorld::World::Render_Compositors); - - context.report (enabled ? - "Compositors -> On" : "Compositors -> Off"); - } - }; - const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -224,7 +208,6 @@ namespace MWScript const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; - const int opcodeToggleCompositors = 0x2000153; void registerExtensions (Compiler::Extensions& extensions) { @@ -246,7 +229,6 @@ namespace MWScript extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); - extensions.registerInstruction ("togglecompositors", "", opcodeToggleCompositors); } void installOpcodes (Interpreter::Interpreter& interpreter) From bda90b77bcbd89c7348b88af504315892755a211 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:59:06 +0200 Subject: [PATCH 164/289] oops, forgot something --- apps/openmw/mwscript/miscextensions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index fe1a642fd..4ba523937 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -247,7 +247,6 @@ namespace MWScript interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); - interpreter.installSegment5 (opcodeToggleCompositors, new OpToggleCompositors); } } } From 3673cd2531743e8ece156644c842eec9af46a5c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:41:15 +0200 Subject: [PATCH 165/289] increased version number --- CMakeLists.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 668fcd83a..e11ad0c0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 14) +set (OPENMW_VERSION_MINOR 15) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") diff --git a/readme.txt b/readme.txt index 53f4a4c59..08e937010 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.14.0 +Version: 0.15.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org From 7aad0cc069daa098edb63461b7937d57b7d45a0f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:44:57 +0200 Subject: [PATCH 166/289] updated readme file --- readme.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/readme.txt b/readme.txt index 08e937010..a8a312e62 100644 --- a/readme.txt +++ b/readme.txt @@ -132,6 +132,31 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil CHANGELOG +0.15.0 + +Bug #5: Physics reimplementation (fixes various issues) +Bug #258: Resizing arrow's background is not transparent +Bug #268: Widening the stats window in X direction causes layout problems +Bug #269: Topic pane in dialgoue window is too small for some longer topics +Bug #271: Dialog choices are sorted incorrectly +Bug #281: The single quote character is not rendered on dialog windows +Bug #285: Terrain not handled properly in cells that are not predefined +Bug #289: Dialogue filter isn't doing case smashing/folding for item IDs +Feature #15: Collision with Terrain +Feature #17: Inventory-, Container- and Trade-Windows +Feature #44: Floating Labels above Focussed Objects +Feature #80: Tooltips +Feature #90: Book and Scroll Windows +Feature #156: Item Stacking in Containers +Feature #213: Pulsating lights +Feature #218: Feather & Burden +Feature #256: Implement magic effect bookkeeping +Feature #259: Add missing information to Stats window +Feature #260: Correct case for dialogue topics +Feature #280: GUI texture atlasing +Feature #291: Ability to use GMST strings from GUI layout files +Task #255: Make MWWorld::Environment into a singleton + 0.14.0 Bug #1: Meshes rendered with wrong orientation From b494533bb2c343fca3083fce34482ecd83f16631 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:54:23 +0200 Subject: [PATCH 167/289] another change to the readme file --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index a8a312e62..513474dd6 100644 --- a/readme.txt +++ b/readme.txt @@ -146,6 +146,7 @@ Feature #15: Collision with Terrain Feature #17: Inventory-, Container- and Trade-Windows Feature #44: Floating Labels above Focussed Objects Feature #80: Tooltips +Feature #83: Barter Dialogue Feature #90: Book and Scroll Windows Feature #156: Item Stacking in Containers Feature #213: Pulsating lights From 343bbaf0fd9a5cce41d8a027b22f65b6e5567f3e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 03:36:03 +0200 Subject: [PATCH 168/289] integrated video settings in the settings file, the launcher is now useless --- apps/openmw/engine.cpp | 34 ++-- components/files/configurationmanager.cpp | 7 - components/files/configurationmanager.hpp | 2 - files/settings-default.cfg | 23 +++ libs/openengine/ogre/renderer.cpp | 129 ++++++------ libs/openengine/ogre/renderer.hpp | 233 +++++++++++----------- 6 files changed, 216 insertions(+), 212 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 85b0557b1..a180849ff 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -268,15 +268,6 @@ void OMW::Engine::go() mOgre = new OEngine::Render::OgreRenderer; - //we need to ensure the path to the configuration exists before creating an - //instance of ogre root so that Ogre doesn't raise an exception when trying to - //access it - const boost::filesystem::path configPath = mCfgMgr.getOgreConfigPath().parent_path(); - if ( !boost::filesystem::exists(configPath) ) - { - boost::filesystem::create_directories(configPath); - } - // Create the settings manager and load default settings file Settings::Manager settings; const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; @@ -308,10 +299,20 @@ void OMW::Engine::go() else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg")) nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"); - mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), - mCfgMgr.getOgreConfigPath().string(), + std::string renderSystem = settings.getString("render system", "Video"); + if (renderSystem == "") + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + renderSystem = "Direct3D9 Rendering Subsystem"; +#else + renderSystem = "OpenGL Rendering Subsystem"; +#endif + } + mOgre->configure( mCfgMgr.getLogPath().string(), - mCfgMgr.getPluginsConfigPath().string(), false); + mCfgMgr.getPluginsConfigPath().string(), + renderSystem, + false); // This has to be added BEFORE MyGUI is initialized, as it needs // to find core.xml here. @@ -325,7 +326,14 @@ void OMW::Engine::go() addZipResource(mResDir / "mygui" / "Obliviontt.zip"); // Create the window - mOgre->createWindow("OpenMW"); + OEngine::Render::WindowSettings windowSettings; + windowSettings.fullscreen = settings.getBool("fullscreen", "Video"); + windowSettings.window_x = settings.getInt("resolution x", "Video"); + windowSettings.window_y = settings.getInt("resolution y", "Video"); + windowSettings.vsync = settings.getBool("vsync", "Video"); + std::string aa = settings.getString("antialiasing", "Video"); + windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; + mOgre->createWindow("OpenMW", windowSettings); loadBSA(); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index d5f322ebd..150a4fcd8 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -15,7 +15,6 @@ namespace Files { static const char* const openmwCfgFile = "openmw.cfg"; -static const char* const ogreCfgFile = "ogre.cfg"; static const char* const pluginsCfgFile = "plugins.cfg"; const char* const mwToken = "?mw?"; @@ -39,7 +38,6 @@ ConfigurationManager::ConfigurationManager() } } - mOgreCfgPath = mFixedPath.getUserPath() / ogreCfgFile; mLogPath = mFixedPath.getUserPath(); } @@ -164,11 +162,6 @@ const boost::filesystem::path& ConfigurationManager::getInstallPath() const return mFixedPath.getInstallPath(); } -const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const -{ - return mOgreCfgPath; -} - const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const { return mPluginsCfgPath; diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 7fb3793c6..af9d02b91 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -41,7 +41,6 @@ struct ConfigurationManager const boost::filesystem::path& getLocalDataPath() const; const boost::filesystem::path& getInstallPath() const; - const boost::filesystem::path& getOgreConfigPath() const; const boost::filesystem::path& getPluginsConfigPath() const; const boost::filesystem::path& getLogPath() const; @@ -59,7 +58,6 @@ struct ConfigurationManager FixedPathType mFixedPath; - boost::filesystem::path mOgreCfgPath; boost::filesystem::path mPluginsCfgPath; boost::filesystem::path mLogPath; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index e4a0c020a..81df50fb6 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -1,6 +1,29 @@ # WARNING: Editing this file might have no effect, as these # settings are overwritten by your user settings file. +[Video] +resolution x = 800 +resolution y = 600 + +fullscreen = false + +# Render system +# blank means default +# Valid values: +# OpenGL Rendering Subsystem +# Direct3D9 Rendering Subsystem +render system = + +# Valid values: +# none +# MSAA 2 +# MSAA 4 +# MSAA 8 +# MSAA 16 +antialiasing = none + +vsync = false + [General] # Camera field of view field of view = 55 diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 4ded3343f..4c8a10c3f 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -13,17 +13,17 @@ using namespace OEngine::Render; void OgreRenderer::cleanup() { - if (mFader) - delete mFader; - - if(mRoot) - delete mRoot; - mRoot = NULL; + if (mFader) + delete mFader; + + if(mRoot) + delete mRoot; + mRoot = NULL; } void OgreRenderer::start() { - mRoot->startRendering(); + mRoot->startRendering(); } bool OgreRenderer::loadPlugins() @@ -53,96 +53,79 @@ bool OgreRenderer::loadPlugins() void OgreRenderer::update(float dt) { - mFader->update(dt); + mFader->update(dt); } void OgreRenderer::screenshot(const std::string &file) { - mWindow->writeContentsToFile(file); + mWindow->writeContentsToFile(file); } float OgreRenderer::getFPS() { - return mWindow->getLastFPS(); + return mWindow->getLastFPS(); } -bool OgreRenderer::configure(bool showConfig, - const std::string &cfgPath, - const std::string &logPath, - const std::string &pluginCfg, - bool _logging) +void OgreRenderer::configure(const std::string &logPath, + const std::string &pluginCfg, + const std::string& renderSystem, + bool _logging) { - // Set up logging first - new LogManager; - Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); - logging = _logging; + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); + logging = _logging; - if(logging) - // Full log detail - log->setLogDetail(LL_BOREME); - else - // Disable logging - log->setDebugOutputEnabled(false); + if(logging) + // Full log detail + log->setLogDetail(LL_BOREME); + else + // Disable logging + log->setDebugOutputEnabled(false); -#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) - mRoot = new Root("", cfgPath, ""); - loadPlugins(); -#else - mRoot = new Root(pluginCfg, cfgPath, ""); -#endif + #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) + mRoot = new Root("", "", ""); + loadPlugins(); + #else + mRoot = new Root(pluginCfg, "", ""); + #endif - // Show the configuration dialog and initialise the system, if the - // showConfig parameter is specified. The settings are stored in - // ogre.cfg. If showConfig is false, the settings are assumed to - // already exist in ogre.cfg. - int result; - if(showConfig) - result = mRoot->showConfigDialog(); - else - result = mRoot->restoreConfig(); - - return !result; + RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); + if (rs == 0) + throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); + mRoot->setRenderSystem(rs); } -bool OgreRenderer::configure(bool showConfig, - const std::string &cfgPath, - const std::string &pluginCfg, - bool _logging) +void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) { - return configure(showConfig, cfgPath, cfgPath, pluginCfg, _logging); -} + assert(mRoot); + mRoot->initialise(false); -bool OgreRenderer::configure(bool showConfig, - const std::string &pluginCfg, - bool _logging) -{ - return configure(showConfig, "", pluginCfg, _logging); -} + NameValuePairList params; + params.insert(std::make_pair("title", title)); + params.insert(std::make_pair("FSAA", settings.fsaa)); + params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false")); -void OgreRenderer::createWindow(const std::string &title) -{ - assert(mRoot); - // Initialize OGRE window - mWindow = mRoot->initialise(true, title, ""); + mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); } void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) { - assert(mRoot); - assert(mWindow); - // Get the SceneManager, in this case a generic one - mScene = mRoot->createSceneManager(ST_GENERIC); + assert(mRoot); + assert(mWindow); + // Get the SceneManager, in this case a generic one + mScene = mRoot->createSceneManager(ST_GENERIC); - // Create the camera - mCamera = mScene->createCamera(camName); - mCamera->setNearClipDistance(nearClip); - mCamera->setFOVy(Degree(fov)); + // Create the camera + mCamera = mScene->createCamera(camName); + mCamera->setNearClipDistance(nearClip); + mCamera->setFOVy(Degree(fov)); - // Create one viewport, entire window - mView = mWindow->addViewport(mCamera); + // Create one viewport, entire window + mView = mWindow->addViewport(mCamera); - // Alter the camera aspect ratio to match the viewport - mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); - - mFader = new Fader(); + // Alter the camera aspect ratio to match the viewport + mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); + + mFader = new Fader(); } diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 179515aa9..7dc539e27 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -33,124 +33,123 @@ namespace Ogre class Viewport; } -namespace OEngine { -namespace Render +namespace OEngine { - class Fader; - class OgreRenderer - { - Ogre::Root *mRoot; - Ogre::RenderWindow *mWindow; - Ogre::SceneManager *mScene; - Ogre::Camera *mCamera; - Ogre::Viewport *mView; -#ifdef ENABLE_PLUGIN_CgProgramManager - Ogre::CgPlugin* mCgPlugin; -#endif -#ifdef ENABLE_PLUGIN_OctreeSceneManager - Ogre::OctreePlugin* mOctreePlugin; -#endif -#ifdef ENABLE_PLUGIN_ParticleFX - Ogre::ParticleFXPlugin* mParticleFXPlugin; -#endif -#ifdef ENABLE_PLUGIN_GL - Ogre::GLPlugin* mGLPlugin; -#endif -#ifdef ENABLE_PLUGIN_Direct3D9 - Ogre::D3D9Plugin* mD3D9Plugin; -#endif - Fader* mFader; - bool logging; - - public: - OgreRenderer() - : mRoot(NULL) - , mWindow(NULL) - , mScene(NULL) - , mCamera(NULL) - , mView(NULL) -#ifdef ENABLE_PLUGIN_CgProgramManager - , mCgPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_OctreeSceneManager - , mOctreePlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_ParticleFX - , mParticleFXPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_GL - , mGLPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_Direct3D9 - , mD3D9Plugin(NULL) -#endif - , mFader(NULL) - , logging(false) + namespace Render { + struct WindowSettings + { + bool vsync; + bool fullscreen; + int window_x, window_y; + std::string fsaa; + }; + + class Fader; + class OgreRenderer + { + Ogre::Root *mRoot; + Ogre::RenderWindow *mWindow; + Ogre::SceneManager *mScene; + Ogre::Camera *mCamera; + Ogre::Viewport *mView; + #ifdef ENABLE_PLUGIN_CgProgramManager + Ogre::CgPlugin* mCgPlugin; + #endif + #ifdef ENABLE_PLUGIN_OctreeSceneManager + Ogre::OctreePlugin* mOctreePlugin; + #endif + #ifdef ENABLE_PLUGIN_ParticleFX + Ogre::ParticleFXPlugin* mParticleFXPlugin; + #endif + #ifdef ENABLE_PLUGIN_GL + Ogre::GLPlugin* mGLPlugin; + #endif + #ifdef ENABLE_PLUGIN_Direct3D9 + Ogre::D3D9Plugin* mD3D9Plugin; + #endif + Fader* mFader; + bool logging; + + public: + OgreRenderer() + : mRoot(NULL) + , mWindow(NULL) + , mScene(NULL) + , mCamera(NULL) + , mView(NULL) + #ifdef ENABLE_PLUGIN_CgProgramManager + , mCgPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_OctreeSceneManager + , mOctreePlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_ParticleFX + , mParticleFXPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_GL + , mGLPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_Direct3D9 + , mD3D9Plugin(NULL) + #endif + , mFader(NULL) + , logging(false) + { + } + + ~OgreRenderer() { cleanup(); } + + /** Configure the renderer. This will load configuration files and + set up the Root and logging classes. */ + void configure( + const std::string &logPath, // Path to directory where to store log files + const std::string &pluginCfg, // plugin.cfg file + const std::string &renderSystem, + bool _logging); // Enable or disable logging + + /// Create a window with the given title + void createWindow(const std::string &title, const WindowSettings& settings); + + /// Set up the scene manager, camera and viewport + void createScene(const std::string camName="Camera",// Camera name + float fov=55, // Field of view angle + float nearClip=5 // Near clip distance + ); + + /// Kill the renderer. + void cleanup(); + + /// Start the main rendering loop + void start(); + + bool loadPlugins(); + + void update(float dt); + + /// Write a screenshot to file + void screenshot(const std::string &file); + + float getFPS(); + + /// Get the Root + Ogre::Root *getRoot() { return mRoot; } + + /// Get the rendering window + Ogre::RenderWindow *getWindow() { return mWindow; } + + /// Get the scene manager + Ogre::SceneManager *getScene() { return mScene; } + + /// Get the screen colour fader + Fader *getFader() { return mFader; } + + /// Camera + Ogre::Camera *getCamera() { return mCamera; } + + /// Viewport + Ogre::Viewport *getViewport() { return mView; } + }; } - - ~OgreRenderer() { cleanup(); } - - /** Configure the renderer. This will load configuration files and - set up the Root and logging classes. */ - bool configure(bool showConfig, // Show config dialog box? - const std::string &cfgPath, // Path to directory where to store config files - const std::string &logPath, // Path to directory where to store log files - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - bool configure(bool showConfig, // Show config dialog box? - const std::string &cfgPath, // Path to directory where to store config files - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - /** Configure the renderer. This will load configuration files and - set up the Root and logging classes. */ - bool configure(bool showConfig, // Show config dialog box? - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - /// Create a window with the given title - void createWindow(const std::string &title); - - /// Set up the scene manager, camera and viewport - void createScene(const std::string camName="Camera",// Camera name - float fov=55, // Field of view angle - float nearClip=5 // Near clip distance - ); - - /// Kill the renderer. - void cleanup(); - - /// Start the main rendering loop - void start(); - - bool loadPlugins(); - - void update(float dt); - - /// Write a screenshot to file - void screenshot(const std::string &file); - - float getFPS(); - - /// Get the Root - Ogre::Root *getRoot() { return mRoot; } - - /// Get the rendering window - Ogre::RenderWindow *getWindow() { return mWindow; } - - /// Get the scene manager - Ogre::SceneManager *getScene() { return mScene; } - - /// Get the screen colour fader - Fader *getFader() { return mFader; } - - /// Camera - Ogre::Camera *getCamera() { return mCamera; } - - /// Viewport - Ogre::Viewport *getViewport() { return mView; } - }; -}} +} #endif From 355268dae11d77556571f97452e8a4bdcb55f16e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 19:36:50 +0200 Subject: [PATCH 169/289] make the launcher build and run again, but it doesn't change settings --- apps/launcher/graphicspage.cpp | 35 ++++++---------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 95b38d53e..8a26ec444 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -150,9 +150,6 @@ void GraphicsPage::createPages() void GraphicsPage::setupConfig() { - QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str(); - QFile file(ogreCfg); - mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat); } void GraphicsPage::setupOgre() @@ -164,32 +161,12 @@ void GraphicsPage::setupOgre() Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); - QString ogreCfg = QString::fromStdString(mCfgMgr.getOgreConfigPath().string()); - file.setFileName(ogreCfg); - - //we need to check that the path to the configuration file exists before we - //try and create an instance of Ogre::Root otherwise Ogre raises an exception - QDir configDir = QFileInfo(file).dir(); - if ( !configDir.exists() && !configDir.mkpath(configDir.path()) ) - { - QMessageBox msgBox; - msgBox.setWindowTitle("Error creating config file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QString(tr("
Failed to create the configuration file

\ - Make sure you have write access to
%1

")).arg(configDir.path())); - msgBox.exec(); - - qApp->exit(1); - return; - } - try { #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) - mOgre = new Ogre::Root("", file.fileName().toStdString(), "./launcherOgre.log"); + mOgre = new Ogre::Root("", "", "./launcherOgre.log"); #else - mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log"); + mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log"); #endif } catch(Ogre::Exception &ex) @@ -227,13 +204,13 @@ void GraphicsPage::setupOgre() mSelectedRenderSystem = *r; mRendererComboBox->addItem((*r)->getName().c_str()); } - +/* int index = mRendererComboBox->findText(mOgreConfig->value("Render System").toString()); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); } - +*/ // Create separate rendersystems QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith)); QString direct3DName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("Direct3D"), Qt::MatchStartsWith)); @@ -460,11 +437,11 @@ void GraphicsPage::writeConfig() QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer) { QString result; - +/* mOgreConfig->beginGroup(renderer->getName().c_str()); result = mOgreConfig->value(key).toString(); mOgreConfig->endGroup(); - +*/ return result; } From ad46049ee078bc9fde6ef92eaf45fd366e8e60dd Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 20:37:18 +0200 Subject: [PATCH 170/289] got the launcher working with the new settings system. --- apps/launcher/graphicspage.cpp | 375 ++++++--------------------------- apps/launcher/graphicspage.hpp | 26 +-- apps/launcher/maindialog.cpp | 27 +++ apps/launcher/maindialog.hpp | 2 + 4 files changed, 102 insertions(+), 328 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 8a26ec444..2cd8006ae 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,7 +1,11 @@ +#include "graphicspage.hpp" + #include -#include "graphicspage.hpp" +#include + #include +#include GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) : QWidget(parent) @@ -17,12 +21,9 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1); renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1); - mRendererStackedWidget = new QStackedWidget(rendererGroup); - QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup); rendererGroupLayout->addLayout(renderSystemLayout); - rendererGroupLayout->addWidget(mRendererStackedWidget); // Display QGroupBox *displayGroup = new QGroupBox(tr("Display"), this); @@ -52,100 +53,29 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) void GraphicsPage::createPages() { - // OpenGL rendering settings - QWidget *mOGLRendererPage = new QWidget(); + QWidget *main = new QWidget(); + QGridLayout *grid = new QGridLayout(main); - QLabel *OGLRTTLabel = new QLabel(tr("Preferred RTT Mode:"), mOGLRendererPage); - mOGLRTTComboBox = new QComboBox(mOGLRendererPage); + mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), main); + grid->addWidget(mVSyncCheckBox, 0, 0, 1, 1); - QLabel *OGLAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mOGLRendererPage); - mOGLAntiAliasingComboBox = new QComboBox(mOGLRendererPage); + mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), main); + grid->addWidget(mFullScreenCheckBox, 1, 0, 1, 1); + + QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), main); + mAntiAliasingComboBox = new QComboBox(main); + grid->addWidget(antiAliasingLabel, 2, 0, 1, 1); + grid->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1); + + QLabel *resolutionLabel = new QLabel(tr("Resolution:"), main); + mResolutionComboBox = new QComboBox(main); + grid->addWidget(resolutionLabel, 3, 0, 1, 1); + grid->addWidget(mResolutionComboBox, 3, 1, 1, 1); - QGridLayout *OGLRendererLayout = new QGridLayout(mOGLRendererPage); QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); + grid->addItem(vSpacer1, 4, 0, 1, 1); - OGLRendererLayout->addWidget(OGLRTTLabel, 0, 0, 1, 1); - OGLRendererLayout->addWidget(mOGLRTTComboBox, 0, 1, 1, 1); - OGLRendererLayout->addWidget(OGLAntiAliasingLabel, 1, 0, 1, 1); - OGLRendererLayout->addWidget(mOGLAntiAliasingComboBox, 1, 1, 1, 1); - OGLRendererLayout->addItem(vSpacer1, 2, 1, 1, 1); - - // OpenGL display settings - QWidget *mOGLDisplayPage = new QWidget(); - - QLabel *OGLResolutionLabel = new QLabel(tr("Resolution:"), mOGLDisplayPage); - mOGLResolutionComboBox = new QComboBox(mOGLDisplayPage); - - QLabel *OGLFrequencyLabel = new QLabel(tr("Display Frequency:"), mOGLDisplayPage); - mOGLFrequencyComboBox = new QComboBox(mOGLDisplayPage); - - mOGLVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mOGLDisplayPage); - mOGLFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mOGLDisplayPage); - - QGridLayout *OGLDisplayLayout = new QGridLayout(mOGLDisplayPage); - QSpacerItem *vSpacer2 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - - OGLDisplayLayout->addWidget(OGLResolutionLabel, 0, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLResolutionComboBox, 0, 1, 1, 1); - OGLDisplayLayout->addWidget(OGLFrequencyLabel, 1, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLFrequencyComboBox, 1, 1, 1, 1); - - OGLDisplayLayout->addItem(vSpacer2, 2, 1, 1, 1); - OGLDisplayLayout->addWidget(mOGLVSyncCheckBox, 3, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLFullScreenCheckBox, 6, 0, 1, 1); - - // Direct3D rendering settings - QWidget *mD3DRendererPage = new QWidget(); - - QLabel *D3DRenderDeviceLabel = new QLabel(tr("Rendering Device:"), mD3DRendererPage); - mD3DRenderDeviceComboBox = new QComboBox(mD3DRendererPage); - - QLabel *D3DAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mD3DRendererPage); - mD3DAntiAliasingComboBox = new QComboBox(mD3DRendererPage); - - QLabel *D3DFloatingPointLabel = new QLabel(tr("Floating-point Mode:"), mD3DRendererPage); - mD3DFloatingPointComboBox = new QComboBox(mD3DRendererPage); - - mD3DNvPerfCheckBox = new QCheckBox(tr("Allow NVPerfHUD"), mD3DRendererPage); - - QGridLayout *D3DRendererLayout = new QGridLayout(mD3DRendererPage); - QSpacerItem *vSpacer3 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - QSpacerItem *vSpacer4 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); - - D3DRendererLayout->addWidget(D3DRenderDeviceLabel, 0, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DRenderDeviceComboBox, 0, 1, 1, 1); - D3DRendererLayout->addWidget(D3DAntiAliasingLabel, 1, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DAntiAliasingComboBox, 1, 1, 1, 1); - D3DRendererLayout->addWidget(D3DFloatingPointLabel, 2, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DFloatingPointComboBox, 2, 1, 1, 1); - D3DRendererLayout->addItem(vSpacer3, 3, 1, 1, 1); - D3DRendererLayout->addWidget(mD3DNvPerfCheckBox, 4, 0, 1, 1); - D3DRendererLayout->addItem(vSpacer4, 5, 1, 1, 1); - - // Direct3D display settings - QWidget *mD3DDisplayPage = new QWidget(); - - QLabel *D3DResolutionLabel = new QLabel(tr("Resolution:"), mD3DDisplayPage); - mD3DResolutionComboBox = new QComboBox(mD3DDisplayPage); - - mD3DVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mD3DDisplayPage); - mD3DFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mD3DDisplayPage); - - QGridLayout *mD3DDisplayLayout = new QGridLayout(mD3DDisplayPage); - QSpacerItem *vSpacer5 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - - mD3DDisplayLayout->addWidget(D3DResolutionLabel, 0, 0, 1, 1); - mD3DDisplayLayout->addWidget(mD3DResolutionComboBox, 0, 1, 1, 1); - mD3DDisplayLayout->addItem(vSpacer5, 1, 1, 1, 1); - mD3DDisplayLayout->addWidget(mD3DVSyncCheckBox, 2, 0, 1, 1); - mD3DDisplayLayout->addWidget(mD3DFullScreenCheckBox, 5, 0, 1, 1); - - // Add the created pages - mRendererStackedWidget->addWidget(mOGLRendererPage); - mRendererStackedWidget->addWidget(mD3DRendererPage); - - mDisplayStackedWidget->addWidget(mOGLDisplayPage); - mDisplayStackedWidget->addWidget(mD3DDisplayPage); + mDisplayStackedWidget->addWidget(main); } void GraphicsPage::setupConfig() @@ -204,13 +134,21 @@ void GraphicsPage::setupOgre() mSelectedRenderSystem = *r; mRendererComboBox->addItem((*r)->getName().c_str()); } -/* - int index = mRendererComboBox->findText(mOgreConfig->value("Render System").toString()); + + int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video"))); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); } -*/ + else + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("Direct3D9 Rendering Subsystem")); +#else + mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("OpenGL Rendering Subsystem")); +#endif + } + // Create separate rendersystems QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith)); QString direct3DName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("Direct3D"), Qt::MatchStartsWith)); @@ -232,217 +170,44 @@ void GraphicsPage::setupOgre() } // Now fill the GUI elements - // OpenGL - if (mOpenGLRenderSystem) { - mOGLRTTComboBox->addItems(getAvailableOptions(QString("RTT Preferred Mode"), mOpenGLRenderSystem)); - mOGLAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mOpenGLRenderSystem)); - mOGLResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mOpenGLRenderSystem)); - mOGLFrequencyComboBox->addItems(getAvailableOptions(QString("Display Frequency"), mOpenGLRenderSystem)); - } - - // Direct3D - if (mDirect3DRenderSystem) { - mD3DRenderDeviceComboBox->addItems(getAvailableOptions(QString("Rendering Device"), mDirect3DRenderSystem)); - mD3DAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mDirect3DRenderSystem)); - mD3DFloatingPointComboBox->addItems(getAvailableOptions(QString("Floating-point mode"), mDirect3DRenderSystem)); - mD3DResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mDirect3DRenderSystem)); - } + mAntiAliasingComboBox->clear(); + mResolutionComboBox->clear(); + mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); } void GraphicsPage::readConfig() { - // Read the config file settings - if (mOpenGLRenderSystem) { + if (Settings::Manager::getBool("vsync", "Video")) + mVSyncCheckBox->setCheckState(Qt::Checked); - int index = mOGLRTTComboBox->findText(getConfigValue("RTT Preferred Mode", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLRTTComboBox->setCurrentIndex(index); - } + if (Settings::Manager::getBool("fullscreen", "Video")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - index = mOGLAntiAliasingComboBox->findText(getConfigValue("FSAA", mOpenGLRenderSystem)); - if ( index != -1){ - mOGLAntiAliasingComboBox->setCurrentIndex(index); - } + int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - index = mOGLResolutionComboBox->findText(getConfigValue("Video Mode", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLResolutionComboBox->setCurrentIndex(index); - } - - index = mOGLFrequencyComboBox->findText(getConfigValue("Display Frequency", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLFrequencyComboBox->setCurrentIndex(index); - } - - // Now we do the same for the checkboxes - if (getConfigValue("VSync", mOpenGLRenderSystem) == QLatin1String("Yes")) { - mOGLVSyncCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("Full Screen", mOpenGLRenderSystem) == QLatin1String("Yes")) { - mOGLFullScreenCheckBox->setCheckState(Qt::Checked); - } - } - - if (mDirect3DRenderSystem) { - - int index = mD3DRenderDeviceComboBox->findText(getConfigValue("Rendering Device", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DRenderDeviceComboBox->setCurrentIndex(index); - } - - index = mD3DAntiAliasingComboBox->findText(getConfigValue("FSAA", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DAntiAliasingComboBox->setCurrentIndex(index); - } - - index = mD3DFloatingPointComboBox->findText(getConfigValue("Floating-point mode", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DFloatingPointComboBox->setCurrentIndex(index); - } - - index = mD3DResolutionComboBox->findText(getConfigValue("Video Mode", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DResolutionComboBox->setCurrentIndex(index); - } - - if (getConfigValue("Allow NVPerfHUD", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DNvPerfCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("VSync", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DVSyncCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("Full Screen", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DFullScreenCheckBox->setCheckState(Qt::Checked); - } - } + std::string resolution = boost::lexical_cast(Settings::Manager::getInt("resolution x", "Video")) + + " x " + boost::lexical_cast(Settings::Manager::getInt("resolution y", "Video")); + int resIndex = mResolutionComboBox->findText(QString::fromStdString(resolution)); + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } void GraphicsPage::writeConfig() { - mOgre->setRenderSystem(mSelectedRenderSystem); + Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); + Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); + Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); - if (mDirect3DRenderSystem) { - // Nvidia Performance HUD - if (mD3DNvPerfCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "No"); - } - - // Antialiasing - mDirect3DRenderSystem->setConfigOption("FSAA", mD3DAntiAliasingComboBox->currentText().toStdString()); - - // Full screen - if (mD3DFullScreenCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("Full Screen", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("Full Screen", "No"); - } - - // Rendering device - mDirect3DRenderSystem->setConfigOption("Rendering Device", mD3DRenderDeviceComboBox->currentText().toStdString()); - - // VSync - if (mD3DVSyncCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("VSync", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("VSync", "No"); - } - - // Resolution - mDirect3DRenderSystem->setConfigOption("Video Mode", mD3DResolutionComboBox->currentText().toStdString()); - } - - if (mOpenGLRenderSystem) { - // Display Frequency - mOpenGLRenderSystem->setConfigOption("Display Frequency", mOGLFrequencyComboBox->currentText().toStdString()); - - // Antialiasing - mOpenGLRenderSystem->setConfigOption("FSAA", mOGLAntiAliasingComboBox->currentText().toStdString()); - - // Full screen - if (mOGLFullScreenCheckBox->checkState() == Qt::Checked) { - mOpenGLRenderSystem->setConfigOption("Full Screen", "Yes"); - } else { - mOpenGLRenderSystem->setConfigOption("Full Screen", "No"); - } - - // RTT mode - mOpenGLRenderSystem->setConfigOption("RTT Preferred Mode", mOGLRTTComboBox->currentText().toStdString()); - - // VSync - if (mOGLVSyncCheckBox->checkState() == Qt::Checked) { - mOpenGLRenderSystem->setConfigOption("VSync", "Yes"); - } else { - mOpenGLRenderSystem->setConfigOption("VSync", "No"); - } - - // Resolution - mOpenGLRenderSystem->setConfigOption("Video Mode", mOGLResolutionComboBox->currentText().toStdString()); - } - - // Now we validate the options - QString ogreError = QString::fromStdString(mSelectedRenderSystem->validateConfigOptions()); - - if (!ogreError.isEmpty()) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error validating Ogre configuration"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
A problem occured while validating the graphics options

\ - The graphics options could not be saved.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(ogreError); - msgBox.exec(); - - Ogre::LogManager::getSingletonPtr()->logMessage( "Caught exception in validateConfigOptions"); - - qCritical("Error validating configuration"); - - qApp->exit(1); - return; - } - - // Write the settings to the config file - - - try - { - mOgre->saveConfig(); - } - catch(Ogre::Exception &ex) - { - QString ogreError = QString::fromStdString(ex.getFullDescription().c_str()); - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing Ogre configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not write the graphics configuration

\ - Please make sure you have the right permissions and try again.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(ogreError); - msgBox.exec(); - - qCritical("Error saving Ogre configuration, the error reported was:\n %s", qPrintable(ogreError)); - - qApp->exit(1); - return; - } - -} - -QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer) -{ - QString result; -/* - mOgreConfig->beginGroup(renderer->getName().c_str()); - result = mOgreConfig->value(key).toString(); - mOgreConfig->endGroup(); -*/ - return result; + std::string resolution = mResolutionComboBox->currentText().toStdString(); + // parse resolution x and y from a string like "800 x 600" + size_t xPos = resolution.find("x"); + int resX = boost::lexical_cast(resolution.substr(0, xPos-1)); + int resY = boost::lexical_cast(resolution.substr(xPos+2, resolution.size()-(xPos+2))); + Settings::Manager::setInt("resolution x", "Video", resX); + Settings::Manager::setInt("resolution y", "Video", resY); } QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer) @@ -461,7 +226,9 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy { if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - result << QString::fromStdString((*opt_it).c_str()).simplified(); + { + result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); + } } } @@ -471,15 +238,11 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy void GraphicsPage::rendererChanged(const QString &renderer) { - if (renderer.contains("Direct3D")) { - mRendererStackedWidget->setCurrentIndex(1); - mDisplayStackedWidget->setCurrentIndex(1); - } - - if (renderer.contains("OpenGL")) { - mRendererStackedWidget->setCurrentIndex(0); - mDisplayStackedWidget->setCurrentIndex(0); - } - mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); + + mAntiAliasingComboBox->clear(); + mResolutionComboBox->clear(); + + mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 6a91a0628..1b0c6f388 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -49,33 +49,15 @@ private: QComboBox *mRendererComboBox; - QStackedWidget *mRendererStackedWidget; QStackedWidget *mDisplayStackedWidget; - // OpenGL - QComboBox *mOGLRTTComboBox; - QComboBox *mOGLAntiAliasingComboBox; - QComboBox *mOGLResolutionComboBox; - QComboBox *mOGLFrequencyComboBox; - - QCheckBox *mOGLVSyncCheckBox; - QCheckBox *mOGLFullScreenCheckBox; - - // Direct3D - QComboBox *mD3DRenderDeviceComboBox; - QComboBox *mD3DAntiAliasingComboBox; - QComboBox *mD3DFloatingPointComboBox; - QComboBox *mD3DResolutionComboBox; - - QCheckBox *mD3DNvPerfCheckBox; - QCheckBox *mD3DVSyncCheckBox; - QCheckBox *mD3DFullScreenCheckBox; - - QSettings *mOgreConfig; + QComboBox *mAntiAliasingComboBox; + QComboBox *mResolutionComboBox; + QCheckBox *mVSyncCheckBox; + QCheckBox *mFullScreenCheckBox; Files::ConfigurationManager &mCfgMgr; - QString getConfigValue(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); void createPages(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 8bb618dd6..d404fed8e 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -7,6 +7,28 @@ MainDialog::MainDialog() { + // Create the settings manager and load default settings file + const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; + const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg"; + + // prefer local + if (boost::filesystem::exists(localdefault)) + mSettings.loadDefault(localdefault); + else if (boost::filesystem::exists(globaldefault)) + mSettings.loadDefault(globaldefault); + else + throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed."); + + // load user settings if they exist, otherwise just load the default settings as user settings + const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; + if (boost::filesystem::exists(settingspath)) + mSettings.loadUser(settingspath); + else if (boost::filesystem::exists(localdefault)) + mSettings.loadUser(localdefault); + else if (boost::filesystem::exists(globaldefault)) + mSettings.loadUser(globaldefault); + + mIconWidget = new QListWidget; mIconWidget->setObjectName("IconWidget"); mIconWidget->setViewMode(QListView::IconMode); @@ -178,6 +200,11 @@ void MainDialog::closeEvent(QCloseEvent *event) // Now write all config files mDataFilesPage->writeConfig(); mGraphicsPage->writeConfig(); + + // Save user settings + const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; + mSettings.saveUser(settingspath); + event->accept(); } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index d6d0e9974..0065aa8c4 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -4,6 +4,7 @@ #include #include +#include class QListWidget; class QListWidgetItem; @@ -41,6 +42,7 @@ private: DataFilesPage *mDataFilesPage; Files::ConfigurationManager mCfgMgr; + Settings::Manager mSettings; }; #endif From b25d62a7e2ad30cf41ee9f19110ebcfb4f328334 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 20:52:38 +0200 Subject: [PATCH 171/289] rename antialiasing mode "MSAA 0" to "none" to avoid confusion. --- apps/launcher/graphicspage.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 2cd8006ae..e156e4fbc 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -222,14 +222,17 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy Ogre::StringVector::iterator opt_it; uint idx = 0; for (opt_it = i->second.possibleValues.begin (); - opt_it != i->second.possibleValues.end (); opt_it++, idx++) - { + opt_it != i->second.possibleValues.end (); opt_it++, idx++) + { - if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - { - result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); - } - } + if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) + { + if (key == "FSAA" && *opt_it == "0") + result << QString("none"); + else + result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); + } + } } From 313294c52297753aed1c168d61b553dc7d5615ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 21:40:42 +0200 Subject: [PATCH 172/289] settings window (hotkey F2) which does nothing. Yay! --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/mode.hpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 25 ++++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 26 +++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 9 ++++++- apps/openmw/mwgui/window_manager.hpp | 2 ++ apps/openmw/mwinput/inputmanager.cpp | 15 +++++++++++ files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_settings_window_layout.xml | 14 ++++++++++ 9 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwgui/settingswindow.cpp create mode 100644 apps/openmw/mwgui/settingswindow.hpp create mode 100644 files/mygui/openmw_settings_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c08c91c02..fd2fdf575 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -27,7 +27,7 @@ add_openmw_dir (mwgui text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list - formatting itemwidget inventorywindow container hud countdialog tradewindow + formatting itemwidget inventorywindow container hud countdialog tradewindow settingswindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 775fe4a03..ad54ed1df 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -6,6 +6,7 @@ namespace MWGui enum GuiMode { GM_Game, // Game mode, only HUD + GM_Settings, // Settings window GM_Inventory, // Inventory mode GM_Container, GM_MainMenu, // Main menu mode diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp new file mode 100644 index 000000000..3641a63a4 --- /dev/null +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -0,0 +1,25 @@ +#include "settingswindow.hpp" + +#include "window_manager.hpp" + +namespace MWGui +{ + SettingsWindow::SettingsWindow(WindowManager& parWindowManager) : + WindowBase("openmw_settings_window_layout.xml", parWindowManager) + { + getWidget(mOkButton, "OkButton"); + + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + + center(); + + int okSize = mOkButton->getTextSize().width + 24; + mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(), + okSize, mOkButton->getHeight()); + } + + void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) + { + mWindowManager.setGuiMode(GM_Game); + } +} diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp new file mode 100644 index 000000000..e37c00f7e --- /dev/null +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -0,0 +1,26 @@ +#ifndef MWGUI_SETTINGS_H +#define MWGUI_SETTINGS_H + +#include "window_base.hpp" + +namespace MWGui +{ + class WindowManager; +} + +namespace MWGui +{ + class SettingsWindow : public WindowBase + { + public: + SettingsWindow(WindowManager& parWindowManager); + + protected: + MyGUI::Button* mOkButton; + + void onOkButtonClicked(MyGUI::Widget* _sender); + }; +} + +#endif + diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2cacf2346..4bb34cf24 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -16,6 +16,7 @@ #include "mainmenu.hpp" #include "countdialog.hpp" #include "tradewindow.hpp" +#include "settingswindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -45,11 +46,12 @@ WindowManager::WindowManager( , mMessageBoxManager(NULL) , console(NULL) , mJournal(NULL) - , mDialogueWindow(nullptr) + , mDialogueWindow(NULL) , mBookWindow(NULL) , mScrollWindow(NULL) , mCountDialog(NULL) , mTradeWindow(NULL) + , mSettingsWindow(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -118,6 +120,7 @@ WindowManager::WindowManager( mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); + mSettingsWindow = new SettingsWindow(*this); // The HUD is always on hud->setVisible(true); @@ -217,6 +220,7 @@ void WindowManager::updateVisible() mScrollWindow->setVisible(false); mBookWindow->setVisible(false); mTradeWindow->setVisible(false); + mSettingsWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -233,6 +237,9 @@ void WindowManager::updateVisible() case GM_MainMenu: menu->setVisible(true); break; + case GM_Settings: + mSettingsWindow->setVisible(true); + break; case GM_Console: console->enable(); break; diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 22fe973a5..aab307035 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -77,6 +77,7 @@ namespace MWGui class MessageBoxManager; class CountDialog; class TradeWindow; + class SettingsWindow; struct ClassPoint { @@ -230,6 +231,7 @@ namespace MWGui BookWindow* mBookWindow; CountDialog* mCountDialog; TradeWindow* mTradeWindow; + SettingsWindow* mSettingsWindow; CharacterCreation* mCharGen; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8f8f1e1ee..8fd6a9c6b 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -71,6 +71,8 @@ namespace MWInput A_ToggleFps, // Toggle FPS display (this is temporary) + A_Settings, // Temporary hotkey + A_LAST // Marker for the last item }; @@ -140,6 +142,16 @@ namespace MWInput windows.messageBox ("Screenshot saved", empty); } + void showSettings() + { + if (mDragDrop) + return; + + MWGui::GuiMode mode = windows.getMode(); + if (mode != MWGui::GM_Settings) + setGuiMode(MWGui::GM_Settings); + } + /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ void toggleInventory() { @@ -261,6 +273,8 @@ namespace MWInput "Ready hands"); disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this), "Toggle FPS display"); + disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this), + "Show settings window"); // Add the exit listener ogre.getRoot()->addFrameListener(&exit); @@ -308,6 +322,7 @@ namespace MWInput disp->bind(A_ToggleWeapon,KC_F); disp->bind(A_ToggleSpell,KC_R); disp->bind(A_ToggleFps, KC_F10); + disp->bind(A_Settings, KC_F2); // Key bindings for polled keys // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame. diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index cacfb7c5a..9f43f2d89 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -57,6 +57,7 @@ configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml new file mode 100644 index 000000000..eaf9191bc --- /dev/null +++ b/files/mygui/openmw_settings_window_layout.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + From 972c035e97dc0aac9b714685628f3910b5ddc546 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 23:35:05 +0200 Subject: [PATCH 173/289] TabControl skin, settings window categories --- files/mygui/openmw_resources.xml | 15 +++++++++++++++ files/mygui/openmw_settings_window_layout.xml | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index 4c509ae13..b47de005d 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -113,6 +113,8 @@
+ + @@ -124,4 +126,17 @@ + + + + + + + + + + + + + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index eaf9191bc..387a8587e 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -3,7 +3,21 @@ - + + + + + + + + + + + + + + + From 656a8f1be9fd3cf181de8140ba343778851e49c3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 01:32:36 +0200 Subject: [PATCH 174/289] working menu transparency slider --- apps/openmw/mwgui/settingswindow.cpp | 38 ++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 4 ++ apps/openmw/mwrender/renderingmanager.cpp | 24 ++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 6 +++ apps/openmw/mwworld/world.cpp | 5 ++ apps/openmw/mwworld/world.hpp | 3 ++ files/mygui/CMakeLists.txt | 1 - files/mygui/openmw_list.skin.xml | 23 ++++++++++ files/mygui/openmw_resources.xml | 2 +- files/mygui/openmw_settings_window_layout.xml | 43 ++++++++++++++++-- files/mygui/transparent.png | Bin 150 -> 0 bytes files/settings-default.cfg | 4 ++ libs/openengine/ogre/renderer.cpp | 15 ++++++ libs/openengine/ogre/renderer.hpp | 4 ++ 14 files changed, 166 insertions(+), 6 deletions(-) delete mode 100644 files/mygui/transparent.png diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3641a63a4..af909ea8c 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -1,5 +1,13 @@ #include "settingswindow.hpp" +#include +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + #include "window_manager.hpp" namespace MWGui @@ -8,18 +16,48 @@ namespace MWGui WindowBase("openmw_settings_window_layout.xml", parWindowManager) { getWidget(mOkButton, "OkButton"); + getWidget(mResolutionList, "ResolutionList"); + getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); + getWidget(mViewDistanceSlider, "ViewDistanceSlider"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); center(); int okSize = mOkButton->getTextSize().width + 24; mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(), okSize, mOkButton->getHeight()); + + // fill resolution list + Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); + const Ogre::StringVector& videoModes = rs->getConfigOptions()["Video Mode"].possibleValues; + for (Ogre::StringVector::const_iterator it=videoModes.begin(); + it!=videoModes.end(); ++it) + { + mResolutionList->addItem(*it); + } + + // read settings + int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); + mMenuTransparencySlider->setScrollPosition(menu_transparency); + onSliderChangePosition(mMenuTransparencySlider, menu_transparency); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { mWindowManager.setGuiMode(GM_Game); } + + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) + { + float val = pos / float(scroller->getScrollRange()-1); + if (scroller == mMenuTransparencySlider) + { + Settings::Manager::setFloat("menu transparency", "GUI", val); + } + + MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index e37c00f7e..597f8dec1 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -17,8 +17,12 @@ namespace MWGui protected: MyGUI::Button* mOkButton; + MyGUI::ListBox* mResolutionList; + MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::ScrollBar* mViewDistanceSlider; void onOkButtonClicked(MyGUI::Widget* _sender); + void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6d0b1b21c..86c1f752c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -114,6 +114,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mDebugging = new Debugging(mMwRoot, engine); mLocalMap = new MWRender::LocalMap(&mRendering, this); + + setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } RenderingManager::~RenderingManager () @@ -563,4 +565,26 @@ Compositors* RenderingManager::getCompositors() return mCompositors; } +void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) +{ + for (Settings::CategorySettingVector::const_iterator it=settings.begin(); + it != settings.end(); ++it) + { + if (it->second == "menu transparency" && it->first == "GUI") + { + setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); + } + } +} + +void RenderingManager::setMenuTransparency(float val) +{ + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName("transparent.png"); + std::vector buffer; + buffer.resize(1); + buffer[0] = (int(255*val) << 24); + memcpy(tex->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], 1*4); + tex->getBuffer()->unlock(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 5ef43a2e2..edee193f3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -13,6 +13,8 @@ #include #include +#include + #include #include @@ -157,10 +159,14 @@ class RenderingManager: private RenderingInterface { ///< transform the specified bounding box (in world coordinates) into screen coordinates. /// @return packed vector4 (min_x, min_y, max_x, max_y) + void processChangedSettings(const Settings::CategorySettingVector& settings); + private: void setAmbientMode(); + void setMenuTransparency(float val); + bool mSunEnabled; SkyManager* mSkyManager; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c0107d9af..772dc71cb 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -1024,4 +1024,9 @@ namespace MWWorld mWorldScene->insertObject(object, cell); } + + void World::processChangedSettings(const Settings::CategorySettingVector& settings) + { + mRendering->processChangedSettings(settings); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 1b0ad7fd8..e8391773b 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -7,6 +7,7 @@ #include #include +#include #include "../mwrender/debugging.hpp" #include "../mwrender/renderingmanager.hpp" @@ -279,6 +280,8 @@ namespace MWWorld bool canPlaceObject(float cursorX, float cursorY); ///< @return true if it is possible to place on object at specified cursor location + + void processChangedSettings(const Settings::CategorySettingVector& settings); }; } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 9f43f2d89..90a0c1fce 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -60,7 +60,6 @@ configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_wi configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) -configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) configure_file("${SDIR}/Obliviontt.zip" "${DDIR}/Obliviontt.zip" COPYONLY) configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index e1fbc49b6..64435451a 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -151,6 +151,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -170,6 +192,7 @@ + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index b47de005d..e96aeb918 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -130,7 +130,7 @@ - + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 387a8587e..9c6716ff0 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -6,17 +6,52 @@ - + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/transparent.png b/files/mygui/transparent.png deleted file mode 100644 index 32d2ed1975611dbfc9baf5550b92118fee2d73b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggaCRPzfaZ{P!_CO&qPZ!4!iOb0; m2?-I$8rTgC1sD!HGcs&^z_3mHan=i<3I @@ -107,6 +110,18 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false")); mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); + + // create the semi-transparent black background texture used by the GUI. + // has to be created in code with TU_DYNAMIC_WRITE_ONLY_DISCARDABLE param + // so that it can be modified at runtime. + mTransparentBGTexture = Ogre::TextureManager::getSingleton().createManual( + "transparent.png", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, + 1, 1, + 0, + Ogre::PF_A8R8G8B8, + Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); } void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 7dc539e27..50fe64015 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -24,6 +24,8 @@ # include "OgreD3D9Plugin.h" #endif +#include "OgreTexture.h" + namespace Ogre { class Root; @@ -71,6 +73,8 @@ namespace OEngine Fader* mFader; bool logging; + Ogre::TexturePtr mTransparentBGTexture; + public: OgreRenderer() : mRoot(NULL) From 689cf7ce054554354a08c49dedabc51fb98f7dd6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 05:28:25 +0200 Subject: [PATCH 175/289] ConfirmationDialog --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwgui/confirmationdialog.cpp | 68 ++++++++++++++++++ apps/openmw/mwgui/confirmationdialog.hpp | 34 +++++++++ apps/openmw/mwgui/countdialog.cpp | 3 - apps/openmw/mwgui/settingswindow.cpp | 69 ++++++++++++++++++- apps/openmw/mwgui/settingswindow.hpp | 4 ++ apps/openmw/mwgui/window_manager.cpp | 5 ++ apps/openmw/mwgui/window_manager.hpp | 3 + components/settings/settings.cpp | 4 ++ files/mygui/CMakeLists.txt | 1 + .../openmw_confirmation_dialog_layout.xml | 25 +++++++ files/mygui/openmw_count_window_layout.xml | 8 ++- files/mygui/openmw_settings_window_layout.xml | 5 +- 13 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 apps/openmw/mwgui/confirmationdialog.cpp create mode 100644 apps/openmw/mwgui/confirmationdialog.hpp create mode 100644 files/mygui/openmw_confirmation_dialog_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fd2fdf575..a3c147b94 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,6 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting itemwidget inventorywindow container hud countdialog tradewindow settingswindow + confirmationdialog ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp new file mode 100644 index 000000000..a54bdb1d8 --- /dev/null +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -0,0 +1,68 @@ +#include "confirmationdialog.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + +namespace MWGui +{ + ConfirmationDialog::ConfirmationDialog(WindowManager& parWindowManager) : + WindowBase("openmw_confirmation_dialog_layout.xml", parWindowManager) + { + getWidget(mMessage, "Message"); + getWidget(mOkButton, "OkButton"); + getWidget(mCancelButton, "CancelButton"); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onCancelButtonClicked); + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked); + } + + void ConfirmationDialog::open(const std::string& message) + { + setVisible(true); + + mMessage->setCaptionWithReplacing(message); + + int height = mMessage->getTextSize().height + 72; + + mMainWidget->setSize(mMainWidget->getWidth(), height); + + mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height+24); + + center(); + + // make other gui elements inaccessible while this dialog is open + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); + + int okButtonWidth = mOkButton->getTextSize().width + 24; + mOkButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth, + mOkButton->getTop(), + okButtonWidth, + mOkButton->getHeight()); + + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth - cancelButtonWidth - 8, + mCancelButton->getTop(), + cancelButtonWidth, + mCancelButton->getHeight()); + } + + void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) + { + close(); + } + + void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender) + { + eventOkClicked(); + + close(); + } + + void ConfirmationDialog::close() + { + setVisible(false); + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); + } +} diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp new file mode 100644 index 000000000..a20034171 --- /dev/null +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -0,0 +1,34 @@ +#ifndef MWGUI_CONFIRMATIONDIALOG_H +#define MWGUI_CONFIRMATIONDIALOG_H + +#include "window_base.hpp" + +namespace MWGui +{ + class ConfirmationDialog : public WindowBase + { + public: + ConfirmationDialog(WindowManager& parWindowManager); + void open(const std::string& message); + + typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; + + /** Event : Ok button was clicked.\n + signature : void method()\n + */ + EventHandle_Void eventOkClicked; + + private: + MyGUI::EditBox* mMessage; + MyGUI::Button* mOkButton; + MyGUI::Button* mCancelButton; + + void onCancelButtonClicked(MyGUI::Widget* _sender); + void onOkButtonClicked(MyGUI::Widget* _sender); + + void close(); + }; + +} + +#endif diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 16e3f9aab..e0a9bb908 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -17,9 +17,6 @@ namespace MWGui getWidget(mOkButton, "OkButton"); getWidget(mCancelButton, "CancelButton"); - mOkButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOk")->str); - mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); - mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index af909ea8c..6eaf31ce9 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -2,6 +2,9 @@ #include #include +#include + +#include #include @@ -9,6 +12,7 @@ #include "../mwworld/world.hpp" #include "window_manager.hpp" +#include "confirmationdialog.hpp" namespace MWGui { @@ -19,10 +23,13 @@ namespace MWGui getWidget(mResolutionList, "ResolutionList"); getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); + getWidget(mFullscreenButton, "FullscreenButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); center(); @@ -42,7 +49,15 @@ namespace MWGui // read settings int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); mMenuTransparencySlider->setScrollPosition(menu_transparency); - onSliderChangePosition(mMenuTransparencySlider, menu_transparency); + + float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); + int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; + mViewDistanceSlider->setScrollPosition(viewdist); + + std::string on = mWindowManager.getGameSettingString("sOn", "On"); + std::string off = mWindowManager.getGameSettingString("sOff", "On"); + + mFullscreenButton->setCaption(Settings::Manager::getBool("fullscreen", "Video") ? on : off); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -50,6 +65,54 @@ namespace MWGui mWindowManager.setGuiMode(GM_Game); } + void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) + { + if (index == MyGUI::ITEM_NONE) + return; + + ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + dialog->open("#{sNotifyMessage67}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); + } + + void SettingsWindow::onResolutionAccept() + { + std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); + size_t xPos = resStr.find("x"); + std::string resXStr = resStr.substr(0, xPos-1); + Ogre::StringUtil::trim(resXStr); + std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); + Ogre::StringUtil::trim(resYStr); + int resX = boost::lexical_cast(resXStr); + int resY = boost::lexical_cast(resYStr); + + Settings::Manager::setInt("resolution x", "Video", resX); + Settings::Manager::setInt("resolution y", "Video", resY); + + MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + } + + void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) + { + std::string on = mWindowManager.getGameSettingString("sOn", "On"); + std::string off = mWindowManager.getGameSettingString("sOff", "On"); + bool newState; + if (_sender->castType()->getCaption() == on) + { + _sender->castType()->setCaption(off); + newState = false; + } + else + { + _sender->castType()->setCaption(on); + newState = true; + } + + if (_sender == mFullscreenButton) + Settings::Manager::setBool("fullscreen", "Video", newState); + } + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) { float val = pos / float(scroller->getScrollRange()-1); @@ -57,6 +120,10 @@ namespace MWGui { Settings::Manager::setFloat("menu transparency", "GUI", val); } + else if (scroller == mViewDistanceSlider) + { + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + } MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 597f8dec1..785b0c9b1 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -18,11 +18,15 @@ namespace MWGui protected: MyGUI::Button* mOkButton; MyGUI::ListBox* mResolutionList; + MyGUI::Button* mFullscreenButton; MyGUI::ScrollBar* mMenuTransparencySlider; MyGUI::ScrollBar* mViewDistanceSlider; void onOkButtonClicked(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); + void onButtonToggled(MyGUI::Widget* _sender); + void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); + void onResolutionAccept(); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4bb34cf24..09ea6543a 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -17,6 +17,7 @@ #include "countdialog.hpp" #include "tradewindow.hpp" #include "settingswindow.hpp" +#include "confirmationdialog.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -52,6 +53,7 @@ WindowManager::WindowManager( , mCountDialog(NULL) , mTradeWindow(NULL) , mSettingsWindow(NULL) + , mConfirmationDialog(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -121,6 +123,7 @@ WindowManager::WindowManager( mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); mSettingsWindow = new SettingsWindow(*this); + mConfirmationDialog = new ConfirmationDialog(*this); // The HUD is always on hud->setVisible(true); @@ -161,6 +164,8 @@ WindowManager::~WindowManager() delete mBookWindow; delete mScrollWindow; delete mTradeWindow; + delete mSettingsWindow; + delete mConfirmationDialog; cleanupGarbage(); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index aab307035..9ccc42b1e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -78,6 +78,7 @@ namespace MWGui class CountDialog; class TradeWindow; class SettingsWindow; + class ConfirmationDialog; struct ClassPoint { @@ -140,6 +141,7 @@ namespace MWGui MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} MWGui::CountDialog* getCountDialog() {return mCountDialog;} + MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MyGUI::Gui* getGui() const { return gui; } @@ -232,6 +234,7 @@ namespace MWGui CountDialog* mCountDialog; TradeWindow* mTradeWindow; SettingsWindow* mSettingsWindow; + ConfirmationDialog* mConfirmationDialog; CharacterCreation* mCharGen; diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 28201eda2..9b941e253 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -131,7 +131,11 @@ void Manager::setString (const std::string& setting, const std::string& category } } else + { + if (mDefaultFile.getSetting(setting, category) != value) + mChangedSettings.push_back(std::make_pair(category, setting)); mNewSettings[s] = value; + } } } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 90a0c1fce..89ebd8f94 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -58,6 +58,7 @@ configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_confirmation_dialog_layout.xml" "${DDIR}/openmw_confirmation_dialog_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) diff --git a/files/mygui/openmw_confirmation_dialog_layout.xml b/files/mygui/openmw_confirmation_dialog_layout.xml new file mode 100644 index 000000000..7b8bd2a1f --- /dev/null +++ b/files/mygui/openmw_confirmation_dialog_layout.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_count_window_layout.xml b/files/mygui/openmw_count_window_layout.xml index 38ba7644f..ae6635dff 100644 --- a/files/mygui/openmw_count_window_layout.xml +++ b/files/mygui/openmw_count_window_layout.xml @@ -20,8 +20,12 @@ - - + + + + + + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 9c6716ff0..2fa332d9a 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -34,9 +34,10 @@ - - + + + From 7ebbc099b37024d4aee29da8f2ac4b4483efc6b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 12:23:35 +0200 Subject: [PATCH 176/289] allow stacking gui modes --- apps/openmw/engine.cpp | 8 +- apps/openmw/mwdialogue/dialoguemanager.cpp | 4 +- apps/openmw/mwgui/bookwindow.cpp | 9 +- apps/openmw/mwgui/charactercreation.cpp | 118 ++++++++++++++------- apps/openmw/mwgui/charactercreation.hpp | 1 - apps/openmw/mwgui/container.cpp | 4 +- apps/openmw/mwgui/dialogue.cpp | 16 ++- apps/openmw/mwgui/dialogue.hpp | 2 - apps/openmw/mwgui/messagebox.cpp | 1 - apps/openmw/mwgui/mode.hpp | 1 - apps/openmw/mwgui/scrollwindow.cpp | 9 +- apps/openmw/mwgui/tradewindow.cpp | 4 +- apps/openmw/mwgui/window_manager.cpp | 69 ++++++------ apps/openmw/mwgui/window_manager.hpp | 24 ++--- apps/openmw/mwinput/inputmanager.cpp | 73 ++++++------- apps/openmw/mwinput/inputmanager.hpp | 4 +- apps/openmw/mwscript/guiextensions.cpp | 2 +- apps/openmw/mwworld/actionopen.cpp | 2 +- apps/openmw/mwworld/actionread.cpp | 4 +- 19 files changed, 194 insertions(+), 161 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 85b0557b1..412050ff2 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -105,7 +105,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // frame. // passing of time - if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWorld()->advanceTime ( mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600); @@ -116,9 +116,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // update actors std::vector > movement; MWBase::Environment::get().getMechanicsManager()->update (movement, mEnvironment.getFrameDuration(), - MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game); + MWBase::Environment::get().getWindowManager()->isGuiMode()); - if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWorld()->doPhysics (movement, mEnvironment.getFrameDuration()); // update world @@ -413,7 +413,7 @@ void OMW::Engine::go() void OMW::Engine::activate() { - if (MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game) + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index af589469e..716f472a0 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -635,7 +635,7 @@ namespace MWDialogue actorKnownTopics.clear(); //initialise the GUI - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Dialogue); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); @@ -843,7 +843,7 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } void DialogueManager::questionAnswered(std::string answere) diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index c6411175d..f1873b550 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -1,13 +1,14 @@ #include "bookwindow.hpp" -#include "formatting.hpp" +#include #include "../mwbase/environment.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwsound/soundmanager.hpp" #include "../mwworld/actiontake.hpp" -#include +#include "formatting.hpp" +#include "window_manager.hpp" using namespace MWGui; @@ -91,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); + mWindowManager.popGuiMode(); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -101,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mBook); take.execute(); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index afb168d32..691fd4a91 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -110,7 +110,6 @@ using namespace MWGui; CharacterCreation::CharacterCreation(WindowManager* _wm) : mNameDialog(0) , mRaceDialog(0) - , mDialogueWindow(0) , mClassChoiceDialog(0) , mGenerateClassQuestionDialog(0) , mGenerateClassResultDialog(0) @@ -253,7 +252,7 @@ void CharacterCreation::onReviewDialogDone(WindowBase* parWindow) if (mReviewDialog) mWM->removeDialog(mReviewDialog); - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } void CharacterCreation::onReviewDialogBack() @@ -261,7 +260,7 @@ void CharacterCreation::onReviewDialogBack() if (mReviewDialog) mWM->removeDialog(mReviewDialog); - mWM->setGuiMode(GM_Birth); + mWM->pushGuiMode(GM_Birth); } void CharacterCreation::onReviewActivateDialog(int parDialog) @@ -270,19 +269,21 @@ void CharacterCreation::onReviewActivateDialog(int parDialog) mWM->removeDialog(mReviewDialog); mCreationStage = CSE_ReviewNext; + mWM->popGuiMode(); + switch(parDialog) { case ReviewDialog::NAME_DIALOG: - mWM->setGuiMode(GM_Name); + mWM->pushGuiMode(GM_Name); break; case ReviewDialog::RACE_DIALOG: - mWM->setGuiMode(GM_Race); + mWM->pushGuiMode(GM_Race); break; case ReviewDialog::CLASS_DIALOG: - mWM->setGuiMode(GM_Class); + mWM->pushGuiMode(GM_Class); break; case ReviewDialog::BIRTHSIGN_DIALOG: - mWM->setGuiMode(GM_Birth); + mWM->pushGuiMode(GM_Birth); }; } @@ -304,13 +305,19 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) //TODO This bit gets repeated a few times; wrap it in a function if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -324,7 +331,8 @@ void CharacterCreation::onPickClassDialogBack() mWM->removeDialog(mPickClassDialog); } - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onClassChoice(int _index) @@ -334,19 +342,21 @@ void CharacterCreation::onClassChoice(int _index) mWM->removeDialog(mClassChoiceDialog); } + mWM->popGuiMode(); + switch(_index) { case ClassChoiceDialog::Class_Generate: - mWM->setGuiMode(GM_ClassGenerate); + mWM->pushGuiMode(GM_ClassGenerate); break; case ClassChoiceDialog::Class_Pick: - mWM->setGuiMode(GM_ClassPick); + mWM->pushGuiMode(GM_ClassPick); break; case ClassChoiceDialog::Class_Create: - mWM->setGuiMode(GM_ClassCreate); + mWM->pushGuiMode(GM_ClassCreate); break; case ClassChoiceDialog::Class_Back: - mWM->setGuiMode(GM_Race); + mWM->pushGuiMode(GM_Race); break; }; @@ -363,13 +373,19 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_NameChosen) - mWM->setGuiMode(GM_Race); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Race); + } else { mCreationStage = CSE_NameChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -383,7 +399,8 @@ void CharacterCreation::onRaceDialogBack() mWM->removeDialog(mRaceDialog); } - mWM->setGuiMode(GM_Name); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Name); } void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) @@ -398,13 +415,19 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); - else if(mCreationStage >= CSE_RaceChosen) - mWM->setGuiMode(GM_Class); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } + else if (mCreationStage >= CSE_NameChosen) + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); + } else { - mCreationStage = CSE_RaceChosen; - mWM->setGuiMode(GM_Game); + mCreationStage = CSE_NameChosen; + mWM->popGuiMode(); } } @@ -419,11 +442,14 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) } if (mCreationStage >= CSE_BirthSignChosen) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else { mCreationStage = CSE_BirthSignChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -435,7 +461,8 @@ void CharacterCreation::onBirthSignDialogBack() mWM->removeDialog(mBirthSignDialog); } - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) @@ -470,13 +497,19 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -485,7 +518,8 @@ void CharacterCreation::onCreateClassDialogBack() if (mCreateClassDialog) mWM->removeDialog(mCreateClassDialog); - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onClassQuestionChosen(int _index) @@ -496,7 +530,8 @@ void CharacterCreation::onClassQuestionChosen(int _index) mWM->removeDialog(mGenerateClassQuestionDialog); if (_index < 0 || _index >= 3) { - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); return; } @@ -581,7 +616,8 @@ void CharacterCreation::showClassQuestionDialog() if (mGenerateClassStep > sGenerateClassSteps.size()) { - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); return; } @@ -610,7 +646,8 @@ void CharacterCreation::onGenerateClassBack() mWM->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) @@ -620,13 +657,19 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -634,7 +677,6 @@ CharacterCreation::~CharacterCreation() { delete mNameDialog; delete mRaceDialog; - delete mDialogueWindow; delete mClassChoiceDialog; delete mGenerateClassQuestionDialog; delete mGenerateClassResultDialog; diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 222754cdc..dfb07853e 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -46,7 +46,6 @@ namespace MWGui //Dialogs TextInputDialog* mNameDialog; RaceDialog* mRaceDialog; - DialogueWindow* mDialogueWindow; ClassChoiceDialog* mClassChoiceDialog; InfoBoxDialog* mGenerateClassQuestionDialog; GenerateClassResultDialog* mGenerateClassResultDialog; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index be21987ef..8ac876c07 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -636,7 +636,7 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -667,6 +667,6 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) containerStore.clear(); - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 53ab98aeb..8a68ff666 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -112,15 +112,6 @@ void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3); } -void DialogueWindow::open() -{ - topicsList->clear(); - pTopicsText.clear(); - history->eraseText(0,history->getTextLength()); - updateOptions(); - setVisible(true); -} - void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) { MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); @@ -133,7 +124,7 @@ void DialogueWindow::onSelectTopic(std::string topic) if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? - mWindowManager.setGuiMode(GM_Barter); + mWindowManager.pushGuiMode(GM_Barter); mWindowManager.getTradeWindow()->startTrade(mActor); } @@ -147,6 +138,11 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) mActor = actor; topicsList->setEnabled(true); setTitle(npcName); + + topicsList->clear(); + pTopicsText.clear(); + history->eraseText(0,history->getTextLength()); + updateOptions(); } void DialogueWindow::setKeywords(std::list keyWords) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 7f69f972c..d3106ad38 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -30,8 +30,6 @@ namespace MWGui public: DialogueWindow(WindowManager& parWindowManager); - void open(); - // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index a6b9025ce..9a0671478 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,7 +58,6 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; - mWindowManager->setNextMode(GM_Game); } } diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 775fe4a03..d465aa0c5 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -5,7 +5,6 @@ namespace MWGui { enum GuiMode { - GM_Game, // Game mode, only HUD GM_Inventory, // Inventory mode GM_Container, GM_MainMenu, // Main menu mode diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 877864cfe..f4d45fc26 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -1,12 +1,13 @@ #include "scrollwindow.hpp" -#include "formatting.hpp" - #include "../mwbase/environment.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwworld/actiontake.hpp" #include "../mwsound/soundmanager.hpp" +#include "formatting.hpp" +#include "window_manager.hpp" + using namespace MWGui; ScrollWindow::ScrollWindow (WindowManager& parWindowManager) : @@ -55,7 +56,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -65,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute(); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 60cc06cb8..311ea6c95 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -210,7 +210,7 @@ namespace MWGui std::string sound = "Item Gold Up"; MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mWindowManager.setGuiMode(GM_Game); + mWindowManager.popGuiMode(); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) @@ -220,7 +220,7 @@ namespace MWGui // now gimme back my stuff! mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - mWindowManager.setGuiMode(GM_Game); + mWindowManager.popGuiMode(); } void TradeWindow::updateLabels() diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2cacf2346..123323168 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -62,9 +62,6 @@ WindowManager::WindowManager( , playerMagicka() , playerFatigue() , gui(NULL) - , mode(GM_Game) - , nextMode(GM_Game) - , needModeChange(false) , garbageDialogs() , shown(GW_ALL) , allowed(newGame ? GW_None : GW_ALL) @@ -178,12 +175,6 @@ void WindowManager::cleanupGarbage() void WindowManager::update() { cleanupGarbage(); - if (needModeChange) - { - needModeChange = false; - MWBase::Environment::get().getInputManager()->setGuiMode(nextMode); - nextMode = GM_Game; - } if (showFPSLevel > 0) { hud->setFPS(mFPS); @@ -192,17 +183,6 @@ void WindowManager::update() } } -void WindowManager::setNextMode(GuiMode newMode) -{ - nextMode = newMode; - needModeChange = true; -} - -void WindowManager::setGuiMode(GuiMode newMode) -{ - MWBase::Environment::get().getInputManager()->setGuiMode(newMode); -} - void WindowManager::updateVisible() { // Start out by hiding everything except the HUD @@ -221,15 +201,20 @@ void WindowManager::updateVisible() // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); - if (mode == GM_Game) + bool gameMode = !isGuiMode(); + + if (gameMode) mToolTips->enterGameMode(); else mToolTips->enterGuiMode(); + // If in game mode, don't show anything. + if (gameMode) + return; + + GuiMode mode = mGuiModes.back(); + switch(mode) { - case GM_Game: - // If in game mode, don't show anything. - break; case GM_MainMenu: menu->setVisible(true); break; @@ -273,7 +258,7 @@ void WindowManager::updateVisible() mInventoryWindow->openInventory(); break; case GM_Dialogue: - mDialogueWindow->open(); + mDialogueWindow->setVisible(true); break; case GM_Barter: mInventoryWindow->setVisible(true); @@ -281,9 +266,6 @@ void WindowManager::updateVisible() mTradeWindow->setVisible(true); break; case GM_InterMessageBox: - if(!mMessageBoxManager->isInteractiveMessageBox()) { - setGuiMode(GM_Game); - } break; case GM_Journal: mJournal->setVisible(true); @@ -291,9 +273,6 @@ void WindowManager::updateVisible() break; default: // Unsupported mode, switch back to game - // Note: The call will eventually end up this method again but - // will stop at the check if mode is GM_Game. - setGuiMode(GM_Game); break; } } @@ -427,7 +406,7 @@ void WindowManager::messageBox (const std::string& message, const std::vectorcreateInteractiveMessageBox(message, buttons); - setGuiMode(GM_InterMessageBox); + pushGuiMode(GM_InterMessageBox); } } @@ -452,7 +431,7 @@ void WindowManager::onDialogueWindowBye() //removeDialog(dialogueWindow); mDialogueWindow->setVisible(false); } - setGuiMode(GM_Game); + popGuiMode(); } void WindowManager::onFrame (float frameDuration) @@ -597,3 +576,27 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r if (setting && setting->type == ESM::VT_String) _result = setting->str; } + +void WindowManager::pushGuiMode(GuiMode mode) +{ + if (mode==GM_Inventory && allowed==GW_None) + return; + + mGuiModes.push_back(mode); + + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + + updateVisible(); +} + +void WindowManager::popGuiMode() +{ + if (mGuiModes.size()) + mGuiModes.pop_back(); + + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + + updateVisible(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 22fe973a5..d519d2e49 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -96,8 +96,6 @@ namespace MWGui WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); virtual ~WindowManager(); - void setGuiMode(GuiMode newMode); - /** * Should be called each frame to update windows/gui elements. * This could mean updating sizes of gui elements or opening @@ -105,19 +103,17 @@ namespace MWGui */ void update(); - void setMode(GuiMode newMode) + void pushGuiMode(GuiMode mode); + void popGuiMode(); + + GuiMode getMode() const { - if (newMode==GM_Inventory && allowed==GW_None) - return; - - mode = newMode; - updateVisible(); + if (mGuiModes.empty()) + throw std::runtime_error ("getMode() called, but there is no active mode"); + return mGuiModes.back(); } - void setNextMode(GuiMode newMode); - GuiMode getMode() const { return mode; } - - bool isGuiMode() const { return getMode() != GM_Game; } // Everything that is not game mode is considered "gui mode" + bool isGuiMode() const { return !mGuiModes.empty(); } // Disallow all inventory mode windows void disallowAll() @@ -244,9 +240,7 @@ namespace MWGui MyGUI::Gui *gui; // Gui - GuiMode mode; // Current gui mode - GuiMode nextMode; // Next mode to activate in update() - bool needModeChange; //Whether a mode change is needed in update() [will use nextMode] + std::vector mGuiModes; std::vector garbageDialogs; void cleanupGarbage(); diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8f8f1e1ee..c074731d8 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -143,20 +143,20 @@ namespace MWInput /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ void toggleInventory() { - using namespace MWGui; + using namespace MWGui; - if (mDragDrop) - return; + if (mDragDrop) + return; - GuiMode mode = windows.getMode(); + bool gameMode = !windows.isGuiMode(); - // Toggle between game mode and inventory mode - if(mode == GM_Game) - setGuiMode(GM_Inventory); - else if(mode == GM_Inventory) - setGuiMode(GM_Game); + // Toggle between game mode and inventory mode + if(gameMode) + windows.pushGuiMode(GM_Inventory); + else if(windows.getMode() == GM_Inventory) + windows.popGuiMode(); - // .. but don't touch any other mode. + // .. but don't touch any other mode. } // Toggle console @@ -167,28 +167,33 @@ namespace MWInput if (mDragDrop) return; - GuiMode mode = windows.getMode(); + bool gameMode = !windows.isGuiMode(); // Switch to console mode no matter what mode we are currently // in, except of course if we are already in console mode - if(mode == GM_Console) - setGuiMode(GM_Game); - else setGuiMode(GM_Console); + if (!gameMode) + { + if (windows.getMode() == GM_Console) + windows.popGuiMode(); + else + windows.pushGuiMode(GM_Console); + } + else + windows.pushGuiMode(GM_Console); } void toggleJournal() { - using namespace MWGui; + using namespace MWGui; - GuiMode mode = windows.getMode(); + // Toggle between game mode and journal mode + bool gameMode = !windows.isGuiMode(); - // Toggle between game mode and journal mode - if(mode == GM_Game) - setGuiMode(GM_Journal); - else if(mode == GM_Journal) - setGuiMode(GM_Game); - - // .. but don't touch any other mode. + if(gameMode) + windows.pushGuiMode(GM_Journal); + else if(windows.getMode() == GM_Journal) + windows.popGuiMode(); + // .. but don't touch any other mode. } void activate() @@ -282,8 +287,7 @@ namespace MWInput lst->add(guiEvents,Event::EV_ALL); } - // Start out in game mode - setGuiMode(MWGui::GM_Game); + changeInputMode(false); /********************************** Key binding section @@ -348,6 +352,7 @@ namespace MWInput windows.update(); // Disable movement in Gui mode + if (windows.isGuiMode()) return; // Configure player movement according to keyboard input. Actual movement will @@ -388,14 +393,10 @@ namespace MWInput // Switch between gui modes. Besides controlling the Gui windows // this also makes sure input is directed to the right place - void setGuiMode(MWGui::GuiMode mode) + void changeInputMode(bool guiMode) { - // Tell the GUI what to show (this also takes care of the mouse - // pointer) - windows.setMode(mode); - // Are we in GUI mode now? - if(windows.isGuiMode()) + if(guiMode) { // Disable mouse look mouse->setCamera(NULL); @@ -431,11 +432,6 @@ namespace MWInput delete impl; } - void MWInputManager::setGuiMode(MWGui::GuiMode mode) - { - impl->setGuiMode(mode); - } - void MWInputManager::update() { impl->update(); @@ -445,4 +441,9 @@ namespace MWInput { impl->setDragDrop(dragDrop); } + + void MWInputManager::changeInputMode(bool guiMode) + { + impl->changeInputMode(guiMode); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 158d05f0e..b8d98ed56 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -50,9 +50,9 @@ namespace MWInput void update(); - void setDragDrop(bool dragDrop); + void changeInputMode(bool guiMode); - void setGuiMode(MWGui::GuiMode mode); + void setDragDrop(bool dragDrop); }; } #endif diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index c4d9e9fab..b267cc6e4 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -44,7 +44,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getInputManager()->setGuiMode(mDialogue); + MWBase::Environment::get().getWindowManager()->pushGuiMode(mDialogue); } }; diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e450585e6..e2c8ec5cf 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,7 +16,7 @@ namespace MWWorld void ActionOpen::execute () { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Container); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(mContainer); } } diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 0d37e06f5..34e95cbd0 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -18,12 +18,12 @@ namespace MWWorld if (ref->base->data.isScroll) { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Scroll); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Scroll); MWBase::Environment::get().getWindowManager()->getScrollWindow()->open(mObject); } else { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Book); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book); MWBase::Environment::get().getWindowManager()->getBookWindow()->open(mObject); } } From a1907e7b88ceff1bfc54ace08b498d55a12c9cb0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 03:48:02 +0200 Subject: [PATCH 177/289] cleaning up mwgui/widgets part 1 --- apps/openmw/mwgui/widgets.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 74da7fc93..6e230e2c6 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -23,6 +23,18 @@ namespace MWGui { void fixTexturePath(std::string &path); + struct SpellEffectParams + { + bool mHasTarget; // potion effects for example have no target (target is always the player) + bool mIsConstant; // constant effect means that duration will not be displayed + std::string effectID; + + // note that the ESM::MagicEffect (retrieved through effectID) might already store skill and attribute, + // in that case the ESM::MagicEffect skill/attribute is preferred. this is just here for ingredients which + // have them defined elsewhere. + signed char skill, attribute; + }; + class MYGUI_EXPORT MWSkill : public Widget { MYGUI_RTTI_DERIVED( MWSkill ); From cb35f4d208d4760634b10aa28c341d3fd71ac9ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 03:50:02 +0200 Subject: [PATCH 178/289] some unrelated gui cleanup --- apps/openmw/mwgui/map_window.cpp | 6 +- apps/openmw/mwgui/stats_window.cpp | 115 -------------------- apps/openmw/mwgui/stats_window.hpp | 2 - apps/openmw/mwgui/window_manager.cpp | 2 + files/mygui/openmw_stats_window_layout.xml | 120 ++++++++++++++++++--- 5 files changed, 109 insertions(+), 136 deletions(-) diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 78ca70798..a44571d0a 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -102,7 +102,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : getWidget(mButton, "WorldButton"); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); - mButton->setCaption(mWindowManager.getGameSettingString("sWorld", "")); + mButton->setCaptionWithReplacing("#{sWorld}"); int width = mButton->getTextSize().width + 24; mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); @@ -172,8 +172,8 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) mGlobalMap->setVisible(mGlobal); mLocalMap->setVisible(!mGlobal); - mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") : - mWindowManager.getGameSettingString("sLocal", "")); + mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : + "#{sWorld}"); int width = mButton->getTextSize().width + 24; mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); } diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index cdf6a5871..54d9d7d4e 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -77,8 +77,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) MyGUI::WindowPtr t = static_cast(mMainWidget); t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); - - setupToolTips(); } void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -633,116 +631,3 @@ void StatsWindow::onPinToggled() { mWindowManager.setHMSVisibility(!mPinned); } - -void StatsWindow::setupToolTips() -{ - - const ESMS::ESMStore &store = mWindowManager.getStore(); - MyGUI::Widget* widget; - - /// \todo move this into the .layout file! - - getWidget(widget, "Attrib1"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); - getWidget(widget, "AttribVal1"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); - - getWidget(widget, "Attrib2"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); - getWidget(widget, "AttribVal2"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); - - getWidget(widget, "Attrib3"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); - getWidget(widget, "AttribVal3"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); - - getWidget(widget, "Attrib4"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); - getWidget(widget, "AttribVal4"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); - - getWidget(widget, "Attrib5"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); - getWidget(widget, "AttribVal5"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); - - getWidget(widget, "Attrib6"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); - getWidget(widget, "AttribVal6"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); - - getWidget(widget, "Attrib7"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); - getWidget(widget, "AttribVal7"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); - - getWidget(widget, "Attrib8"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); - getWidget(widget, "AttribVal8"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); -} diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 50a83bb29..bbd916585 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -50,8 +50,6 @@ namespace MWGui MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); - void setupToolTips(); - void setFactions (const FactionList& factions); void setBirthSign (const std::string &signId); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 09ea6543a..6be712509 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -608,4 +608,6 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(_tag); if (setting && setting->type == ESM::VT_String) _result = setting->str; + else + _result = _tag; } diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 4729e3bca..81d70f704 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -99,29 +99,117 @@ - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + From 9b94edd561d27a69ba137c89f225ed49cbd5bf2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 04:34:53 +0200 Subject: [PATCH 179/289] audio tab with volume sliders --- apps/openmw/mwgui/settingswindow.cpp | 44 ++++++++++++++++--- apps/openmw/mwgui/settingswindow.hpp | 9 ++++ apps/openmw/mwsound/soundmanager.cpp | 16 +++++-- apps/openmw/mwsound/soundmanager.hpp | 8 ++++ files/mygui/openmw_settings_window_layout.xml | 43 ++++++++++++++++-- files/settings-default.cfg | 4 +- 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 6eaf31ce9..d8e1072e3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -24,6 +24,11 @@ namespace MWGui getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); + getWidget(mMasterVolumeSlider, "MasterVolume"); + getWidget(mVoiceVolumeSlider, "VoiceVolume"); + getWidget(mEffectsVolumeSlider, "EffectsVolume"); + getWidget(mFootstepsVolumeSlider, "FootstepsVolume"); + getWidget(mMusicVolumeSlider, "MusicVolume"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -31,6 +36,12 @@ namespace MWGui mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); + mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + center(); int okSize = mOkButton->getTextSize().width + 24; @@ -54,6 +65,12 @@ namespace MWGui int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; mViewDistanceSlider->setScrollPosition(viewdist); + mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1)); + mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1)); + mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1)); + mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); + mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); + std::string on = mWindowManager.getGameSettingString("sOn", "On"); std::string off = mWindowManager.getGameSettingString("sOff", "On"); @@ -90,7 +107,7 @@ namespace MWGui Settings::Manager::setInt("resolution x", "Video", resX); Settings::Manager::setInt("resolution y", "Video", resY); - MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + apply(); } void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) @@ -117,14 +134,27 @@ namespace MWGui { float val = pos / float(scroller->getScrollRange()-1); if (scroller == mMenuTransparencySlider) - { Settings::Manager::setFloat("menu transparency", "GUI", val); - } else if (scroller == mViewDistanceSlider) - { - Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); - } + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + else if (scroller == mMasterVolumeSlider) + Settings::Manager::setFloat("master volume", "Sound", val); + else if (scroller == mVoiceVolumeSlider) + Settings::Manager::setFloat("voice volume", "Sound", val); + else if (scroller == mEffectsVolumeSlider) + Settings::Manager::setFloat("sfx volume", "Sound", val); + else if (scroller == mFootstepsVolumeSlider) + Settings::Manager::setFloat("footsteps volume", "Sound", val); + else if (scroller == mMusicVolumeSlider) + Settings::Manager::setFloat("music volume", "Sound", val); - MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + apply(); + } + + void SettingsWindow::apply() + { + const Settings::CategorySettingVector changed = Settings::Manager::apply(); + MWBase::Environment::get().getWorld()->processChangedSettings(changed); + MWBase::Environment::get().getWorld()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 785b0c9b1..62acc5649 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -22,11 +22,20 @@ namespace MWGui MyGUI::ScrollBar* mMenuTransparencySlider; MyGUI::ScrollBar* mViewDistanceSlider; + // audio + MyGUI::ScrollBar* mMasterVolumeSlider; + MyGUI::ScrollBar* mVoiceVolumeSlider; + MyGUI::ScrollBar* mEffectsVolumeSlider; + MyGUI::ScrollBar* mFootstepsVolumeSlider; + MyGUI::ScrollBar* mMusicVolumeSlider; + void onOkButtonClicked(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); void onResolutionAccept(); + + void apply(); }; } diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 8deab3c04..11576e22a 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "../mwbase/environment.hpp" @@ -53,6 +52,8 @@ namespace MWSound , mMasterVolume(1.0f) , mSFXVolume(1.0f) , mMusicVolume(1.0f) + , mFootstepsVolume(1.0f) + , mVoiceVolume(1.0f) { if(!useSound) return; @@ -210,7 +211,7 @@ namespace MWSound try { // The range values are not tested - float basevol = mMasterVolume * mSFXVolume; + float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; const ESM::Position &pos = ptr.getCellRef().pos; const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); @@ -234,7 +235,7 @@ namespace MWSound return; try { - float basevol = mMasterVolume * mSFXVolume; + float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); @@ -527,6 +528,15 @@ namespace MWSound } + void SoundManager::processChangedSettings(const Settings::CategorySettingVector& settings) + { + mMasterVolume = Settings::Manager::getFloat("master volume", "Sound"); + mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); + mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); + mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); + mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + } + // Default readAll implementation, for decoders that can't do anything // better void Sound_Decoder::readAll(std::vector &output) diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index e1816cd1f..562b2af00 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -7,6 +7,8 @@ #include +#include + #include "../mwworld/ptr.hpp" @@ -52,6 +54,10 @@ namespace MWSound float mMasterVolume; float mSFXVolume; float mMusicVolume; + float mVoiceVolume; + + // not implemented + float mFootstepsVolume; boost::shared_ptr mMusic; std::string mCurrentPlaylist; @@ -78,6 +84,8 @@ namespace MWSound SoundManager(bool useSound); ~SoundManager(); + void processChangedSettings(const Settings::CategorySettingVector& settings); + void stopMusic(); ///< Stops music if it's playing diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 2fa332d9a..dc1cbfa9e 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -9,23 +9,58 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index ab0b75ff2..a6623656c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -131,7 +131,9 @@ underwater effect = true # Device name. Blank means default device = -# Volumes. Sfx and music volumes are both affected by the master volume +# Volumes. master volume affects all other volumes. master volume = 1.0 sfx volume = 1.0 music volume = 0.4 +footsteps volume = 0.6 +voice volume = 1.0 From 189b044392b6fc94464d3450ca73754b38abb1ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 04:37:41 +0200 Subject: [PATCH 180/289] small correction --- apps/openmw/mwsound/soundmanager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 11576e22a..b6f4296aa 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -64,6 +64,10 @@ namespace MWSound mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f); mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + mVoiceVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); + mFootstepsVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); std::cout << "Sound output: " << SOUND_OUT << std::endl; std::cout << "Sound decoder: " << SOUND_IN << std::endl; From cbe89f7e32eede6ea7773a5d606066329b01344b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 08:56:45 +0200 Subject: [PATCH 181/289] copy&paste mistake --- apps/openmw/mwsound/soundmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b6f4296aa..27294ae77 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -65,9 +65,9 @@ namespace MWSound mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); - mVoiceVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mVoiceVolume = std::min(std::max(mVoiceVolume, 0.0f), 1.0f); mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); - mFootstepsVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f); std::cout << "Sound output: " << SOUND_OUT << std::endl; std::cout << "Sound decoder: " << SOUND_IN << std::endl; From 6ea7bdb224c07a6965482610508d02c6f78c9b89 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 11:50:48 +0200 Subject: [PATCH 182/289] vsync & fps buttons, sound volume apply fix --- apps/openmw/mwgui/settingswindow.cpp | 42 ++++++++++++-- apps/openmw/mwgui/settingswindow.hpp | 8 ++- apps/openmw/mwgui/window_manager.cpp | 13 ++--- apps/openmw/mwgui/window_manager.hpp | 6 +- apps/openmw/mwinput/inputmanager.cpp | 10 ---- files/mygui/openmw_settings_window_layout.xml | 58 +++++++++++++------ 6 files changed, 92 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d8e1072e3..ce7f0d0e2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -10,10 +10,24 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "confirmationdialog.hpp" +namespace +{ + std::string fpsLevelToStr(int level) + { + if (level == 0) + return "#{sOff}"; + else if (level == 1) + return "Basic"; + else + return "Detailed"; + } +} + namespace MWGui { SettingsWindow::SettingsWindow(WindowManager& parWindowManager) : @@ -24,6 +38,8 @@ namespace MWGui getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); + getWidget(mVSyncButton, "VSyncButton"); + getWidget(mFPSButton, "FPSButton"); getWidget(mMasterVolumeSlider, "MasterVolume"); getWidget(mVoiceVolumeSlider, "VoiceVolume"); getWidget(mEffectsVolumeSlider, "EffectsVolume"); @@ -32,6 +48,8 @@ namespace MWGui mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); @@ -71,10 +89,9 @@ namespace MWGui mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); - std::string on = mWindowManager.getGameSettingString("sOn", "On"); - std::string off = mWindowManager.getGameSettingString("sOff", "On"); - - mFullscreenButton->setCaption(Settings::Manager::getBool("fullscreen", "Video") ? on : off); + mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); + mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); + mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -128,6 +145,20 @@ namespace MWGui if (_sender == mFullscreenButton) Settings::Manager::setBool("fullscreen", "Video", newState); + else if (_sender == mVSyncButton) + { + Settings::Manager::setBool("vsync", "Video", newState); + MWBase::Environment::get().getWindowManager()-> + messageBox("VSync will be applied after a restart", std::vector()); + } + } + + void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) + { + int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; + Settings::Manager::setInt("fps", "HUD", newLevel); + mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel)); + apply(); } void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -155,6 +186,7 @@ namespace MWGui { const Settings::CategorySettingVector changed = Settings::Manager::apply(); MWBase::Environment::get().getWorld()->processChangedSettings(changed); - MWBase::Environment::get().getWorld()->processChangedSettings(changed); + MWBase::Environment::get().getSoundManager()->processChangedSettings(changed); + MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 62acc5649..79af03994 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -17,9 +17,14 @@ namespace MWGui protected: MyGUI::Button* mOkButton; + + MyGUI::ScrollBar* mMenuTransparencySlider; + + // graphics MyGUI::ListBox* mResolutionList; MyGUI::Button* mFullscreenButton; - MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::Button* mVSyncButton; + MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; // audio @@ -30,6 +35,7 @@ namespace MWGui MyGUI::ScrollBar* mMusicVolumeSlider; void onOkButtonClicked(MyGUI::Widget* _sender); + void onFpsToggled(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 6be712509..b71edc718 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -554,14 +554,6 @@ void WindowManager::toggleFogOfWar() hud->toggleFogOfWar(); } -int WindowManager::toggleFps() -{ - showFPSLevel = (showFPSLevel+1)%3; - hud->setFpsLevel(showFPSLevel); - Settings::Manager::setInt("fps", "HUD", showFPSLevel); - return showFPSLevel; -} - void WindowManager::setFocusObject(const MWWorld::Ptr& focus) { mToolTips->setFocusObject(focus); @@ -611,3 +603,8 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r else _result = _tag; } + +void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) +{ + hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 9ccc42b1e..f585ac3ba 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -17,6 +17,7 @@ #include "MyGUI_UString.h" #include +#include #include #include @@ -182,9 +183,6 @@ namespace MWGui void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; - int toggleFps(); - ///< toggle fps display @return resulting fps level - void setInteriorMapTexture(const int x, const int y); ///< set the index of the map texture that should be used (for interiors) @@ -215,6 +213,8 @@ namespace MWGui const ESMS::ESMStore& getStore() const; + void processChangedSettings(const Settings::CategorySettingVector& changed); + private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *hud; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8fd6a9c6b..3ae1daadf 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -69,8 +69,6 @@ namespace MWInput A_ToggleWeapon, A_ToggleSpell, - A_ToggleFps, // Toggle FPS display (this is temporary) - A_Settings, // Temporary hotkey A_LAST // Marker for the last item @@ -95,11 +93,6 @@ namespace MWInput /* InputImpl Methods */ - void toggleFps() - { - windows.toggleFps(); - } - void toggleSpell() { if (windows.isGuiMode()) return; @@ -271,8 +264,6 @@ namespace MWInput "Draw Weapon"); disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this), "Ready hands"); - disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this), - "Toggle FPS display"); disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this), "Show settings window"); // Add the exit listener @@ -321,7 +312,6 @@ namespace MWInput disp->bind(A_ToggleWalk, KC_C); disp->bind(A_ToggleWeapon,KC_F); disp->bind(A_ToggleSpell,KC_R); - disp->bind(A_ToggleFps, KC_F10); disp->bind(A_Settings, KC_F2); // Key bindings for polled keys diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index dc1cbfa9e..9b5826765 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -68,25 +68,47 @@ - - - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 57d834b14bcea471c335cf2581a0bb2c900ff33f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 12:05:43 +0200 Subject: [PATCH 183/289] fixed an issue with interactive messagebox --- apps/openmw/mwgui/messagebox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 9a0671478..9df80476e 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,6 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; + mWindowManager->popGuiMode(); } } From c0ee382c7211e027a22608cbf5194e4d7008bd5d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 May 2012 13:21:52 +0200 Subject: [PATCH 184/289] Issue #176: made actor deregistration more robust --- apps/openmw/mwmechanics/actors.cpp | 5 ++++- apps/openmw/mwmechanics/actors.hpp | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 5a17d50e4..8f8fd6871 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -71,7 +71,10 @@ namespace MWMechanics void Actors::removeActor (const MWWorld::Ptr& ptr) { - mActors.erase (ptr); + std::set::iterator iter = mActors.find (ptr); + + if (iter!=mActors.end()) + mActors.erase (iter); } void Actors::dropActors (const MWWorld::Ptr::CellStore *cellStore) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 30e73ccf7..1be29463f 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -32,6 +32,8 @@ namespace MWMechanics void removeActor (const MWWorld::Ptr& ptr); ///< Deregister an actor for stats management + /// + /// \note Ignored, if \a ptr is not a registered actor. void dropActors (const MWWorld::Ptr::CellStore *cellStore); ///< Deregister all actors in the given cell. From 684208dfc9eb457c20bd7c473e0a5c5993db5458 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 May 2012 13:26:07 +0200 Subject: [PATCH 185/289] Issue #176: when deleting objects, don't go through disable to remove actors from the mechanics manager --- apps/openmw/mwworld/world.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c0107d9af..6d42560d2 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -553,16 +553,17 @@ namespace MWWorld { ptr.getRefData().setCount (0); + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) + { + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){ -// Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed - MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); - mPhysics->removeObject (ptr.getRefData().getHandle()); - mRendering->removeObject(ptr); + mPhysics->removeObject (ptr.getRefData().getHandle()); + mRendering->removeObject(ptr); - mLocalScripts.remove (ptr); - } + mLocalScripts.remove (ptr); + } } } From 05fd8f0211967781ce0848c82d8138e3eb749eee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 24 May 2012 05:30:22 -0700 Subject: [PATCH 186/289] Update the actual sounds and music volume when settings change --- apps/openmw/mwsound/soundmanager.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 27294ae77..ff618ac33 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -539,6 +539,30 @@ namespace MWSound mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + + SoundMap::iterator snditer = mActiveSounds.begin(); + while(snditer != mActiveSounds.end()) + { + if(snditer->second.second != "_say_sound") + { + float basevol = mMasterVolume * mSFXVolume; + float min, max; + lookup(snditer->second.second, basevol, min, max); + snditer->first->mBaseVolume = basevol; + } + else + { + float basevol = mMasterVolume * mVoiceVolume; + snditer->first->mBaseVolume = basevol; + } + snditer->first->update(); + snditer++; + } + if(mMusic) + { + mMusic->mBaseVolume = mMasterVolume * mMusicVolume; + mMusic->update(); + } } // Default readAll implementation, for decoders that can't do anything From a3a22e9096c1f055e20014690c359694c4033e59 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 14:47:57 +0200 Subject: [PATCH 187/289] ingredient tooltip shows possible effects --- apps/openmw/mwclass/ingredient.cpp | 13 ++ apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 6 +- apps/openmw/mwgui/tooltips.hpp | 9 +- apps/openmw/mwgui/widgets.cpp | 195 ++++++++++++++++++----------- apps/openmw/mwgui/widgets.hpp | 56 ++++++--- 6 files changed, 178 insertions(+), 103 deletions(-) diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index c0186da37..0c7fa7e69 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -135,6 +135,19 @@ namespace MWClass text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); } + MWGui::Widgets::SpellEffectList list; + for (int i=0; i<4; ++i) + { + if (ref->base->data.effectID[i] < 0) + continue; + MWGui::Widgets::SpellEffectParams params; + params.mEffectID = ref->base->data.effectID[i]; + params.mAttribute = ref->base->data.attributes[i]; + params.mSkill = ref->base->data.skills[i]; + list.push_back(params); + } + info.effects = list; + info.text = text; return info; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index ffc838639..157af01f5 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -132,7 +132,7 @@ namespace MWClass text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); - info.effects = &ref->base->effects; + info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->base->effects); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 3ade598ba..c61aa56a3 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -285,7 +285,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)), ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight ); - if (info.effects != 0) + if (!info.effects.empty()) { Widget* effectArea = mDynamicToolTipBox->createWidget("", IntCoord(0, totalSize.height, 300, 300-totalSize.height), @@ -305,7 +305,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) effectsWidget->setEffectList(info.effects); std::vector effectItems; - effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_Potion); + effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_NoTarget); totalSize.height += coord.top-6; totalSize.width = std::max(totalSize.width, coord.width); } @@ -321,7 +321,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); enchantWidget->setWindowManager(mWindowManager); - enchantWidget->setEffectList(&enchant->effects); + enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->effects)); std::vector enchantEffectItems; int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 4be0baff9..6d4a205d1 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -5,6 +5,8 @@ #include #include "../mwworld/ptr.hpp" +#include "widgets.hpp" + namespace MWGui { class WindowManager; @@ -13,11 +15,6 @@ namespace MWGui struct ToolTipInfo { public: - ToolTipInfo() : - effects(0) - { - }; - std::string caption; std::string text; std::string icon; @@ -26,7 +23,7 @@ namespace MWGui std::string enchant; // effects (for potions, ingredients) - const ESM::EffectList* effects; + Widgets::SpellEffectList effects; }; class ToolTips : public OEngine::GUI::Layout diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 0422bb0e2..2fd40b7c2 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -234,8 +234,17 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI: { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - effect->setFlags(flags); - effect->setSpellEffect(*it); + SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (flags & MWEffectList::EF_Constant); + params.mNoTarget = (flags & MWEffectList::EF_NoTarget); + effect->setSpellEffect(params); effects.push_back(effect); coord.top += effect->getHeight(); coord.width = std::max(coord.width, effect->getRequestedWidth()); @@ -274,7 +283,7 @@ MWEffectList::MWEffectList() { } -void MWEffectList::setEffectList(const ESM::EffectList* list) +void MWEffectList::setEffectList(const SpellEffectList& list) { mEffectList = list; updateWidgets(); @@ -283,25 +292,26 @@ void MWEffectList::setEffectList(const ESM::EffectList* list) void MWEffectList::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags) { // We don't know the width of all the elements beforehand, so we do it in - // 2 steps: first, create all widgets and check their width + // 2 steps: first, create all widgets and check their width.... MWSpellEffectPtr effect = nullptr; - std::vector::const_iterator end = mEffectList->list.end(); int maxwidth = coord.width; - for (std::vector::const_iterator it = mEffectList->list.begin(); it != end; ++it) + + for (SpellEffectList::iterator it=mEffectList.begin(); + it != mEffectList.end(); ++it) { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - effect->setFlags(flags); + it->mIsConstant = (flags & EF_Constant); + it->mNoTarget = (flags & EF_NoTarget); effect->setSpellEffect(*it); effects.push_back(effect); - if (effect->getRequestedWidth() > maxwidth) maxwidth = effect->getRequestedWidth(); coord.top += effect->getHeight(); } - // then adjust the size for all widgets + // ... then adjust the size for all widgets for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) { effect = static_cast(*it); @@ -334,6 +344,25 @@ MWEffectList::~MWEffectList() { } +SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects) +{ + SpellEffectList result; + std::vector::const_iterator end = effects->list.end(); + for (std::vector::const_iterator it = effects->list.begin(); it != end; ++it) + { + SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + result.push_back(params); + } + return result; +} + /* MWSpellEffect */ MWSpellEffect::MWSpellEffect() @@ -341,13 +370,12 @@ MWSpellEffect::MWSpellEffect() , imageWidget(nullptr) , textWidget(nullptr) , mRequestedWidth(0) - , mFlags(0) { } -void MWSpellEffect::setSpellEffect(SpellEffectValue value) +void MWSpellEffect::setSpellEffect(const SpellEffectParams& params) { - effect = value; + mEffectParams = params; updateWidgets(); } @@ -357,74 +385,71 @@ void MWSpellEffect::updateWidgets() return; const ESMS::ESMStore &store = mWindowManager->getStore(); - const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID); + const ESM::MagicEffect *magicEffect = store.magicEffects.search(mEffectParams.mEffectID); + if (!magicEffect) + return; if (textWidget) { - if (magicEffect) + std::string pt = mWindowManager->getGameSettingString("spoint", ""); + std::string pts = mWindowManager->getGameSettingString("spoints", ""); + std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; + std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); + std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); + + std::string effectIDStr = effectIDToString(mEffectParams.mEffectID); + std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); + if (effectInvolvesSkill(effectIDStr) && mEffectParams.mSkill >= 0 && mEffectParams.mSkill < ESM::Skill::Length) { - std::string pt = mWindowManager->getGameSettingString("spoint", ""); - std::string pts = mWindowManager->getGameSettingString("spoints", ""); - std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; - std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); - std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); - - std::string effectIDStr = effectIDToString(effect.effectID); - std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); - if (effect.skill >= 0 && effect.skill < ESM::Skill::Length) - { - spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], ""); - } - if (effect.attribute >= 0 && effect.attribute < 8) - { - static const char *attributes[8] = { - "sAttributeStrength", - "sAttributeIntelligence", - "sAttributeWillpower", - "sAttributeAgility", - "sAttributeSpeed", - "sAttributeEndurance", - "sAttributePersonality", - "sAttributeLuck" - }; - spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], ""); - } - - if ((effect.magnMin >= 0 || effect.magnMax >= 0) && effectHasMagnitude(effectIDStr)) - { - if (effect.magnMin == effect.magnMax) - spellLine += " " + boost::lexical_cast(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts); - else - { - spellLine += " " + boost::lexical_cast(effect.magnMin) + to + boost::lexical_cast(effect.magnMax) + " " + pts; - } - } - - // constant effects have no duration and no target - if (!(mFlags & MWEffectList::EF_Constant)) - { - if (effect.duration >= 0 && effectHasDuration(effectIDStr)) - { - spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(effect.duration) + ((effect.duration == 1) ? sec : secs); - } - - // potions have no target - if (!(mFlags & MWEffectList::EF_Potion)) - { - std::string on = mWindowManager->getGameSettingString("sonword", ""); - if (effect.range == ESM::RT_Self) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); - else if (effect.range == ESM::RT_Touch) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); - else if (effect.range == ESM::RT_Target) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); - } - } - - static_cast(textWidget)->setCaption(spellLine); - mRequestedWidth = textWidget->getTextSize().width + 24; + spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], ""); } - else - static_cast(textWidget)->setCaption(""); + if (effectInvolvesAttribute(effectIDStr) && mEffectParams.mAttribute >= 0 && mEffectParams.mAttribute < 8) + { + static const char *attributes[8] = { + "sAttributeStrength", + "sAttributeIntelligence", + "sAttributeWillpower", + "sAttributeAgility", + "sAttributeSpeed", + "sAttributeEndurance", + "sAttributePersonality", + "sAttributeLuck" + }; + spellLine += " " + mWindowManager->getGameSettingString(attributes[mEffectParams.mAttribute], ""); + } + + if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && effectHasMagnitude(effectIDStr)) + { + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts); + else + { + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax) + " " + pts; + } + } + + // constant effects have no duration and no target + if (!mEffectParams.mIsConstant) + { + if (mEffectParams.mDuration >= 0 && effectHasDuration(effectIDStr)) + { + spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); + } + + // potions have no target + if (!mEffectParams.mNoTarget) + { + std::string on = mWindowManager->getGameSettingString("sonword", ""); + if (mEffectParams.mRange == ESM::RT_Self) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); + else if (mEffectParams.mRange == ESM::RT_Touch) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); + else if (mEffectParams.mRange == ESM::RT_Target) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); + } + } + + static_cast(textWidget)->setCaption(spellLine); + mRequestedWidth = textWidget->getTextSize().width + 24; } if (imageWidget) { @@ -677,6 +702,24 @@ bool MWSpellEffect::effectHasMagnitude(const std::string& effect) return (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effect) == effectsWithoutMagnitude.end()); } +bool MWSpellEffect::effectInvolvesAttribute (const std::string& effect) +{ + return (effect == "sEffectRestoreAttribute" + || effect == "sEffectAbsorbAttribute" + || effect == "sEffectDrainAttribute" + || effect == "sEffectFortifyAttribute" + || effect == "sEffectDamageAttribute"); +} + +bool MWSpellEffect::effectInvolvesSkill (const std::string& effect) +{ + return (effect == "sEffectRestoreSkill" + || effect == "sEffectAbsorbSkill" + || effect == "sEffectDrainSkill" + || effect == "sEffectFortifySkill" + || effect == "sEffectDamageSkill"); +} + MWSpellEffect::~MWSpellEffect() { } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 6e230e2c6..54a278f1c 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -21,20 +21,40 @@ namespace MWGui namespace Widgets { + class MWEffectList; + void fixTexturePath(std::string &path); struct SpellEffectParams { - bool mHasTarget; // potion effects for example have no target (target is always the player) - bool mIsConstant; // constant effect means that duration will not be displayed - std::string effectID; + SpellEffectParams() + : mMagnMin(-1) + , mMagnMax(-1) + , mRange(-1) + , mDuration(-1) + , mSkill(-1) + , mAttribute(-1) + , mEffectID(-1) + , mNoTarget(false) + , mIsConstant(false) + { + } - // note that the ESM::MagicEffect (retrieved through effectID) might already store skill and attribute, - // in that case the ESM::MagicEffect skill/attribute is preferred. this is just here for ingredients which - // have them defined elsewhere. - signed char skill, attribute; + bool mNoTarget; // potion effects for example have no target (target is always the player) + bool mIsConstant; // constant effect means that duration will not be displayed + + // value of -1 here means the effect is unknown to the player + short mEffectID; + + // value of -1 here means there is no skill/attribute + signed char mSkill, mAttribute; + + // value of -1 here means the value is unavailable + int mMagnMin, mMagnMax, mRange, mDuration; }; + typedef std::vector SpellEffectList; + class MYGUI_EXPORT MWSkill : public Widget { MYGUI_RTTI_DERIVED( MWSkill ); @@ -120,6 +140,9 @@ namespace MWGui }; typedef MWAttribute* MWAttributePtr; + /** + * @todo remove this class and use MWEffectList instead + */ class MWSpellEffect; class MYGUI_EXPORT MWSpell : public Widget { @@ -167,12 +190,14 @@ namespace MWGui enum EffectFlags { - EF_Potion = 0x01, // potions have no target (target is always the player) + EF_NoTarget = 0x01, // potions have no target (target is always the player) EF_Constant = 0x02 // constant effect means that duration will not be displayed }; void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } - void setEffectList(const ESM::EffectList* list); + void setEffectList(const SpellEffectList& list); + + static SpellEffectList effectListFromESM(const ESM::EffectList* effects); /** * @param vector to store the created effect widgets @@ -192,7 +217,7 @@ namespace MWGui void updateWidgets(); WindowManager* mWindowManager; - const ESM::EffectList* mEffectList; + SpellEffectList mEffectList; }; typedef MWEffectList* MWEffectListPtr; @@ -205,14 +230,13 @@ namespace MWGui typedef ESM::ENAMstruct SpellEffectValue; void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } - void setSpellEffect(SpellEffectValue value); - void setFlags(int flags) { mFlags = flags; } + void setSpellEffect(const SpellEffectParams& params); std::string effectIDToString(const short effectID); bool effectHasMagnitude (const std::string& effect); bool effectHasDuration (const std::string& effect); - - const SpellEffectValue &getSpellEffect() const { return effect; } + bool effectInvolvesAttribute (const std::string& effect); + bool effectInvolvesSkill (const std::string& effect); int getRequestedWidth() const { return mRequestedWidth; } @@ -226,8 +250,7 @@ namespace MWGui void updateWidgets(); WindowManager* mWindowManager; - SpellEffectValue effect; - int mFlags; + SpellEffectParams mEffectParams; MyGUI::ImageBox* imageWidget; MyGUI::TextBox* textWidget; int mRequestedWidth; @@ -259,7 +282,6 @@ namespace MWGui MyGUI::TextBox* barTextWidget; }; typedef MWDynamicStat* MWDynamicStatPtr; - } } From c2b818373e075af0c3b8be49e9caacfa4e78d871 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 15:11:45 +0200 Subject: [PATCH 188/289] adjust tooltip skin, now is never transparent --- apps/openmw/mwgui/tooltips.cpp | 8 +++---- files/mygui/openmw_hud_box.skin.xml | 37 +++++++++++++++++++++++++++++ files/mygui/openmw_tooltips.xml | 18 +++++++------- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 3ade598ba..49e68bd86 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -37,10 +37,10 @@ void ToolTips::setEnabled(bool enabled) void ToolTips::onFrame(float frameDuration) { - MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); - mDynamicToolTipBox = mMainWidget->createWidget("HUD_Box", - IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), - Align::Stretch, "DynamicToolTipBox"); + while (mDynamicToolTipBox->getChildCount()) + { + MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0)); + } // start by hiding everything for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i) diff --git a/files/mygui/openmw_hud_box.skin.xml b/files/mygui/openmw_hud_box.skin.xml index 86b63fcf6..ce231e5bb 100644 --- a/files/mygui/openmw_hud_box.skin.xml +++ b/files/mygui/openmw_hud_box.skin.xml @@ -38,4 +38,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index a1673d346..262fd2020 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -4,12 +4,12 @@ - + - + @@ -22,7 +22,7 @@ - + @@ -40,7 +40,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -78,7 +78,7 @@ - + @@ -98,7 +98,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -156,7 +156,7 @@ - + From 09c870ad68d79424eb089ab50c4cda569805a4af Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 12:58:28 +0200 Subject: [PATCH 189/289] first alchemy window layout (not pretty) --- apps/openmw/mwgui/alchemywindow.cpp | 27 +++++++ apps/openmw/mwgui/alchemywindow.hpp | 7 ++ files/mygui/openmw_alchemy_window_layout.xml | 80 ++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 570a1f6d4..90326c3d7 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,10 +1,37 @@ #include "alchemywindow.hpp" +#include "window_manager.hpp" + namespace MWGui { AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager) : WindowBase("openmw_alchemy_window_layout.xml", parWindowManager) { + getWidget(mCreateButton, "CreateButton"); + getWidget(mCancelButton, "CancelButton"); + + + MyGUI::Widget* buttonBox = mCancelButton->getParent(); + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(buttonBox->getWidth() - cancelButtonWidth, + mCancelButton->getTop(), cancelButtonWidth, mCancelButton->getHeight()); + int createButtonWidth = mCreateButton->getTextSize().width + 24; + mCreateButton->setCoord(buttonBox->getWidth() - createButtonWidth - cancelButtonWidth - 4, + mCreateButton->getTop(), createButtonWidth, mCreateButton->getHeight()); + + mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked); + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked); + center(); } + + void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) + { + mWindowManager.popGuiMode(); + mWindowManager.popGuiMode(); + } + + void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) + { + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 37e50413b..d43bb6d33 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -9,6 +9,13 @@ namespace MWGui { public: AlchemyWindow(WindowManager& parWindowManager); + + protected: + MyGUI::Button* mCreateButton; + MyGUI::Button* mCancelButton; + + void onCancelButtonClicked(MyGUI::Widget* _sender); + void onCreateButtonClicked(MyGUI::Widget* _sender); }; } diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index c6c4b1caa..22511f013 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -3,6 +3,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6eb15f7680be9c48409cc5c0eeb1e7e413fe6b1d Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 15:24:33 +0200 Subject: [PATCH 190/289] 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: From 1df1b521a4d06edd482f18a36b4410b13d2c9021 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 16:20:57 +0200 Subject: [PATCH 191/289] show the list of potion effects --- apps/openmw/mwgui/alchemywindow.cpp | 107 ++++++++++++++++++- apps/openmw/mwgui/alchemywindow.hpp | 4 + apps/openmw/mwgui/widgets.hpp | 7 ++ files/mygui/openmw_alchemy_window_layout.xml | 2 +- 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 60ad123a5..c9548e05d 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -4,6 +4,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" @@ -36,6 +37,7 @@ namespace MWGui getWidget(mApparatus2, "Apparatus2"); getWidget(mApparatus3, "Apparatus3"); getWidget(mApparatus4, "Apparatus4"); + getWidget(mEffectsBox, "CreatedEffects"); mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); @@ -143,6 +145,41 @@ namespace MWGui { MyGUI::ImageBox* add = NULL; + // don't allow to add an ingredient that is already added + // (which could happen if two similiar ingredients don't stack because of script / owner) + bool alreadyAdded = false; + std::string name = MWWorld::Class::get(item).getName(item); + if (mIngredient1->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient1->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient2->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient2->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient3->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient3->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient4->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient4->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (alreadyAdded) + return; + if (!mIngredient1->isUserString("ToolTipType")) add = mIngredient1; if (add == NULL && !mIngredient2->isUserString("ToolTipType")) @@ -159,6 +196,9 @@ namespace MWGui add->setImageTexture(getIconPath(item)); drawItems(); update(); + + std::string sound = MWWorld::Class::get(item).getUpSoundId(item); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } } @@ -180,7 +220,8 @@ namespace MWGui void AlchemyWindow::update() { - // update ingredient count labels + Widgets::SpellEffectList effects; + for (int i=0; i<4; ++i) { MyGUI::ImageBox* ingredient; @@ -196,6 +237,20 @@ namespace MWGui if (!ingredient->isUserString("ToolTipType")) continue; + // add the effects of this ingredient to list of effects + ESMS::LiveCellRef* ref = ingredient->getUserData()->get(); + for (int i=0; i<4; ++i) + { + if (ref->base->data.effectID[i] < 0) + continue; + MWGui::Widgets::SpellEffectParams params; + params.mEffectID = ref->base->data.effectID[i]; + params.mAttribute = ref->base->data.attributes[i]; + params.mSkill = ref->base->data.skills[i]; + effects.push_back(params); + } + + // update ingredient count labels if (ingredient->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); @@ -206,5 +261,55 @@ namespace MWGui text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setCaption(getCountString(ingredient->getUserData()->getRefData().getCount())); } + + // now remove effects that are only present once + Widgets::SpellEffectList::iterator it = effects.begin(); + while (it != effects.end()) + { + Widgets::SpellEffectList::iterator next = it; + ++next; + bool found = false; + for (; next != effects.end(); ++next) + { + if (*next == *it) + found = true; + } + + if (!found) + it = effects.erase(it); + else + ++it; + } + + // now remove duplicates + Widgets::SpellEffectList old = effects; + effects.clear(); + for (Widgets::SpellEffectList::iterator it = old.begin(); + it != old.end(); ++it) + { + bool found = false; + for (Widgets::SpellEffectList::iterator it2 = effects.begin(); + it2 != effects.end(); ++it2) + { + if (*it2 == *it) + found = true; + } + if (!found) + effects.push_back(*it); + } + mEffects = effects; + + while (mEffectsBox->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0)); + + MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24); + Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget + ("MW_StatName", coord, Align::Left | Align::Top); + effectsWidget->setWindowManager(&mWindowManager); + effectsWidget->setEffectList(effects); + + std::vector effectItems; + effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); + effectsWidget->setCoord(coord); } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 365ad9642..17f363e92 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -27,6 +27,10 @@ namespace MWGui MyGUI::ImageBox* mApparatus3; MyGUI::ImageBox* mApparatus4; + MyGUI::Widget* mEffectsBox; + + Widgets::SpellEffectList mEffects; // effects of created potion + void onCancelButtonClicked(MyGUI::Widget* _sender); void onCreateButtonClicked(MyGUI::Widget* _sender); void onIngredientSelected(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 54a278f1c..c66bf5dd0 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -51,6 +51,13 @@ namespace MWGui // value of -1 here means the value is unavailable int mMagnMin, mMagnMax, mRange, mDuration; + + bool operator==(const SpellEffectParams& other) const + { + return (other.mEffectID == mEffectID + && other.mSkill == mSkill + && other.mAttribute == mAttribute); + } }; typedef std::vector SpellEffectList; diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 22511f013..8eb5e1265 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -72,7 +72,7 @@ - + From 63b3b82657fb5a3c4d3782eaf3848ffd32c4258a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 16:23:49 +0200 Subject: [PATCH 192/289] don't allow more than 4 potion effects --- apps/openmw/mwgui/alchemywindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index c9548e05d..bd2f05289 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -281,9 +281,10 @@ namespace MWGui ++it; } - // now remove duplicates + // now remove duplicates, and don't allow more than 4 effects Widgets::SpellEffectList old = effects; effects.clear(); + int i=0; for (Widgets::SpellEffectList::iterator it = old.begin(); it != old.end(); ++it) { @@ -294,8 +295,11 @@ namespace MWGui if (*it2 == *it) found = true; } - if (!found) + if (!found && i<4) + { + ++i; effects.push_back(*it); + } } mEffects = effects; From 36885b2e4004bff3610b08ee283828b4d081b2fa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:04:33 +0200 Subject: [PATCH 193/289] Issue #176: removed enable/disable functions from Creature, Npc and Light --- apps/openmw/mwclass/creature.cpp | 9 --------- apps/openmw/mwclass/creature.hpp | 6 ------ apps/openmw/mwclass/light.cpp | 6 ------ apps/openmw/mwclass/light.hpp | 5 ----- apps/openmw/mwclass/npc.cpp | 29 ++++++----------------------- apps/openmw/mwclass/npc.hpp | 6 ------ 6 files changed, 6 insertions(+), 55 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 653fabd08..e33fd322a 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -81,24 +81,15 @@ namespace MWClass ESMS::LiveCellRef *ref = ptr.get(); - const std::string &model = ref->base->model; assert (ref->base != NULL); if(!model.empty()){ physics.insertActorPhysics(ptr, "meshes\\" + model); } - } - void Creature::enable (const MWWorld::Ptr& ptr) const - { MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Creature::disable (const MWWorld::Ptr& ptr) const - { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - } - std::string Creature::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 9d9491579..237f54e82 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -22,12 +22,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - - virtual void disable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index d9af2e73f..12ae517ef 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -55,12 +55,6 @@ namespace MWClass if(!model.empty()){ physics.insertObjectPhysics(ptr, "meshes\\" + model); } - } - - void Light::enable (const MWWorld::Ptr& ptr) const - { - ESMS::LiveCellRef *ref = - ptr.get(); if (!ref->base->sound.empty()) { diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 4f21a0f8e..cd963d842 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -14,11 +14,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e7f6cc527..4c964c700 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -110,44 +110,27 @@ namespace MWClass void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - - renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); - } void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { - - ESMS::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); - std::string headID = ref->base->head; - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - + std::string headID = ref->base->head; + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; std::string smodel = "meshes\\base_anim.nif"; - if(beast) - smodel = "meshes\\base_animkna.nif"; - physics.insertActorPhysics(ptr, smodel); + if(beast) + smodel = "meshes\\base_animkna.nif"; + physics.insertActorPhysics(ptr, smodel); - - } - - void Npc::enable (const MWWorld::Ptr& ptr) const - { MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Npc::disable (const MWWorld::Ptr& ptr) const - { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - } - std::string Npc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index ef154bad4..4cb733977 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -19,12 +19,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - - virtual void disable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. From 0131c53005e01fc2e5ab6b1ed3264e5dfe8a9b74 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:28:27 +0200 Subject: [PATCH 194/289] Issue #176: removed enable/disable functions from MWWorld::Class --- apps/openmw/mwworld/class.cpp | 10 ---------- apps/openmw/mwworld/class.hpp | 10 ---------- apps/openmw/mwworld/scene.cpp | 15 +++++++++++++-- apps/openmw/mwworld/scene.hpp | 6 ++++++ apps/openmw/mwworld/world.cpp | 29 +++++++---------------------- 5 files changed, 26 insertions(+), 44 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 15bc405ce..fe39406fe 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -32,16 +32,6 @@ namespace MWWorld } - void Class::enable (const Ptr& ptr) const - { - - } - - void Class::disable (const Ptr& ptr) const - { - - } - MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index a8f2aba17..46781d516 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -68,16 +68,6 @@ namespace MWWorld virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). - virtual void enable (const Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part (default implementation: ignore) - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - - virtual void disable (const Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part (default implementation: ignore) - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - virtual std::string getName (const Ptr& ptr) const = 0; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 94f0c69a9..47238ee71 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -41,7 +41,6 @@ namespace { rendering.addObject(ptr); class_.insertObject(ptr, physics); - class_.enable (ptr); } catch (const std::exception& e) { @@ -459,8 +458,20 @@ namespace MWWorld mRendering.addObject(newPtr); MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); - MWWorld::Class::get(newPtr).enable(newPtr); } + void Scene::addObjectToScene (const Ptr& ptr) + { + mRendering.addObject (ptr); + MWWorld::Class::get (ptr).insertObject (ptr, *mPhysics); + } + + void Scene::removeObjectFromScene (const Ptr& ptr) + { + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); + mPhysics->removeObject (ptr.getRefData().getHandle()); + mRendering.removeObject (ptr); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 857ee50d1..906580ff4 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -105,6 +105,12 @@ namespace MWWorld void insertObject(MWWorld::Ptr object, Ptr::CellStore* cell); void update (float duration); + + void addObjectToScene (const Ptr& ptr); + ///< Add an object that already exists in the world model to the scene. + + void removeObjectFromScene (const Ptr& ptr); + ///< Remove an object from the scene, but not from the world model. }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6d42560d2..8f3d6c838 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -357,12 +357,8 @@ namespace MWWorld { reference.getRefData().enable(); - - //render->enable (reference.getRefData().getHandle()); - if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end()) - Class::get (reference).enable (reference); - - + if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) + mWorldScene->addObjectToScene (reference); } } @@ -372,14 +368,8 @@ namespace MWWorld { reference.getRefData().disable(); - - //render->disable (reference.getRefData().getHandle()); - if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){ - Class::get (reference).disable (reference); - MWBase::Environment::get().getSoundManager()->stopSound3D (reference); - } - - + if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) + mWorldScene->removeObjectFromScene (reference); } } @@ -553,15 +543,10 @@ namespace MWWorld { ptr.getRefData().setCount (0); - if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end() && + ptr.getRefData().isEnabled()) { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - - MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); - - mPhysics->removeObject (ptr.getRefData().getHandle()); - mRendering->removeObject(ptr); - + mWorldScene->removeObjectFromScene (ptr); mLocalScripts.remove (ptr); } } From 6fe53aa3205fa438895c76b7cab5f74e68e97f3b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:55:00 +0200 Subject: [PATCH 195/289] Issue #277: containers in cells were not filled up on cell load when the cell was preloaded before --- apps/openmw/mwworld/cells.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 8c657a5c8..b6d3e38ce 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -78,8 +78,6 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) std::map, Ptr::CellStore>::iterator result = mExteriors.find (std::make_pair (x, y)); - bool fill = false; - if (result==mExteriors.end()) { const ESM::Cell *cell = mStore.cells.searchExt (x, y); @@ -100,15 +98,13 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) result = mExteriors.insert (std::make_pair ( std::make_pair (x, y), Ptr::CellStore (cell))).first; - - fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) + { result->second.load (mStore, mReader); - - if (fill) fillContainers (result->second); + } return &result->second; } @@ -117,22 +113,18 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) { std::map::iterator result = mInteriors.find (name); - bool fill = false; - if (result==mInteriors.end()) { const ESM::Cell *cell = mStore.cells.findInt (name); result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; - - fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) + { result->second.load (mStore, mReader); - - if (fill) fillContainers (result->second); + } return &result->second; } From 750259973e13824836963753ef509fa36a76cd71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 18:00:13 +0200 Subject: [PATCH 196/289] potion creating works, most of the values are bogus --- apps/openmw/mwgui/alchemywindow.cpp | 161 ++++++++++++++++++++++- apps/openmw/mwgui/alchemywindow.hpp | 4 + apps/openmw/mwgui/messagebox.cpp | 2 +- files/mygui/openmw_layers.xml | 1 + files/mygui/openmw_messagebox_layout.xml | 2 +- 5 files changed, 163 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index bd2f05289..4fdd6588f 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,8 +1,11 @@ #include "alchemywindow.hpp" +#include + #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" +#include "../mwworld/manualref.hpp" #include "../mwworld/containerstore.hpp" #include "../mwsound/soundmanager.hpp" @@ -38,6 +41,7 @@ namespace MWGui getWidget(mApparatus3, "Apparatus3"); getWidget(mApparatus4, "Apparatus4"); getWidget(mEffectsBox, "CreatedEffects"); + getWidget(mNameEdit, "NameEdit"); mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); @@ -72,6 +76,145 @@ namespace MWGui void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) { + // check if mortar & pestle is available (always needed) + /// \todo check albemic, calcinator, retort (sometimes needed) + if (!mApparatus1->isUserString("ToolTipType")) + { + mWindowManager.messageBox("#{sNotifyMessage45}", std::vector()); + return; + } + + // make sure 2 or more ingredients were selected + int numIngreds = 0; + if (mIngredient1->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient2->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient3->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient4->isUserString("ToolTipType")) + ++numIngreds; + if (numIngreds < 2) + { + mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector()); + return; + } + + // make sure a name was entered + std::string name = mNameEdit->getCaption(); + boost::algorithm::trim(name); + if (name == "") + { + mWindowManager.messageBox("#{sNotifyMessage37}", std::vector()); + return; + } + + // if there are no created effects, the potion will always fail (but the ingredients won't be destroyed) + if (mEffects.empty()) + { + mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); + return; + } + + if (rand() % 2 == 0) /// \todo + { + ESM::Potion newPotion; + newPotion.name = mNameEdit->getCaption(); + ESM::EffectList effects; + for (unsigned int i=0; i<4; ++i) + { + if (mEffects.size() >= i+1) + { + ESM::ENAMstruct effect; + effect.effectID = mEffects[i].mEffectID; + effect.range = ESM::RT_Self; + effect.skill = mEffects[i].mSkill; + effect.attribute = mEffects[i].mAttribute; + effect.magnMin = 1; /// \todo + effect.magnMax = 10; /// \todo + effect.duration = 60; /// \todo + effects.list.push_back(effect); + } + } + + // UESP Wiki / Morrowind:Alchemy + // "The weight of a potion is an average of the weight of the ingredients, rounded down." + // note by scrawl: not rounding down here, I can't imagine a created potion to + // have 0 weight when using ingredients with 0.1 weight respectively + float weight = 0; + if (mIngredient1->isUserString("ToolTipType")) + weight += mIngredient1->getUserData()->get()->base->data.weight; + if (mIngredient2->isUserString("ToolTipType")) + weight += mIngredient2->getUserData()->get()->base->data.weight; + if (mIngredient3->isUserString("ToolTipType")) + weight += mIngredient3->getUserData()->get()->base->data.weight; + if (mIngredient4->isUserString("ToolTipType")) + weight += mIngredient4->getUserData()->get()->base->data.weight; + newPotion.data.weight = weight / float(numIngreds); + + newPotion.data.value = 100; /// \todo + newPotion.effects = effects; + // pick a random mesh and icon + std::vector names; + /// \todo is the mesh/icon dependent on alchemy skill? + names.push_back("standard"); + names.push_back("bargain"); + names.push_back("cheap"); + names.push_back("fresh"); + names.push_back("exclusive"); + names.push_back("quality"); + int random = rand() % names.size(); + newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif"; + newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds"; + std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + + // create a reference and add it to player inventory + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); + MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + ref.getPtr().getRefData().setCount(1); + store.add(ref.getPtr()); + + mWindowManager.messageBox("#{sPotionSuccess}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f); + } + else + { + // potion failed + mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); + } + + // reduce count of the ingredients + if (mIngredient1->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient1->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient1); + } + if (mIngredient2->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient2->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient2); + } + if (mIngredient3->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient3->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient3); + } + if (mIngredient4->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient4->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient4); + } + update(); } void AlchemyWindow::open() @@ -133,10 +276,7 @@ namespace MWGui void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) { - _sender->clearUserStrings(); - static_cast(_sender)->setImageTexture(""); - if (_sender->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(_sender->getChildAt(0)); + removeIngredient(_sender); drawItems(); update(); } @@ -292,7 +432,10 @@ namespace MWGui for (Widgets::SpellEffectList::iterator it2 = effects.begin(); it2 != effects.end(); ++it2) { - if (*it2 == *it) + // MW considers all "foritfy attribute" effects as the same effect. See the + // "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy + // thus, we are only checking effectID here and not attribute or skill + if (it2->mEffectID == it->mEffectID) found = true; } if (!found && i<4) @@ -316,4 +459,12 @@ namespace MWGui effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); effectsWidget->setCoord(coord); } + + void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient) + { + ingredient->clearUserStrings(); + static_cast(ingredient)->setImageTexture(""); + if (ingredient->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 17f363e92..e75597bcd 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -29,6 +29,8 @@ namespace MWGui MyGUI::Widget* mEffectsBox; + MyGUI::EditBox* mNameEdit; + Widgets::SpellEffectList mEffects; // effects of created potion void onCancelButtonClicked(MyGUI::Widget* _sender); @@ -38,6 +40,8 @@ namespace MWGui virtual void onSelectedItemImpl(MWWorld::Ptr item); virtual std::vector itemsToIgnore(); + void removeIngredient(MyGUI::Widget* ingredient); + void update(); }; } diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 9df80476e..0bb7d3c1c 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -161,7 +161,7 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin getWidget(mMessageWidget, "message"); mMessageWidget->setOverflowToTheLeft(true); - mMessageWidget->addText(cMessage); + mMessageWidget->setCaptionWithReplacing(cMessage); MyGUI::IntSize size; size.width = mFixedWidth; diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index a5044fb78..56f800ea3 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -7,6 +7,7 @@ + diff --git a/files/mygui/openmw_messagebox_layout.xml b/files/mygui/openmw_messagebox_layout.xml index c99c00a49..c5a7464ef 100644 --- a/files/mygui/openmw_messagebox_layout.xml +++ b/files/mygui/openmw_messagebox_layout.xml @@ -4,7 +4,7 @@ - + From c7010623fb419f928fb369b5e93cbcfe39c0e0c8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 18:45:17 +0200 Subject: [PATCH 197/289] Issue #294: disallowed inventory prevents Talk, Open and Take actions --- apps/openmw/mwgui/window_manager.hpp | 5 +++++ apps/openmw/mwworld/actionopen.cpp | 3 +++ apps/openmw/mwworld/actiontake.cpp | 4 ++++ apps/openmw/mwworld/actiontalk.cpp | 5 ++++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index c698047fe..f565c15fa 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -133,6 +133,11 @@ namespace MWGui updateVisible(); } + bool isAllowed(GuiWindow wnd) + { + return allowed & wnd; + } + MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;} diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e2c8ec5cf..dd36487dc 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,6 +16,9 @@ namespace MWWorld void ActionOpen::execute () { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(mContainer); } diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index 384cb3ffe..9cff42812 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -2,6 +2,7 @@ #include "actiontake.hpp" #include "../mwbase/environment.hpp" +#include "../mwgui/window_manager.hpp" #include "class.hpp" #include "world.hpp" @@ -13,6 +14,9 @@ namespace MWWorld void ActionTake::execute() { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + // insert into player's inventory MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true); diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index b33b78832..b3b631653 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -2,7 +2,7 @@ #include "actiontalk.hpp" #include "../mwbase/environment.hpp" - +#include "../mwgui/window_manager.hpp" #include "../mwdialogue/dialoguemanager.hpp" namespace MWWorld @@ -11,6 +11,9 @@ namespace MWWorld void ActionTalk::execute() { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } } From 3cba884f59488609172de97e062a175e186a6351 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 05:46:46 +0200 Subject: [PATCH 198/289] Issue #294: show/hide HUD elements based on allowed windows --- apps/openmw/mwgui/window_manager.cpp | 10 ++++++++-- apps/openmw/mwgui/window_manager.hpp | 3 --- apps/openmw/mwgui/window_pinnable_base.hpp | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 96469d105..745ef16d4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -222,6 +222,11 @@ void WindowManager::updateVisible() else mToolTips->enterGuiMode(); + setMinimapVisibility((allowed & GW_Map) && !map->pinned()); + setWeaponVisibility((allowed & GW_Inventory) && !mInventoryWindow->pinned()); + setSpellVisibility((allowed & GW_Magic)); /// \todo add pin state when spells window is implemented + setHMSVisibility((allowed & GW_Stats) && !mStatsWindow->pinned()); + // If in game mode, don't show anything. if (gameMode) return; @@ -560,12 +565,13 @@ bool WindowManager::getFullHelp() const void WindowManager::setWeaponVisibility(bool visible) { - hud->weapBox->setVisible(visible); + hud->setBottomLeftVisibility(hud->health->getVisible(), visible, hud->spellBox->getVisible()); } void WindowManager::setSpellVisibility(bool visible) { - hud->spellBox->setVisible(visible); + hud->setBottomLeftVisibility(hud->health->getVisible(), hud->weapBox->getVisible(), visible); + hud->setBottomRightVisibility(visible, hud->minimapBox->getVisible()); } void WindowManager::setMouseVisible(bool visible) diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index f565c15fa..e2fbd3e1e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -263,9 +263,6 @@ namespace MWGui the start of the game, when windows are enabled one by one through script commands. You can manipulate this through using allow() and disableAll(). - - The setting should also affect visibility of certain HUD - elements, but this is not done yet. */ GuiWindow allowed; diff --git a/apps/openmw/mwgui/window_pinnable_base.hpp b/apps/openmw/mwgui/window_pinnable_base.hpp index 8ef38c386..86bc3b85c 100644 --- a/apps/openmw/mwgui/window_pinnable_base.hpp +++ b/apps/openmw/mwgui/window_pinnable_base.hpp @@ -12,6 +12,7 @@ namespace MWGui public: WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager); void setVisible(bool b); + bool pinned() { return mPinned; } private: void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName); From 313a8e55b7cea30dd4061fc507ee8606eff534b1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 21:09:21 +0200 Subject: [PATCH 199/289] - Issue #296: Clicking on HUD elements shows/hides the respective window - Slightly redesigned the map window and minimap, the player arrow now isn't cut off at cell borders anymore --- apps/openmw/mwgui/hud.cpp | 64 ++++++------- apps/openmw/mwgui/hud.hpp | 6 +- apps/openmw/mwgui/map_window.cpp | 109 +++++++++++++++-------- apps/openmw/mwgui/map_window.hpp | 12 ++- apps/openmw/mwgui/window_manager.cpp | 6 +- apps/openmw/mwgui/window_manager.hpp | 6 ++ files/mygui/openmw_hud_layout.xml | 76 +++++----------- files/mygui/openmw_map_window_layout.xml | 42 +-------- 8 files changed, 154 insertions(+), 167 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 892bd6c7a..a3036cec4 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -48,25 +48,38 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(health, "Health"); getWidget(magicka, "Magicka"); getWidget(stamina, "Stamina"); + hmsBaseLeft = health->getLeft(); + MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame; + getWidget(healthFrame, "HealthFrame"); + getWidget(magickaFrame, "MagickaFrame"); + getWidget(fatigueFrame, "FatigueFrame"); + healthFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + // Item and spell images and status bars getWidget(weapBox, "WeapBox"); getWidget(weapImage, "WeapImage"); getWidget(weapStatus, "WeapStatus"); weapBoxBaseLeft = weapBox->getLeft(); + weapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked); getWidget(spellBox, "SpellBox"); getWidget(spellImage, "SpellImage"); getWidget(spellStatus, "SpellStatus"); spellBoxBaseLeft = spellBox->getLeft(); + spellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(effectBox, "EffectBox"); getWidget(effect1, "Effect1"); effectBoxBaseRight = effectBox->getRight(); + effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(minimapBox, "MiniMapBox"); minimapBoxBaseRight = minimapBox->getRight(); + minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); @@ -85,7 +98,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setSpellStatus(65, 100); setEffect("icons\\s\\tx_s_chameleon.dds"); - LocalMapBase::init(minimap, this); + LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); @@ -192,35 +205,6 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& v } } -void HUD::setPlayerDir(const float x, const float y) -{ - if (!minimapBox->getVisible() || (x == mLastPositionX && y == mLastPositionY)) return; - - MyGUI::ISubWidget* main = compass->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(x,y); - rotatingSubskin->setAngle(angle); - mLastPositionX = x; - mLastPositionY = y; -} - -void HUD::setPlayerPos(const float x, const float y) -{ - if (!minimapBox->getVisible() || (x == mLastDirectionX && y == mLastDirectionY)) return; - - MyGUI::IntSize size = minimap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = minimap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - - minimap->setViewOffset(pos); - compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); - - mLastDirectionX = x; - mLastDirectionY = y; -} - void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible) { int weapDx = 0, spellDx = 0; @@ -320,3 +304,23 @@ void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { MyGUI::PointerManager::getInstance().setPointer("arrow"); } + +void HUD::onHMSClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats); +} + +void HUD::onMapClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map); +} + +void HUD::onWeaponClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory); +} + +void HUD::onMagicClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 81f64ee50..924893351 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -21,8 +21,6 @@ namespace MWGui void setFPS(float fps); void setTriangleCount(size_t count); void setBatchCount(size_t count); - void setPlayerDir(const float x, const float y); - void setPlayerPos(const float x, const float y); void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); @@ -53,5 +51,9 @@ namespace MWGui void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); + void onHMSClicked(MyGUI::Widget* _sender); + void onWeaponClicked(MyGUI::Widget* _sender); + void onMagicClicked(MyGUI::Widget* _sender); + void onMapClicked(MyGUI::Widget* _sender); }; } diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index a44571d0a..a51b66e2b 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -11,6 +11,7 @@ LocalMapBase::LocalMapBase() , mInterior(false) , mFogOfWar(true) , mLocalMap(NULL) + , mMapDragAndDrop(false) , mPrefix() , mChanged(true) , mLayout(NULL) @@ -18,13 +19,41 @@ LocalMapBase::LocalMapBase() , mLastPositionY(0.0f) , mLastDirectionX(0.0f) , mLastDirectionY(0.0f) + , mCompass(NULL) { } -void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) +void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) { mLocalMap = widget; mLayout = layout; + mMapDragAndDrop = mapDragAndDrop; + mCompass = compass; + + // create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each + const int widgetSize = 512; + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + MyGUI::ImageBox* map = mLocalMap->createWidget("ImageBox", + MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my)); + + MyGUI::ImageBox* fog = map->createWidget("ImageBox", + MyGUI::IntCoord(0, 0, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my) + "_fog"); + + if (!mMapDragAndDrop) + { + map->setNeedMouseFocus(false); + fog->setNeedMouseFocus(false); + } + + mMapWidgets.push_back(map); + mFogWidgets.push_back(fog); + } + } } void LocalMapBase::setCellPrefix(const std::string& prefix) @@ -47,10 +76,10 @@ void LocalMapBase::applyFogOfWar() { std::string name = "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my); + std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" + boost::lexical_cast(mCurY + (mInterior ? (my-1) : -1*(my-1))); - MyGUI::ImageBox* fog; - mLayout->getWidget(fog, name+"_fog"); + MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx]; fog->setImageTexture(mFogOfWar ? ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" : "black.png" ) @@ -66,14 +95,13 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior) { for (int my=0; my<3; ++my) { - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" + boost::lexical_cast(y + (interior ? (my-1) : -1*(my-1))); - MyGUI::ImageBox* box; - mLayout->getWidget(box, name); + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + + MyGUI::ImageBox* box = mMapWidgets[my + 3*mx]; if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) box->setImageTexture(image); @@ -86,6 +114,42 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior) mCurY = y; mChanged = false; applyFogOfWar(); + + // set the compass texture again, because MyGUI determines sorting of ImageBox widgets + // based on the last setImageTexture call + std::string tex = "textures\\compass.dds"; + mCompass->setImageTexture(""); + mCompass->setImageTexture(tex); +} + + +void LocalMapBase::setPlayerPos(const float x, const float y) +{ + if (x == mLastPositionX && y == mLastPositionY) + return; + MyGUI::IntSize size = mLocalMap->getCanvasSize(); + MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); + MyGUI::IntCoord viewsize = mLocalMap->getCoord(); + MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); + mLocalMap->setViewOffset(pos); + + mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16)); + mLastPositionX = x; + mLastPositionY = y; +} + +void LocalMapBase::setPlayerDir(const float x, const float y) +{ + if (x == mLastDirectionX && y == mLastDirectionY) + return; + MyGUI::ISubWidget* main = mCompass->getSubWidgetMain(); + MyGUI::RotatingSkin* rotatingSubskin = main->castType(); + rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); + float angle = std::atan2(x,y); + rotatingSubskin->setAngle(angle); + + mLastDirectionX = x; + mLastDirectionY = y; } // ------------------------------------------------------------------------------------------ @@ -111,7 +175,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - LocalMapBase::init(mLocalMap, this); + LocalMapBase::init(mLocalMap, mPlayerArrow, this); } void MapWindow::setCellName(const std::string& cellName) @@ -119,33 +183,6 @@ void MapWindow::setCellName(const std::string& cellName) setTitle(cellName); } -void MapWindow::setPlayerPos(const float x, const float y) -{ - if (mGlobal || !mVisible || (x == mLastPositionX && y == mLastPositionY)) return; - MyGUI::IntSize size = mLocalMap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - mLocalMap->setViewOffset(pos); - - mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); - mLastPositionX = x; - mLastPositionY = y; -} - -void MapWindow::setPlayerDir(const float x, const float y) -{ - if (!mVisible || (x == mLastDirectionX && y == mLastDirectionY)) return; - MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(x,y); - rotatingSubskin->setAngle(angle); - - mLastDirectionX = x; - mLastDirectionY = y; -} - void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) { if (_id!=MyGUI::MouseButton::Left) return; diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp index e7318f4e4..8d3392b82 100644 --- a/apps/openmw/mwgui/map_window.hpp +++ b/apps/openmw/mwgui/map_window.hpp @@ -9,10 +9,12 @@ namespace MWGui { public: LocalMapBase(); - void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); + void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop=false); void setCellPrefix(const std::string& prefix); void setActiveCell(const int x, const int y, bool interior=false); + void setPlayerDir(const float x, const float y); + void setPlayerPos(const float x, const float y); void toggleFogOfWar(); @@ -20,14 +22,20 @@ namespace MWGui int mCurX, mCurY; bool mInterior; MyGUI::ScrollView* mLocalMap; + MyGUI::ImageBox* mCompass; std::string mPrefix; bool mChanged; bool mFogOfWar; + std::vector mMapWidgets; + std::vector mFogWidgets; + void applyFogOfWar(); OEngine::GUI::Layout* mLayout; + bool mMapDragAndDrop; + float mLastPositionX; float mLastPositionY; float mLastDirectionX; @@ -40,8 +48,6 @@ namespace MWGui MapWindow(WindowManager& parWindowManager); virtual ~MapWindow(){} - void setPlayerPos(const float x, const float y); - void setPlayerDir(const float x, const float y); void setCellName(const std::string& cellName); private: diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 745ef16d4..088e9c61e 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -271,9 +271,9 @@ void WindowManager::updateVisible() int eff = shown & allowed; // Show the windows we want - map -> setVisible( (eff & GW_Map) != 0 ); - mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); - mInventoryWindow->setVisible(true); + map -> setVisible( (eff & GW_Map) ); + mStatsWindow -> setVisible( (eff & GW_Stats) ); + mInventoryWindow->setVisible( (eff & GW_Inventory)); break; } case GM_Container: diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index e2fbd3e1e..df32547fc 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -119,6 +119,12 @@ namespace MWGui bool isGuiMode() const { return !mGuiModes.empty(); } + void toggleVisible(GuiWindow wnd) + { + shown = (shown & wnd) ? (GuiWindow) (shown & ~wnd) : (GuiWindow) (shown | wnd); + updateVisible(); + } + // Disallow all inventory mode windows void disallowAll() { diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 0aabc3e3e..26c31793c 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -29,79 +29,49 @@ - + - + + + + + + + - - + - + + + + + - - - + + + - - - - - - + + + - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - diff --git a/files/mygui/openmw_map_window_layout.xml b/files/mygui/openmw_map_window_layout.xml index e0ae5bd88..63fd03b14 100644 --- a/files/mygui/openmw_map_window_layout.xml +++ b/files/mygui/openmw_map_window_layout.xml @@ -11,46 +11,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + From 63213b36bfdf162fe9fd3edaec8a2a9716c7c672 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 23:06:15 +0200 Subject: [PATCH 200/289] Show a label on the HUD with the cell name when it changes (visible for a few seconds) - like Morrowind --- apps/openmw/mwgui/hud.cpp | 23 +++++++++++++++++++++++ apps/openmw/mwgui/hud.hpp | 8 ++++++++ apps/openmw/mwgui/window_manager.cpp | 4 ++++ files/mygui/openmw_hud_layout.xml | 8 ++++++++ 4 files changed, 43 insertions(+) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a3036cec4..d3d7696b4 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -41,6 +41,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , effectBoxBaseRight(0) , minimapBoxBaseRight(0) , mDragAndDrop(dragAndDrop) + , mCellNameTimer(0.0f) + , mCellNameBox(NULL) { setCoord(0,0, width, height); @@ -83,6 +85,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); + getWidget(mCellNameBox, "CellName"); + getWidget(crosshair, "Crosshair"); setFpsLevel(fpsLevel); @@ -324,3 +328,22 @@ void HUD::onMagicClicked(MyGUI::Widget* _sender) { MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); } + +void HUD::setCellName(const std::string& cellName) +{ + if (mCellName != cellName) + { + mCellNameTimer = 5.0f; + mCellName = cellName; + + mCellNameBox->setCaption(mCellName); + mCellNameBox->setVisible(true); + } +} + +void HUD::onFrame(float dt) +{ + mCellNameTimer -= dt; + if (mCellNameTimer < 0) + mCellNameBox->setVisible(false); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 924893351..f7131a39c 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -25,6 +25,10 @@ namespace MWGui void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); + void onFrame(float dt); + + void setCellName(const std::string& cellName); + MyGUI::ProgressPtr health, magicka, stamina; MyGUI::Widget *weapBox, *spellBox; MyGUI::ImageBox *weapImage, *spellImage; @@ -34,6 +38,7 @@ namespace MWGui MyGUI::ScrollView* minimap; MyGUI::ImageBox* compass; MyGUI::ImageBox* crosshair; + MyGUI::TextBox* mCellNameBox; MyGUI::WidgetPtr fpsbox; MyGUI::TextBox* fpscounter; @@ -48,6 +53,9 @@ namespace MWGui DragAndDrop* mDragAndDrop; + std::string mCellName; + float mCellNameTimer; + void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 088e9c61e..acd0b089f 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -470,6 +470,8 @@ void WindowManager::onFrame (float frameDuration) mInventoryWindow->onFrame(); mStatsWindow->onFrame(); + + hud->onFrame(frameDuration); } const ESMS::ESMStore& WindowManager::getStore() const @@ -494,6 +496,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) } map->setCellName( name ); + hud->setCellName( name ); map->setCellPrefix("Cell"); hud->setCellPrefix("Cell"); @@ -503,6 +506,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) else { map->setCellName( cell->cell->name ); + hud->setCellName( cell->cell->name ); map->setCellPrefix( cell->cell->name ); hud->setCellPrefix( cell->cell->name ); } diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 26c31793c..d0026bf25 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -59,6 +59,14 @@ name="Effect1"/> + + + + + + + + From a7e6a142f972ad102443f1eb0d4bff9ace4c59b6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 00:39:33 +0200 Subject: [PATCH 201/289] blend fog of war into adjacent cells --- apps/openmw/mwrender/localmap.cpp | 71 +++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index ea8902443..55cb45fdc 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -307,19 +307,19 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni // convert from world coordinates to texture UV coordinates float u,v; - std::string texName; + std::string texBaseName; if (!mInterior) { u = std::abs((pos.x - (sSize*x))/sSize); v = 1-std::abs((pos.y + (sSize*y))/sSize); - texName = "Cell_"+coordStr(x,y); + texBaseName = "Cell_"; } else { u = (pos.x - min.x - sSize*x)/sSize; v = (pos.y - min.y - sSize*y)/sSize; - texName = mInteriorName + "_" + coordStr(x,y); + texBaseName = mInteriorName + "_"; } MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v); @@ -327,30 +327,57 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni // explore radius (squared) const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; + const float exploreRadius = 0.1 * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution + const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) - // get the appropriate fog of war texture - TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); - if (!tex.isNull()) + int intExtMult = mInterior ? 1 : -1; // interior and exterior have reversed Y coordinates (interior: top to bottom) + + // change the affected fog of war textures (in a 3x3 grid around the player) + for (int mx = -1; mx<2; ++mx) { - // get its buffer - if (mBuffers.find(texName) == mBuffers.end()) return; - int i=0; - for (int texV = 0; texV> 24); - alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); - mBuffers[texName][i] = (uint32) (alpha << 24); - ++i; + // is this texture affected at all? + bool affected = false; + if (mx == 0 && my == 0) // the player is always in the center of the 3x3 grid + affected = true; + else + { + bool affectsX = (mx > 0)? (u + exploreRadiusUV > 1) : (u - exploreRadiusUV < 0); + bool affectsY = (my > 0)? (v + exploreRadiusUV > 1) : (v - exploreRadiusUV < 0); + affected = (affectsX && (my == 0)) || (affectsY && mx == 0) || (affectsX && affectsY); + } + + if (!affected) + continue; + + std::string texName = texBaseName + coordStr(x+mx,y+my*intExtMult); + + TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); + if (!tex.isNull()) + { + // get its buffer + if (mBuffers.find(texName) == mBuffers.end()) return; + int i=0; + for (int texV = 0; texV> 24); + alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); + mBuffers[texName][i] = (uint32) (alpha << 24); + + ++i; + } + } + + // copy to the texture + memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4); + tex->getBuffer()->unlock(); } } - - // copy to the texture - memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4); - tex->getBuffer()->unlock(); } } From f1d3978897b0e89f6f8f70128494c847d434d09c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 01:14:33 +0200 Subject: [PATCH 202/289] Issue #290: Auto-Close MW-reference related GUI windows --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/alchemywindow.cpp | 4 +-- apps/openmw/mwgui/alchemywindow.hpp | 2 ++ apps/openmw/mwgui/container.cpp | 27 ++++++++++-------- apps/openmw/mwgui/container.hpp | 16 +++++------ apps/openmw/mwgui/dialogue.cpp | 9 ++++-- apps/openmw/mwgui/dialogue.hpp | 7 +++-- apps/openmw/mwgui/inventorywindow.cpp | 8 +++--- apps/openmw/mwgui/inventorywindow.hpp | 2 ++ apps/openmw/mwgui/referenceinterface.cpp | 28 +++++++++++++++++++ apps/openmw/mwgui/referenceinterface.hpp | 29 ++++++++++++++++++++ apps/openmw/mwgui/tradewindow.cpp | 35 ++++++++++++++---------- apps/openmw/mwgui/tradewindow.hpp | 2 ++ apps/openmw/mwgui/window_manager.cpp | 18 ++++++++++++ apps/openmw/mwgui/window_manager.hpp | 1 + 15 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 apps/openmw/mwgui/referenceinterface.cpp create mode 100644 apps/openmw/mwgui/referenceinterface.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index ac3882714..edbeab0a1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,7 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow - confirmationdialog alchemywindow + confirmationdialog alchemywindow referenceinterface ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 4fdd6588f..50d209524 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -171,7 +171,7 @@ namespace MWGui // create a reference and add it to player inventory MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); ref.getPtr().getRefData().setCount(1); store.add(ref.getPtr()); @@ -223,7 +223,7 @@ namespace MWGui setFilter(ContainerBase::Filter_Ingredients); // pick the best available apparatus - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::Ptr bestAlbemic; MWWorld::Ptr bestMortarPestle; diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index e75597bcd..c01a18e41 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -42,6 +42,8 @@ namespace MWGui void removeIngredient(MyGUI::Widget* ingredient); + virtual void onReferenceUnavailable() { ; } + void update(); }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6aabeb2c6..1cfbc1b2b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -264,16 +264,16 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) if(mDragAndDrop->mIsOnDragAndDrop) //drop item here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + 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 (mContainer.getTypeName() == typeid(ESM::Container).name()) + if (mPtr.getTypeName() == typeid(ESM::Container).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->flags & ESM::Container::Organic) { // user notification @@ -288,13 +288,13 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) // check that we don't exceed the allowed weight (only for containers, not for inventory) if (!isInventory()) { - float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); + 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(mContainer).getEncumbrance(mContainer); + float curWeight = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); if (curWeight > capacity) { it->getRefData().setCount(0); @@ -346,7 +346,7 @@ void ContainerBase::setFilter(ContainerBase::Filter filter) void ContainerBase::openContainer(MWWorld::Ptr container) { - mContainer = container; + mPtr = container; drawItems(); } @@ -356,7 +356,7 @@ void ContainerBase::drawItems() { MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); } - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); int x = 0; int y = 0; @@ -557,7 +557,7 @@ void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) void ContainerBase::addItem(MWWorld::Ptr item, int count) { - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); int origCount = item.getRefData().getCount(); @@ -569,7 +569,7 @@ void ContainerBase::addItem(MWWorld::Ptr item, int count) void ContainerBase::transferBoughtItems() { - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) { @@ -587,7 +587,7 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) MWWorld::ContainerStore& ContainerBase::getContainerStore() { - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); return store; } @@ -651,7 +651,7 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { // transfer everything into the player's inventory - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); @@ -676,3 +676,8 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getWindowManager()->popGuiMode(); } } + +void ContainerWindow::onReferenceUnavailable() +{ + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); +} diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 26e78149a..5cd8167c2 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -2,15 +2,14 @@ #define MGUI_CONTAINER_H #include -#include "../mwclass/container.hpp" -#include -#include -#include -#include + #include "window_base.hpp" +#include "referenceinterface.hpp" + +#include "../mwclass/container.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/containerstore.hpp" -#include + namespace MWWorld { @@ -43,7 +42,7 @@ namespace MWGui int mDraggedCount; }; - class ContainerBase + class ContainerBase : public ReferenceInterface { public: ContainerBase(DragAndDrop* dragAndDrop); @@ -89,7 +88,6 @@ namespace MWGui MyGUI::Widget* mSelectedItem; DragAndDrop* mDragAndDrop; - MWWorld::Ptr mContainer; Filter mFilter; @@ -140,6 +138,8 @@ namespace MWGui void onWindowResize(MyGUI::Window* window); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); + + virtual void onReferenceUnavailable(); }; } #endif // CONTAINER_H diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 8a68ff666..ce687424c 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -125,7 +125,7 @@ void DialogueWindow::onSelectTopic(std::string topic) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? mWindowManager.pushGuiMode(GM_Barter); - mWindowManager.getTradeWindow()->startTrade(mActor); + mWindowManager.getTradeWindow()->startTrade(mPtr); } else @@ -135,7 +135,7 @@ void DialogueWindow::onSelectTopic(std::string topic) void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) { mEnabled = true; - mActor = actor; + mPtr = actor; topicsList->setEnabled(true); setTitle(npcName); @@ -260,3 +260,8 @@ void DialogueWindow::goodbye() topicsList->setEnabled(false); mEnabled = false; } + +void DialogueWindow::onReferenceUnavailable() +{ + mWindowManager.removeGuiMode(GM_Dialogue); +} diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index d3106ad38..8e9aba003 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -2,6 +2,7 @@ #define MWGUI_DIALOGE_H #include "window_base.hpp" +#include "referenceinterface.hpp" #include #include "../mwworld/ptr.hpp" @@ -25,7 +26,7 @@ namespace MWGui { class DialogueHistory; - class DialogueWindow: public WindowBase + class DialogueWindow: public WindowBase, public ReferenceInterface { public: DialogueWindow(WindowManager& parWindowManager); @@ -58,6 +59,8 @@ namespace MWGui void onMouseWheel(MyGUI::Widget* _sender, int _rel); void onWindowResize(MyGUI::Window* _sender); + virtual void onReferenceUnavailable(); + private: void updateOptions(); /** @@ -70,8 +73,6 @@ namespace MWGui bool mEnabled; - MWWorld::Ptr mActor; // actor being talked to - DialogueHistory* history; Widgets::MWList* topicsList; MyGUI::ProgressPtr pDispositionBar; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 04a30b69b..2b224ab2c 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -155,7 +155,7 @@ namespace MWGui if (mDragAndDrop->mDraggedFrom != this) { // add item to the player's inventory - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::ContainerStoreIterator it = invStore.begin(); int origCount = ptr.getRefData().getCount(); @@ -192,7 +192,7 @@ namespace MWGui std::vector InventoryWindow::getEquippedItems() { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); std::vector items; @@ -210,7 +210,7 @@ namespace MWGui void InventoryWindow::_unequipItem(MWWorld::Ptr item) { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -244,7 +244,7 @@ namespace MWGui int InventoryWindow::getPlayerGold() { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 86f7ee3c7..ecff75f10 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -48,6 +48,8 @@ namespace MWGui virtual bool isInventory() { return true; } virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); + + virtual void onReferenceUnavailable() { ; } }; } diff --git a/apps/openmw/mwgui/referenceinterface.cpp b/apps/openmw/mwgui/referenceinterface.cpp new file mode 100644 index 000000000..c6e710952 --- /dev/null +++ b/apps/openmw/mwgui/referenceinterface.cpp @@ -0,0 +1,28 @@ +#include "referenceinterface.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + +namespace MWGui +{ + ReferenceInterface::ReferenceInterface() + : mCurrentPlayerCell(NULL) + { + } + + void ReferenceInterface::checkReferenceAvailable() + { + if (mPtr.isEmpty()) + return; + + MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); + + // check if player has changed cell, or count of the reference has become 0 + if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL) + || mPtr.getRefData().getCount() == 0) + onReferenceUnavailable(); + + mCurrentPlayerCell = playerCell; + } +} diff --git a/apps/openmw/mwgui/referenceinterface.hpp b/apps/openmw/mwgui/referenceinterface.hpp new file mode 100644 index 000000000..40844b238 --- /dev/null +++ b/apps/openmw/mwgui/referenceinterface.hpp @@ -0,0 +1,29 @@ +#ifndef MWGUI_REFERENCEINTERFACE_H +#define MWGUI_REFERENCEINTERFACE_H + +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + /// \brief this class is intended for GUI interfaces that access an MW-Reference + /// for example dialogue window accesses an NPC, or Container window accesses a Container + /// these classes have to be automatically closed if the reference becomes unavailable + /// make sure that checkReferenceAvailable() is called every frame and that onReferenceUnavailable() has been overridden + class ReferenceInterface + { + public: + ReferenceInterface(); + + void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable + + protected: + virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable + + MWWorld::Ptr mPtr; + + private: + MWWorld::Ptr::CellStore* mCurrentPlayerCell; + }; +} + +#endif diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 311ea6c95..0a12a82a0 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -157,9 +157,9 @@ namespace MWGui // check if the merchant can afford this int merchantgold; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->npdt52.gold == -10) merchantgold = ref->base->npdt12.gold; else @@ -167,7 +167,7 @@ namespace MWGui } else // ESM::Creature { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); merchantgold = ref->base->data.gold; } if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) @@ -218,7 +218,7 @@ namespace MWGui // i give you back your stuff! returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore()); // now gimme back my stuff! - mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); mWindowManager.popGuiMode(); } @@ -240,9 +240,9 @@ namespace MWGui } int merchantgold; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->npdt52.gold == -10) merchantgold = ref->base->npdt12.gold; else @@ -250,7 +250,7 @@ namespace MWGui } else // ESM::Creature { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); merchantgold = ref->base->data.gold; } @@ -262,13 +262,13 @@ namespace MWGui { std::vector items; - if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { // creatures don't have equipment slots. return items; } - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -285,15 +285,15 @@ namespace MWGui bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) { int services = 0; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->hasAI) services = ref->base->AI.services; } - else if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->hasAI) services = ref->base->AI.services; } @@ -327,7 +327,7 @@ namespace MWGui std::vector TradeWindow::itemsToIgnore() { std::vector items; - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) @@ -356,4 +356,11 @@ namespace MWGui updateLabels(); } + + void TradeWindow::onReferenceUnavailable() + { + // remove both Trade and Dialogue (since you always trade with the NPC/creature that you have previously talked to) + mWindowManager.removeGuiMode(GM_Barter); + mWindowManager.removeGuiMode(GM_Dialogue); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 8da96d37e..b391fd8fa 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -69,6 +69,8 @@ namespace MWGui virtual std::vector itemsToIgnore(); void updateLabels(); + + virtual void onReferenceUnavailable(); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index acd0b089f..a6d236136 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -472,6 +472,10 @@ void WindowManager::onFrame (float frameDuration) mStatsWindow->onFrame(); hud->onFrame(frameDuration); + + mDialogueWindow->checkReferenceAvailable(); + mTradeWindow->checkReferenceAvailable(); + mContainerWindow->checkReferenceAvailable(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -626,3 +630,17 @@ void WindowManager::popGuiMode() updateVisible(); } + +void WindowManager::removeGuiMode(GuiMode mode) +{ + std::vector::iterator it = mGuiModes.begin(); + while (it != mGuiModes.end()) + { + if (*it == mode) + it = mGuiModes.erase(it); + else + ++it; + } + + updateVisible(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index df32547fc..7082cc0bc 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -109,6 +109,7 @@ namespace MWGui void pushGuiMode(GuiMode mode); void popGuiMode(); + void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack GuiMode getMode() const { From 10cfe0f5bc37d08356dccb3a4d08589facda131e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 06:39:10 +0200 Subject: [PATCH 203/289] Issue #295: Class creation dialogs tooltips; plus tons of other improvements --- apps/openmw/mwgui/class.cpp | 129 +++++++++++-- apps/openmw/mwgui/class.hpp | 8 + apps/openmw/mwgui/race.cpp | 15 +- apps/openmw/mwgui/review.cpp | 52 ++++- apps/openmw/mwgui/review.hpp | 2 + apps/openmw/mwgui/stats_window.cpp | 79 +------- apps/openmw/mwgui/tooltips.cpp | 181 ++++++++++++++++++ apps/openmw/mwgui/tooltips.hpp | 9 + apps/openmw/mwgui/widgets.cpp | 4 +- components/esm/attr.cpp | 11 ++ components/esm/attr.hpp | 1 + files/mygui/openmw_chargen_class_layout.xml | 16 +- .../openmw_chargen_create_class_layout.xml | 14 +- ...w_chargen_generate_class_result_layout.xml | 4 +- files/mygui/openmw_chargen_race_layout.xml | 8 +- files/mygui/openmw_chargen_review_layout.xml | 75 +++++++- ...w_chargen_select_specialization_layout.xml | 6 +- files/mygui/openmw_infobox_layout.xml | 2 +- files/mygui/openmw_resources.xml | 29 +++ files/mygui/openmw_text.skin.xml | 41 ++-- files/mygui/openmw_tooltips.xml | 25 +++ 21 files changed, 565 insertions(+), 146 deletions(-) diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 3e41fa6b1..d3d261ab0 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -1,6 +1,4 @@ #include "class.hpp" -#include "window_manager.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -8,6 +6,11 @@ #include #include +#include + +#include "window_manager.hpp" +#include "tooltips.hpp" + #undef min #undef max @@ -79,17 +82,13 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager) // Centre dialog center(); - setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(favoriteAttribute[0], "FavoriteAttribute0"); getWidget(favoriteAttribute[1], "FavoriteAttribute1"); favoriteAttribute[0]->setWindowManager(&mWindowManager); favoriteAttribute[1]->setWindowManager(&mWindowManager); - setText("MajorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu3", "Major Skills:")); - setText("MinorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu4", "Minor Skills:")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -231,15 +230,21 @@ void PickClassDialog::updateStats() "sSpecializationMagic", "sSpecializationStealth" }; - specializationName->setCaption(mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization])); + std::string specName = mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specialization); favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]); favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]); + ToolTips::createAttributeToolTip(favoriteAttribute[0], favoriteAttribute[0]->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute[1], favoriteAttribute[1]->getAttributeId()); for (int i = 0; i < 5; ++i) { majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); + ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][0]); + ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][1]); } classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); @@ -387,7 +392,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); @@ -451,6 +455,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) minorSkill[2]->setSkillId(ESM::Skill::Spear); minorSkill[3]->setSkillId(ESM::Skill::Athletics); minorSkill[4]->setSkillId(ESM::Skill::Enchant); + + setSpecialization(0); + update(); } CreateClassDialog::~CreateClassDialog() @@ -461,6 +468,18 @@ CreateClassDialog::~CreateClassDialog() delete descDialog; } +void CreateClassDialog::update() +{ + for (int i = 0; i < 5; ++i) + { + ToolTips::createSkillToolTip(majorSkill[i], majorSkill[i]->getSkillId()); + ToolTips::createSkillToolTip(minorSkill[i], minorSkill[i]->getSkillId()); + } + + ToolTips::createAttributeToolTip(favoriteAttribute0, favoriteAttribute0->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute1, favoriteAttribute1->getAttributeId()); +} + std::string CreateClassDialog::getName() const { return editName->getOnlyText(); @@ -539,14 +558,25 @@ void CreateClassDialog::open() void CreateClassDialog::onDialogCancel() { if (specDialog) - specDialog->setVisible(false); + { + mWindowManager.removeDialog(specDialog); + specDialog = 0; + } if (attribDialog) - attribDialog->setVisible(false); + { + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + } if (skillDialog) - skillDialog->setVisible(false); + { + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + } if (descDialog) - descDialog->setVisible(false); - // TODO: Delete dialogs here + { + mWindowManager.removeDialog(descDialog); + descDialog = 0; + } } void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) @@ -562,8 +592,23 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) void CreateClassDialog::onSpecializationSelected() { specializationId = specDialog->getSpecializationId(); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); - specDialog->setVisible(false); + setSpecialization(specializationId); + + mWindowManager.removeDialog(specDialog); + specDialog = 0; +} + +void CreateClassDialog::setSpecialization(int id) +{ + specializationId = (ESM::Class::Specialization) id; + static const char *specIds[3] = { + "sSpecializationCombat", + "sSpecializationMagic", + "sSpecializationStealth" + }; + std::string specName = mWindowManager.getGameSettingString(specIds[specializationId], specIds[specializationId]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specializationId); } void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) @@ -592,7 +637,10 @@ void CreateClassDialog::onAttributeSelected() favoriteAttribute0->setAttributeId(favoriteAttribute1->getAttributeId()); } attribute->setAttributeId(id); - attribDialog->setVisible(false); + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + + update(); } void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) @@ -625,7 +673,9 @@ void CreateClassDialog::onSkillSelected() } skill->setSkillId(skillDialog->getSkillId()); - skillDialog->setVisible(false); + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + update(); } void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) @@ -640,6 +690,7 @@ void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) { description = descDialog->getTextInput(); mWindowManager.removeDialog(descDialog); + descDialog = 0; } void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) @@ -665,20 +716,35 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM getWidget(specialization0, "Specialization0"); getWidget(specialization1, "Specialization1"); getWidget(specialization2, "Specialization2"); - specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); + std::string combat = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""); + std::string magic = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], ""); + std::string stealth = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], ""); + + specialization0->setCaption(combat); specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); + specialization1->setCaption(magic); specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); + specialization2->setCaption(stealth); specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specializationId = ESM::Class::Combat; + ToolTips::createSpecializationToolTip(specialization0, combat, ESM::Class::Combat); + ToolTips::createSpecializationToolTip(specialization1, magic, ESM::Class::Magic); + ToolTips::createSpecializationToolTip(specialization2, stealth, ESM::Class::Stealth); + MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSpecializationDialog::~SelectSpecializationDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -721,6 +787,7 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) attribute->setWindowManager(&parWindowManager); attribute->setAttributeId(ESM::Attribute::attributeIds[i]); attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); + ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId()); } MyGUI::ButtonPtr cancelButton; @@ -729,6 +796,13 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectAttributeDialog::~SelectAttributeDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -810,6 +884,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) skills[spec][i].widget->setWindowManager(&mWindowManager); skills[spec][i].widget->setSkillId(skills[spec][i].skillId); skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); + ToolTips::createSkillToolTip(skills[spec][i].widget, skills[spec][i].widget->getSkillId()); } } @@ -819,6 +894,13 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSkillDialog::~SelectSkillDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -853,6 +935,13 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +DescriptionDialog::~DescriptionDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 6f0138aa4..868052800 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -139,6 +139,7 @@ namespace MWGui { public: SelectSpecializationDialog(WindowManager& parWindowManager); + ~SelectSpecializationDialog(); ESM::Class::Specialization getSpecializationId() const { return specializationId; } @@ -169,6 +170,7 @@ namespace MWGui { public: SelectAttributeDialog(WindowManager& parWindowManager); + ~SelectAttributeDialog(); ESM::Attribute::AttributeID getAttributeId() const { return attributeId; } Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; } @@ -201,6 +203,7 @@ namespace MWGui { public: SelectSkillDialog(WindowManager& parWindowManager); + ~SelectSkillDialog(); ESM::Skill::SkillEnum getSkillId() const { return skillId; } Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; } @@ -236,6 +239,7 @@ namespace MWGui { public: DescriptionDialog(WindowManager& parWindowManager); + ~DescriptionDialog(); std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } @@ -285,6 +289,10 @@ namespace MWGui void onDescriptionEntered(WindowBase* parWindow); void onDialogCancel(); + void setSpecialization(int id); + + void update(); + private: MyGUI::EditPtr editName; MyGUI::TextBox* specializationName; diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index f18bdb41f..dea365ac2 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -1,7 +1,4 @@ #include "race.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -10,6 +7,12 @@ #include #include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" + using namespace MWGui; using namespace Widgets; @@ -51,7 +54,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager) prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); - setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair")); + setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu4", "Change Hair")); getWidget(prevButton, "PrevHairButton"); getWidget(nextButton, "NextHairButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); @@ -255,6 +258,8 @@ void RaceDialog::updateSkills() skillWidget->setWindowManager(&mWindowManager); skillWidget->setSkillNumber(skillId); skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus)); + ToolTips::createSkillToolTip(skillWidget, skillId); + skillItems.push_back(skillWidget); @@ -288,6 +293,8 @@ void RaceDialog::updateSpellPowers() spellPowerWidget = spellPowerList->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast(i)); spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setSpellId(spellpower); + spellPowerWidget->setUserString("ToolTipType", "Spell"); + spellPowerWidget->setUserString("Spell", spellpower); spellPowerItems.push_back(spellPowerWidget); diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 5059efb34..be537e854 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -1,12 +1,15 @@ #include "review.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" + +#include #include #include -#include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" #undef min #undef max @@ -74,7 +77,7 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) getWidget(skillAreaWidget, "Skills"); getWidget(skillClientWidget, "SkillClient"); getWidget(skillScrollerWidget, "SkillScroller"); - + skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition); updateScroller(); @@ -137,13 +140,17 @@ void ReviewDialog::setRace(const std::string &raceId_) raceId = raceId_; const ESM::Race *race = mWindowManager.getStore().races.search(raceId); if (race) + { + ToolTips::createRaceToolTip(raceWidget, race); raceWidget->setCaption(race->name); + } } void ReviewDialog::setClass(const ESM::Class& class_) { klass = class_; classWidget->setCaption(klass.name); + ToolTips::createClassToolTip(classWidget, klass); } void ReviewDialog::setBirthSign(const std::string& signId) @@ -151,22 +158,31 @@ void ReviewDialog::setBirthSign(const std::string& signId) birthSignId = signId; const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId); if (sign) + { birthSignWidget->setCaption(sign->name); + ToolTips::createBirthsignToolTip(birthSignWidget, birthSignId); + } } void ReviewDialog::setHealth(const MWMechanics::DynamicStat& value) { health->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + health->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } void ReviewDialog::setMagicka(const MWMechanics::DynamicStat& value) { magicka->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + magicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } void ReviewDialog::setFatigue(const MWMechanics::DynamicStat& value) { fatigue->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + fatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat& value) @@ -219,6 +235,8 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::ImageBox* separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); + separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); + skillWidgets.push_back(separator); coord1.top += separator->getHeight(); @@ -228,6 +246,7 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2 void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* groupWidget = skillClientWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); + groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); groupWidget->setCaption(label); skillWidgets.push_back(groupWidget); @@ -242,10 +261,12 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); + skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -262,6 +283,7 @@ void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGU skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); @@ -297,6 +319,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId else if (modified < base) state = "decreased"; MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + + for (int i=0; i<2; ++i) + { + ToolTips::createSkillToolTip(skillWidgets[skillWidgets.size()-1-i], skillId); + } + skillWidgetMap[skillId] = widget; } } @@ -330,6 +358,8 @@ void ReviewDialog::updateScroller() { skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); + if (clientHeight != 0) + skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() ); } // widget controls @@ -363,3 +393,15 @@ void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender) { eventActivateDialog(BIRTHSIGN_DIALOG); } + +void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (skillScrollerWidget->getScrollPosition() - _rel*0.3 < 0) + skillScrollerWidget->setScrollPosition(0); + else if (skillScrollerWidget->getScrollPosition() - _rel*0.3 > skillScrollerWidget->getScrollRange()-1) + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollRange()-1); + else + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollPosition() - _rel*0.3); + + onScrollChangePosition(skillScrollerWidget, skillScrollerWidget->getScrollPosition()); +} diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 76ca5a2d7..bae4dc459 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -68,6 +68,8 @@ namespace MWGui void onClassClicked(MyGUI::Widget* _sender); void onBirthSignClicked(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 54d9d7d4e..061800bf0 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -12,6 +12,7 @@ #include "../mwbase/environment.hpp" #include "window_manager.hpp" +#include "tooltips.hpp" using namespace MWGui; @@ -442,32 +443,17 @@ void StatsWindow::updateSkillArea() const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); MyGUI::Widget* raceWidget; getWidget(raceWidget, "RaceText"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); getWidget(raceWidget, "Race_str"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); // class tooltip MyGUI::Widget* classWidget; const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); - int spec = playerClass.data.specialization; - std::string specStr; - if (spec == 0) - specStr = "#{sSpecializationCombat}"; - else if (spec == 1) - specStr = "#{sSpecializationMagic}"; - else if (spec == 2) - specStr = "#{sSpecializationStealth}"; - getWidget(classWidget, "ClassText"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); getWidget(classWidget, "Class_str"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); if (!mFactions.empty()) { @@ -534,61 +520,8 @@ void StatsWindow::updateSkillArea() addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); MyGUI::Widget* w = addItem(sign->name, coord1, coord2); - w->setUserString("ToolTipType", "Layout"); - w->setUserString("ToolTipLayout", "BirthSignToolTip"); - std::string image = sign->texture; - image.replace(image.size()-3, 3, "dds"); - w->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); - std::string text; - text += sign->name; - text += "\n#BF9959" + sign->description; - - std::vector abilities, powers, spells; - - std::vector::const_iterator it = sign->powers.list.begin(); - std::vector::const_iterator end = sign->powers.list.end(); - for (; it != end; ++it) - { - const std::string &spellId = *it; - const ESM::Spell *spell = store.spells.search(spellId); - if (!spell) - continue; // Skip spells which cannot be found - ESM::Spell::SpellType type = static_cast(spell->data.type); - if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) - continue; // We only want spell, ability and powers. - - if (type == ESM::Spell::ST_Ability) - abilities.push_back(spellId); - else if (type == ESM::Spell::ST_Power) - powers.push_back(spellId); - else if (type == ESM::Spell::ST_Spell) - spells.push_back(spellId); - } - - struct{ const std::vector &spells; std::string label; } categories[3] = { - {abilities, "sBirthsignmenu1"}, - {powers, "sPowers"}, - {spells, "sBirthsignmenu2"} - }; - - for (int category = 0; category < 3; ++category) - { - for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) - { - if (it == categories[category].spells.begin()) - { - text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; - } - - const std::string &spellId = *it; - - const ESM::Spell *spell = store.spells.search(spellId); - text += "\n#BF9959" + spell->name; - } - } - - w->setUserString("Caption_BirthSignText", text); + ToolTips::createBirthsignToolTip(w, birthSignId); } // Add a line separator if there are items above diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index e21c88646..c6d8e2c8c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -65,6 +65,17 @@ void ToolTips::onFrame(float frameDuration) IntSize tooltipSize; + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) + { + focus = focus->getParent(); + if (!focus) + return; + ++i; + } + std::string type = focus->getUserString("ToolTipType"); std::string text = focus->getUserString("ToolTipText"); @@ -78,6 +89,29 @@ void ToolTips::onFrame(float frameDuration) mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } else if (type == "Layout") { // tooltip defined in the layout @@ -440,3 +474,150 @@ void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, mFocusToolTipX = (min_x + max_x) / 2; mFocusToolTipY = min_y; } + +void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId) +{ + if (skillId == -1) + return; + + const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); + assert(skill); + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->data.attribute); + assert(attr); + std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("Caption_SkillNoProgressName", "#{"+skillNameId+"}"); + widget->setUserString("Caption_SkillNoProgressDescription", skill->description); + widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); + widget->setUserString("ImageTexture_SkillNoProgressImage", icon); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); +} + +void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId) +{ + if (attributeId == -1) + return; + + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(attributeId); + assert(attr); + std::string icon = ESM::Attribute::attributeIcons[attributeId]; + std::string name = ESM::Attribute::gmstAttributeIds[attributeId]; + std::string desc = ESM::Attribute::gmstAttributeDescIds[attributeId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", "#{"+name+"}"); + widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}"); + widget->setUserString("ImageTexture_AttributeImage", icon); +} + +void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId) +{ + widget->setUserString("Caption_CenteredCaption", name); + std::string specText; + // get all skills of this specialisation + std::map skills = MWBase::Environment::get().getWorld()->getStore().skills.list; + for (std::map::const_iterator it = skills.begin(); + it != skills.end(); ++it) + { + if (it->second.data.specialization == specId) + specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->second.index] + "}"; + } + widget->setUserString("Caption_CenteredCaptionText", specText); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); + widget->setUserString("ToolTipType", "Layout"); +} + +void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId) +{ + const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find(birthsignId); + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "BirthSignToolTip"); + std::string image = sign->texture; + image.replace(image.size()-3, 3, "dds"); + widget->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); + std::string text; + + text += sign->name; + text += "\n#BF9959" + sign->description; + + std::vector abilities, powers, spells; + + std::vector::const_iterator it = sign->powers.list.begin(); + std::vector::const_iterator end = sign->powers.list.end(); + for (; it != end; ++it) + { + const std::string &spellId = *it; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + if (!spell) + continue; // Skip spells which cannot be found + ESM::Spell::SpellType type = static_cast(spell->data.type); + if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) + continue; // We only want spell, ability and powers. + + if (type == ESM::Spell::ST_Ability) + abilities.push_back(spellId); + else if (type == ESM::Spell::ST_Power) + powers.push_back(spellId); + else if (type == ESM::Spell::ST_Spell) + spells.push_back(spellId); + } + + struct{ const std::vector &spells; std::string label; } categories[3] = { + {abilities, "sBirthsignmenu1"}, + {powers, "sPowers"}, + {spells, "sBirthsignmenu2"} + }; + + for (int category = 0; category < 3; ++category) + { + for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) + { + if (it == categories[category].spells.begin()) + { + text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; + } + + const std::string &spellId = *it; + + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + text += "\n#BF9959" + spell->name; + } + } + + widget->setUserString("Caption_BirthSignText", text); +} + +void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace) +{ + widget->setUserString("Caption_CenteredCaption", playerRace->name); + widget->setUserString("Caption_CenteredCaptionText", playerRace->description); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); +} + +void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass) +{ + if (playerClass.name == "") + return; + + int spec = playerClass.data.specialization; + std::string specStr; + if (spec == 0) + specStr = "#{sSpecializationCombat}"; + else if (spec == 1) + specStr = "#{sSpecializationMagic}"; + else if (spec == 2) + specStr = "#{sSpecializationStealth}"; + + widget->setUserString("Caption_ClassName", playerClass.name); + widget->setUserString("Caption_ClassDescription", playerClass.description); + widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "ClassToolTip"); +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 6d4a205d1..1925a4f14 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -57,6 +57,15 @@ namespace MWGui static std::string getCountString(const int value); ///< @return blank string if count is 1, or else " (value)" + // these do not create an actual tooltip, but they fill in the data that is required so the tooltip + // system knows what to show in case this widget is hovered + static void createSkillToolTip(MyGUI::Widget* widget, int skillId); + static void createAttributeToolTip(MyGUI::Widget* widget, int attributeId); + static void createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId); + static void createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId); + static void createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace); + static void createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass); + private: MyGUI::Widget* mDynamicToolTipBox; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 2fd40b7c2..b85074805 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -301,8 +301,8 @@ void MWEffectList::createEffectWidgets(std::vector &effects, M { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - it->mIsConstant = (flags & EF_Constant); - it->mNoTarget = (flags & EF_NoTarget); + it->mIsConstant = (flags & EF_Constant) || it->mIsConstant; + it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget; effect->setSpellEffect(*it); effects.push_back(effect); if (effect->getRequestedWidth() > maxwidth) diff --git a/components/esm/attr.cpp b/components/esm/attr.cpp index 8c410e57a..b077ef499 100644 --- a/components/esm/attr.cpp +++ b/components/esm/attr.cpp @@ -34,3 +34,14 @@ const std::string Attribute::gmstAttributeDescIds[Attribute::Length] = { "sPerDesc", "sLucDesc" }; + +const std::string Attribute::attributeIcons[Attribute::Length] = { + "icons\\k\\attribute_strength.dds", + "icons\\k\\attribute_int.dds", + "icons\\k\\attribute_wilpower.dds", + "icons\\k\\attribute_agility.dds", + "icons\\k\\attribute_speed.dds", + "icons\\k\\attribute_endurance.dds", + "icons\\k\\attribute_personality.dds", + "icons\\k\\attribute_luck.dds" +}; diff --git a/components/esm/attr.hpp b/components/esm/attr.hpp index 183fb9e0e..620683dbb 100644 --- a/components/esm/attr.hpp +++ b/components/esm/attr.hpp @@ -30,6 +30,7 @@ struct Attribute static const AttributeID attributeIds[Length]; static const std::string gmstAttributeIds[Length]; static const std::string gmstAttributeDescIds[Length]; + static const std::string attributeIcons[Length]; Attribute(AttributeID id, const std::string &name, const std::string &description) : id(id) diff --git a/files/mygui/openmw_chargen_class_layout.xml b/files/mygui/openmw_chargen_class_layout.xml index 38fa606ab..613143d54 100644 --- a/files/mygui/openmw_chargen_class_layout.xml +++ b/files/mygui/openmw_chargen_class_layout.xml @@ -14,8 +14,11 @@ - + + + + @@ -23,16 +26,19 @@ - + + + + - + @@ -42,7 +48,7 @@ - + @@ -58,7 +64,7 @@ - + diff --git a/files/mygui/openmw_chargen_create_class_layout.xml b/files/mygui/openmw_chargen_create_class_layout.xml index be6a10e0c..dde74a6a2 100644 --- a/files/mygui/openmw_chargen_create_class_layout.xml +++ b/files/mygui/openmw_chargen_create_class_layout.xml @@ -12,17 +12,23 @@ - + + + + - + - + + + + @@ -59,7 +65,7 @@ - + diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml index 9a6ed4f2e..1cef9c9ce 100644 --- a/files/mygui/openmw_chargen_generate_class_result_layout.xml +++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml @@ -9,10 +9,10 @@ - + @@ -24,7 +24,7 @@ - + diff --git a/files/mygui/openmw_chargen_race_layout.xml b/files/mygui/openmw_chargen_race_layout.xml index a9b072f5e..df0d29f78 100644 --- a/files/mygui/openmw_chargen_race_layout.xml +++ b/files/mygui/openmw_chargen_race_layout.xml @@ -17,27 +17,23 @@ - - - - @@ -45,15 +41,13 @@ - - + - diff --git a/files/mygui/openmw_chargen_review_layout.xml b/files/mygui/openmw_chargen_review_layout.xml index 57bb3b124..2071cac88 100644 --- a/files/mygui/openmw_chargen_review_layout.xml +++ b/files/mygui/openmw_chargen_review_layout.xml @@ -26,26 +26,83 @@ + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -59,7 +116,7 @@ - + diff --git a/files/mygui/openmw_chargen_select_specialization_layout.xml b/files/mygui/openmw_chargen_select_specialization_layout.xml index 53980b133..1b5295bc9 100644 --- a/files/mygui/openmw_chargen_select_specialization_layout.xml +++ b/files/mygui/openmw_chargen_select_specialization_layout.xml @@ -11,13 +11,13 @@ - + - + - + diff --git a/files/mygui/openmw_infobox_layout.xml b/files/mygui/openmw_infobox_layout.xml index de1030830..89031a616 100644 --- a/files/mygui/openmw_infobox_layout.xml +++ b/files/mygui/openmw_infobox_layout.xml @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index e96aeb918..f1a8b0dfc 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -139,4 +139,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 6b62f618d..bfa970de5 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -65,26 +65,45 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 262fd2020..148e98064 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -134,6 +134,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From f6a6684685d033554f01fb1a0187f77be5c6eee3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 21:39:18 +0200 Subject: [PATCH 204/289] when the resolution changes, adjust camera aspect ratio and recreate compositors --- apps/openmw/mwrender/compositors.cpp | 15 +++++++++++ apps/openmw/mwrender/compositors.hpp | 5 ++++ apps/openmw/mwrender/renderingmanager.cpp | 32 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 10 ++++++- apps/openmw/mwrender/sky.cpp | 7 +++-- apps/openmw/mwrender/sky.hpp | 2 +- apps/openmw/mwrender/water.cpp | 9 +++++-- apps/openmw/mwrender/water.hpp | 3 ++- libs/openengine/ogre/renderer.cpp | 15 +++++++++++ libs/openengine/ogre/renderer.hpp | 5 ++++ 10 files changed, 94 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index 4c9f08b72..d786c263b 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -26,6 +26,21 @@ void Compositors::setEnabled (const bool enabled) mEnabled = enabled; } +void Compositors::recreate() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + + CompositorMap temp = mCompositors; + mCompositors.clear(); + + for (CompositorMap::iterator it=temp.begin(); + it != temp.end(); ++it) + { + addCompositor(it->first, it->second.second); + setCompositorEnabled(it->first, mEnabled && it->second.first); + } +} + void Compositors::addCompositor (const std::string& name, const int priority) { int id = 0; diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index 50b53f84a..f249ece42 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -25,6 +25,11 @@ namespace MWRender */ void setEnabled (const bool enabled); + void setViewport(Ogre::Viewport* vp) { mViewport = vp; } + + /// recreate compositors (call this after viewport size changes) + void recreate(); + bool toggle() { setEnabled(!mEnabled); return mEnabled; } /** diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 86c1f752c..e5ce6b0dd 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -11,6 +11,7 @@ #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwworld/ptr.hpp" +#include "../mwworld/player.hpp" #include "../mwbase/environment.hpp" #include #include @@ -30,6 +31,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) { mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); + mRendering.setWindowEventListener(this); mCompositors = new Compositors(mRendering.getViewport()); @@ -567,6 +569,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { + bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) { @@ -574,6 +577,24 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec { setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } + else if (it->second == "max viewing distance" && it->first == "Viewing distance") + { + if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior()) + configureFog(*MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()); + } + else if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y" + || it->second == "fullscreen")) + changeRes = true; + } + + if (changeRes) + { + int x = Settings::Manager::getInt("resolution x", "Video"); + int y = Settings::Manager::getInt("resolution y", "Video"); + mRendering.getWindow()->resize(x, y); + mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } } @@ -587,4 +608,15 @@ void RenderingManager::setMenuTransparency(float val) tex->getBuffer()->unlock(); } +void RenderingManager::windowResized(Ogre::RenderWindow* rw) +{ + mCompositors->setViewport(mRendering.recreateViewport()); + mCompositors->recreate(); + mWater->assignTextures(); +} + +void RenderingManager::windowClosed(Ogre::RenderWindow* rw) +{ +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index edee193f3..562184c62 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -8,6 +8,8 @@ #include "../mwworld/class.hpp" +#include + #include #include #include @@ -51,7 +53,7 @@ namespace MWRender class Water; class Compositors; -class RenderingManager: private RenderingInterface { +class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { private: @@ -161,6 +163,12 @@ class RenderingManager: private RenderingInterface { void processChangedSettings(const Settings::CategorySettingVector& settings); + Ogre::Viewport* getViewport() { return mRendering.getViewport(); } + + protected: + virtual void windowResized(Ogre::RenderWindow* rw); + virtual void windowClosed(Ogre::RenderWindow* rw); + private: void setAmbientMode(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 72f88c6c5..19e45c189 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -374,7 +374,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mSunGlare(NULL) , mMasser(NULL) , mSecunda(NULL) - , mViewport(NULL) + , mCamera(pCamera) , mRootNode(NULL) , mSceneMgr(NULL) , mAtmosphereDay(NULL) @@ -399,9 +399,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mSecundaEnabled(true) , mCreated(false) { - mViewport = pCamera->getViewport(); mSceneMgr = pMwRoot->getCreator(); - mRootNode = pCamera->getParentSceneNode()->createChildSceneNode(); + mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates mRootNode->setInheritOrientation(false); } @@ -741,7 +740,7 @@ void SkyManager::update(float duration) // on how directly the player is looking at the sun Vector3 sun = mSunGlare->getPosition(); sun = Vector3(sun.x, sun.z, -sun.y); - Vector3 cam = mViewport->getCamera()->getRealDirection(); + Vector3 cam = mCamera->getRealDirection(); const Degree angle = sun.angleBetween( cam ); float val = 1- (angle.valueDegrees() / 180.f); val = (val*val*val*val)*2; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index da89d0eb0..e11745e82 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -185,7 +185,7 @@ namespace MWRender Moon* mMasser; Moon* mSecunda; - Ogre::Viewport* mViewport; + Ogre::Camera* mCamera; Ogre::SceneNode* mRootNode; Ogre::SceneManager* mSceneMgr; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index dda215999..981343e91 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -10,7 +10,7 @@ namespace MWRender { Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : - mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), + mCamera (camera), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), mReflectionRenderActive(false), mRendering(rend) @@ -80,6 +80,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mSceneManager->addRenderQueueListener(this); + assignTextures(); + // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- @@ -262,10 +264,13 @@ void Water::createMaterial() // use technique without shaders if reflection is disabled if (mReflectionTarget == 0) mMaterial->removeTechnique(0); +} +void Water::assignTextures() +{ if (Settings::Manager::getBool("shader", "Water")) { - CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer"); + CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 25631b4af..edd217e84 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -17,7 +17,6 @@ namespace MWRender { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; Ogre::SceneManager *mSceneManager; - Ogre::Viewport *mViewport; Ogre::Plane mWaterPlane; Ogre::SceneNode *mWaterNode; @@ -65,6 +64,8 @@ namespace MWRender { void toggle(); void update(); + void assignTextures(); + void setViewportBackground(const Ogre::ColourValue& bg); void checkUnderwater(float y); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index ab7920ab8..579ba3dd7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -144,3 +144,18 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC mFader = new Fader(); } + +Ogre::Viewport* OgreRenderer::recreateViewport() +{ + mWindow->removeViewport(mView->getZOrder()); + mView = mWindow->addViewport(mCamera); + + // Alter the camera aspect ratio to match the viewport + mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); + return mView; +} + +void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) +{ + Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); +} diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 50fe64015..7a0fd11df 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -25,6 +25,7 @@ #endif #include "OgreTexture.h" +#include namespace Ogre { @@ -104,6 +105,8 @@ namespace OEngine ~OgreRenderer() { cleanup(); } + void setWindowEventListener(Ogre::WindowEventListener* listener); + /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ void configure( @@ -153,6 +156,8 @@ namespace OEngine /// Viewport Ogre::Viewport *getViewport() { return mView; } + + Ogre::Viewport* recreateViewport(); }; } } From 8f667580bb855ae04857eda9c228888956527d87 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 23:12:45 +0200 Subject: [PATCH 205/289] ogre 1.8 final release compability fixes --- apps/openmw/mwrender/terrain.cpp | 20 ++++++++++---------- apps/openmw/mwrender/terrain.hpp | 2 +- files/gbuffer/gbuffer.compositor | 17 ++++------------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 56eff4a9a..90345cf30 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -22,30 +22,30 @@ namespace MWRender TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) : mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) { - + mTerrainGlobals = OGRE_NEW TerrainGlobalOptions(); TerrainMaterialGeneratorPtr matGen; TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); matGen.bind(matGenP); - mTerrainGlobals.setDefaultMaterialGenerator(matGen); + mTerrainGlobals->setDefaultMaterialGenerator(matGen); TerrainMaterialGenerator::Profile* const activeProfile = - mTerrainGlobals.getDefaultMaterialGenerator() + mTerrainGlobals->getDefaultMaterialGenerator() ->getActiveProfile(); mActiveProfile = static_cast(activeProfile); //The pixel error should be as high as possible without it being noticed //as it governs how fast mesh quality decreases. - mTerrainGlobals.setMaxPixelError(8); + mTerrainGlobals->setMaxPixelError(8); - mTerrainGlobals.setLayerBlendMapSize(32); - mTerrainGlobals.setDefaultGlobalColourMapSize(65); + mTerrainGlobals->setLayerBlendMapSize(32); + mTerrainGlobals->setDefaultGlobalColourMapSize(65); //10 (default) didn't seem to be quite enough - mTerrainGlobals.setSkirtSize(128); + mTerrainGlobals->setSkirtSize(128); //due to the sudden flick between composite and non composite textures, //this seemed the distance where it wasn't too noticeable - mTerrainGlobals.setCompositeMapDistance(mWorldSize*2); + mTerrainGlobals->setCompositeMapDistance(mWorldSize*2); mActiveProfile->setLightmapEnabled(false); mActiveProfile->setLayerSpecularMappingEnabled(false); @@ -92,14 +92,14 @@ namespace MWRender void TerrainManager::setDiffuse(const ColourValue& diffuse) { - mTerrainGlobals.setCompositeMapDiffuse(diffuse); + mTerrainGlobals->setCompositeMapDiffuse(diffuse); } //---------------------------------------------------------------------------------------------- void TerrainManager::setAmbient(const ColourValue& ambient) { - mTerrainGlobals.setCompositeMapAmbient(ambient); + mTerrainGlobals->setCompositeMapAmbient(ambient); } //---------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index c4ff053a6..273ede084 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -33,7 +33,7 @@ namespace MWRender{ void cellAdded(MWWorld::Ptr::CellStore* store); void cellRemoved(MWWorld::Ptr::CellStore* store); private: - Ogre::TerrainGlobalOptions mTerrainGlobals; + Ogre::TerrainGlobalOptions* mTerrainGlobals; Ogre::TerrainGroup mTerrainGroup; RenderingManager* mRendering; diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor index 316003af6..6ca35df87 100644 --- a/files/gbuffer/gbuffer.compositor +++ b/files/gbuffer/gbuffer.compositor @@ -11,11 +11,8 @@ compositor gbuffer input none pass clear { - clear - { - // make sure to set this to the viewport background color from outside - colour_value 0 0 0 1 - } + // make sure to set this to the viewport background color from outside + colour_value 0 0 0 1 } pass render_scene { @@ -59,11 +56,8 @@ compositor gbufferFinalizer shadows off pass clear { - clear - { - buffers colour - colour_value 0 0 0 0 - } + buffers colour + colour_value 0 0 0 0 } pass render_quad { @@ -81,9 +75,6 @@ compositor gbufferFinalizer input none pass clear { - clear - { - } } pass render_quad { From 19c428e86c46ab120379f9dbfb1aceb72ac6d0ff Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 02:04:00 +0200 Subject: [PATCH 206/289] delete fix --- apps/openmw/mwrender/terrain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 90345cf30..4dac750c7 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -86,6 +86,7 @@ namespace MWRender TerrainManager::~TerrainManager() { + OGRE_DELETE mTerrainGlobals; } //---------------------------------------------------------------------------------------------- From 3daf1ebc3fc36dbc565279a1274a110a69963147 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 05:03:50 +0200 Subject: [PATCH 207/289] small map tweak --- apps/openmw/mwrender/localmap.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 55cb45fdc..2442700bb 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -326,8 +326,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, -playerdirection.z); // explore radius (squared) - const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; - const float exploreRadius = 0.1 * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution + const float sqrExploreRadius = (mInterior ? 0.01 : 0.09) * sFogOfWarResolution*sFogOfWarResolution; + const float exploreRadius = (mInterior ? 0.1 : 0.3) * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) int intExtMult = mInterior ? 1 : -1; // interior and exterior have reversed Y coordinates (interior: top to bottom) @@ -364,7 +364,11 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni { for (int texU = 0; texU> 24); alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); From 14f4f09f834b4d5f7c1d840de8b3be18ff66943e Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 09:19:25 +0200 Subject: [PATCH 208/289] proper resolution switching (reposition GUI & adjust mouse clipping region) --- apps/openmw/mwgui/console.cpp | 5 +++++ apps/openmw/mwgui/console.hpp | 2 ++ apps/openmw/mwgui/hud.cpp | 5 +++++ apps/openmw/mwgui/hud.hpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 5 +++++ apps/openmw/mwgui/window_base.cpp | 10 +++++++++- apps/openmw/mwgui/window_manager.cpp | 21 +++++++++++++++++++++ apps/openmw/mwinput/inputmanager.cpp | 23 ++++++++++++++++++++++- apps/openmw/mwinput/inputmanager.hpp | 4 ++++ apps/openmw/mwrender/renderingmanager.cpp | 23 +++++++++++++++++++---- libs/mangle/input/servers/ois_driver.cpp | 7 +++++++ libs/mangle/input/servers/ois_driver.hpp | 2 ++ libs/openengine/gui/events.cpp | 18 +++--------------- libs/openengine/gui/events.hpp | 2 -- libs/openengine/ogre/renderer.cpp | 6 +----- libs/openengine/ogre/renderer.hpp | 2 +- 16 files changed, 107 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 8e15abddd..bf80a77b2 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -370,4 +370,9 @@ namespace MWGui /* All keywords match with the shortest. Append it to the output string and return it. */ return output.append(matches.front()); } + + void Console::onResChange(int width, int height) + { + setCoord(10,10, width-10, height/2); + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 6974d8333..117285847 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -58,6 +58,8 @@ namespace MWGui void setFont(const std::string &fntName); + void onResChange(int width, int height); + void clearHistory(); // Print a message to the console. Messages may contain color diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index d3d7696b4..31952e993 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -347,3 +347,8 @@ void HUD::onFrame(float dt) if (mCellNameTimer < 0) mCellNameBox->setVisible(false); } + +void HUD::onResChange(int width, int height) +{ + setCoord(0, 0, width, height); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index f7131a39c..531dd7020 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -26,6 +26,7 @@ namespace MWGui void setFpsLevel(const int level); void onFrame(float dt); + void onResChange(int width, int height); void setCellName(const std::string& cellName); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 0e0815228..c8337d74c 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -11,6 +11,7 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwsound/soundmanager.hpp" +#include "../mwinput/inputmanager.hpp" #include "window_manager.hpp" #include "confirmationdialog.hpp" @@ -144,7 +145,10 @@ namespace MWGui } if (_sender == mFullscreenButton) + { Settings::Manager::setBool("fullscreen", "Video", newState); + apply(); + } else if (_sender == mVSyncButton) { Settings::Manager::setBool("vsync", "Video", newState); @@ -188,5 +192,6 @@ namespace MWGui MWBase::Environment::get().getWorld()->processChangedSettings(changed); MWBase::Environment::get().getSoundManager()->processChangedSettings(changed); MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); + MWBase::Environment::get().getInputManager()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp index 45206214b..433057931 100644 --- a/apps/openmw/mwgui/window_base.cpp +++ b/apps/openmw/mwgui/window_base.cpp @@ -1,6 +1,8 @@ #include "window_base.hpp" #include "window_manager.hpp" +#include + using namespace MWGui; WindowBase::WindowBase(const std::string& parLayout, WindowManager& parWindowManager) @@ -25,7 +27,13 @@ void WindowBase::setVisible(bool visible) void WindowBase::center() { // Centre dialog - MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Note by scrawl: The following works more reliably in the case when the window was _just_ + // resized and MyGUI RenderManager doesn't know about the new size yet + MyGUI::IntSize gameWindowSize = MyGUI::IntSize(Settings::Manager::getInt("resolution x", "Video"), + Settings::Manager::getInt("resolution y", "Video")); + MyGUI::IntCoord coord = mMainWidget->getCoord(); coord.left = (gameWindowSize.width - coord.width)/2; coord.top = (gameWindowSize.height - coord.height)/2; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a6d236136..891f85ca2 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -605,6 +605,27 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); + + bool changeRes = false; + for (Settings::CategorySettingVector::const_iterator it = changed.begin(); + it != changed.end(); ++it) + { + if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y")) + { + changeRes = true; + } + } + + if (changeRes) + { + int x = Settings::Manager::getInt("resolution x", "Video"); + int y = Settings::Manager::getInt("resolution y", "Video"); + hud->onResChange(x, y); + console->onResChange(x, y); + mSettingsWindow->center(); + } } void WindowManager::pushGuiMode(GuiMode mode) diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 9b6a1d39b..a2bafcbf7 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -92,7 +92,12 @@ namespace MWInput /* InputImpl Methods */ - +public: + void adjustMouseRegion(int width, int height) + { + input.adjustMouseClippingSize(width, height); + } +private: void toggleSpell() { if (windows.isGuiMode()) return; @@ -450,4 +455,20 @@ namespace MWInput { impl->changeInputMode(guiMode); } + + void MWInputManager::processChangedSettings(const Settings::CategorySettingVector& changed) + { + bool changeRes = false; + for (Settings::CategorySettingVector::const_iterator it = changed.begin(); + it != changed.end(); ++it) + { + if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y")) + changeRes = true; + } + + if (changeRes) + impl->adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video")); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index b8d98ed56..4ef3df137 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -3,6 +3,8 @@ #include "../mwgui/mode.hpp" +#include + namespace OEngine { namespace Render @@ -52,6 +54,8 @@ namespace MWInput void changeInputMode(bool guiMode); + void processChangedSettings(const Settings::CategorySettingVector& changed); + void setDragDrop(bool dragDrop); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e5ce6b0dd..46e274ff5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -22,6 +22,9 @@ #include "water.hpp" #include "compositors.hpp" +#include "../mwgui/window_manager.hpp" // FIXME +#include "../mwinput/inputmanager.hpp" // FIXME + using namespace MWRender; using namespace Ogre; @@ -591,9 +594,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec if (changeRes) { - int x = Settings::Manager::getInt("resolution x", "Video"); - int y = Settings::Manager::getInt("resolution y", "Video"); - mRendering.getWindow()->resize(x, y); + unsigned int x = Settings::Manager::getInt("resolution x", "Video"); + unsigned int y = Settings::Manager::getInt("resolution y", "Video"); + + if (x != mRendering.getWindow()->getWidth() || y != mRendering.getWindow()->getHeight()) + { + mRendering.getWindow()->resize(x, y); + } mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } } @@ -610,9 +617,17 @@ void RenderingManager::setMenuTransparency(float val) void RenderingManager::windowResized(Ogre::RenderWindow* rw) { - mCompositors->setViewport(mRendering.recreateViewport()); + Settings::Manager::setInt("resolution x", "Video", rw->getWidth()); + Settings::Manager::setInt("resolution y", "Video", rw->getHeight()); + + + mRendering.adjustViewport(); mCompositors->recreate(); mWater->assignTextures(); + + const Settings::CategorySettingVector& changed = Settings::Manager::apply(); + MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME + MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME } void RenderingManager::windowClosed(Ogre::RenderWindow* rw) diff --git a/libs/mangle/input/servers/ois_driver.cpp b/libs/mangle/input/servers/ois_driver.cpp index 2071b91ea..acca69df4 100644 --- a/libs/mangle/input/servers/ois_driver.cpp +++ b/libs/mangle/input/servers/ois_driver.cpp @@ -146,3 +146,10 @@ bool OISDriver::isDown(int index) // TODO: Extend to mouse buttons as well return keyboard->isKeyDown((OIS::KeyCode)index); } + +void OISDriver::adjustMouseClippingSize(int width, int height) +{ + const OIS::MouseState &ms = mouse->getMouseState(); + ms.width = width; + ms.height = height; +} diff --git a/libs/mangle/input/servers/ois_driver.hpp b/libs/mangle/input/servers/ois_driver.hpp index ba780c39e..81633542f 100644 --- a/libs/mangle/input/servers/ois_driver.hpp +++ b/libs/mangle/input/servers/ois_driver.hpp @@ -31,6 +31,8 @@ namespace Mangle OISDriver(Ogre::RenderWindow *window, bool exclusive=true); ~OISDriver(); + void adjustMouseClippingSize(int width, int height); + void capture(); bool isDown(int index); /// Not currently supported. diff --git a/libs/openengine/gui/events.cpp b/libs/openengine/gui/events.cpp index 3e52c6435..a19c247c2 100644 --- a/libs/openengine/gui/events.cpp +++ b/libs/openengine/gui/events.cpp @@ -8,18 +8,9 @@ using namespace OIS; using namespace OEngine::GUI; EventInjector::EventInjector(MyGUI::Gui *g) - : gui(g), mouseX(0), mouseY(0), enabled(true) + : gui(g), enabled(true) { assert(gui); - maxX = MyGUI::RenderManager::getInstance().getViewSize().width; - maxY = MyGUI::RenderManager::getInstance().getViewSize().height; -} - -template -void setRange(X &x, X min, X max) -{ - if(x < min) x = min; - else if(x > max) x = max; } void EventInjector::event(Type type, int index, const void *p) @@ -64,11 +55,8 @@ void EventInjector::event(Type type, int index, const void *p) MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); // Update mouse position - mouseX += mouse->state.X.rel; - mouseY += mouse->state.Y.rel; - - setRange(mouseX,0,maxX); - setRange(mouseY,0,maxY); + int mouseX = mouse->state.X.abs; + int mouseY = mouse->state.Y.abs; if(type == EV_MouseDown) MyGUI::InputManager::getInstance().injectMousePress(mouseX, mouseY, id); diff --git a/libs/openengine/gui/events.hpp b/libs/openengine/gui/events.hpp index 6ca83cf75..1f506cffa 100644 --- a/libs/openengine/gui/events.hpp +++ b/libs/openengine/gui/events.hpp @@ -16,8 +16,6 @@ namespace GUI class EventInjector : public Mangle::Input::Event { MyGUI::Gui *gui; - int mouseX, mouseY; - int maxX, maxY; public: bool enabled; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 579ba3dd7..7a01ffce7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -145,14 +145,10 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC mFader = new Fader(); } -Ogre::Viewport* OgreRenderer::recreateViewport() +void OgreRenderer::adjustViewport() { - mWindow->removeViewport(mView->getZOrder()); - mView = mWindow->addViewport(mCamera); - // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); - return mView; } void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 7a0fd11df..9d1d0122d 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -157,7 +157,7 @@ namespace OEngine /// Viewport Ogre::Viewport *getViewport() { return mView; } - Ogre::Viewport* recreateViewport(); + void adjustViewport(); }; } } From 6014a900025cd45b13325c0d1f9d896e856defe5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 09:46:05 +0200 Subject: [PATCH 209/289] added tooltip delay option --- apps/openmw/mwgui/settingswindow.cpp | 6 ++++ apps/openmw/mwgui/settingswindow.hpp | 1 + apps/openmw/mwgui/tooltips.cpp | 30 +++++++++++++++++++ apps/openmw/mwgui/tooltips.hpp | 8 +++++ apps/openmw/mwgui/window_manager.cpp | 1 + files/mygui/openmw_settings_window_layout.xml | 15 ++++++++++ files/settings-default.cfg | 3 ++ 7 files changed, 64 insertions(+) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index c8337d74c..428e0e862 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -37,6 +37,7 @@ namespace MWGui getWidget(mOkButton, "OkButton"); getWidget(mResolutionList, "ResolutionList"); getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); + getWidget(mToolTipDelaySlider, "ToolTipDelaySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); @@ -52,6 +53,7 @@ namespace MWGui mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); @@ -79,6 +81,8 @@ namespace MWGui // read settings int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); mMenuTransparencySlider->setScrollPosition(menu_transparency); + int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); + mToolTipDelaySlider->setScrollPosition(tooltip_delay); float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; @@ -170,6 +174,8 @@ namespace MWGui float val = pos / float(scroller->getScrollRange()-1); if (scroller == mMenuTransparencySlider) Settings::Manager::setFloat("menu transparency", "GUI", val); + else if (scroller == mToolTipDelaySlider) + Settings::Manager::setFloat("tooltip delay", "GUI", val); else if (scroller == mViewDistanceSlider) Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); else if (scroller == mMasterVolumeSlider) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 79af03994..09a93264d 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -19,6 +19,7 @@ namespace MWGui MyGUI::Button* mOkButton; MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::ScrollBar* mToolTipDelaySlider; // graphics MyGUI::ListBox* mResolutionList; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index c6d8e2c8c..bdce61a44 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -8,6 +8,8 @@ #include +#include + using namespace MWGui; using namespace MyGUI; @@ -19,6 +21,10 @@ ToolTips::ToolTips(WindowManager* windowManager) : , mEnabled(true) , mFocusToolTipX(0.0) , mFocusToolTipY(0.0) + , mDelay(0.0) + , mRemainingDelay(0.0) + , mLastMouseX(0) + , mLastMouseY(0) { getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); @@ -28,6 +34,9 @@ ToolTips::ToolTips(WindowManager* windowManager) : // even if the mouse is over the tooltip mDynamicToolTipBox->setNeedMouseFocus(false); mMainWidget->setNeedMouseFocus(false); + + mDelay = Settings::Manager::getFloat("tooltip delay", "GUI"); + mRemainingDelay = mDelay; } void ToolTips::setEnabled(bool enabled) @@ -57,6 +66,21 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { + const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) + { + mRemainingDelay -= frameDuration; + } + else + { + mRemainingDelay = mDelay; + } + mLastMouseX = mousePos.left; + mLastMouseY = mousePos.top; + + if (mRemainingDelay > 0) + return; + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); if (focus == 0) { @@ -621,3 +645,9 @@ void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playe widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipLayout", "ClassToolTip"); } + +void ToolTips::setDelay(float delay) +{ + mDelay = delay; + mRemainingDelay = mDelay; +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 1925a4f14..036bdfaa3 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -41,6 +41,8 @@ namespace MWGui void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; + void setDelay(float delay); + void setFocusObject(const MWWorld::Ptr& focus); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); ///< set the screen-space position of the tooltip for focused object @@ -84,6 +86,12 @@ namespace MWGui float mFocusToolTipX; float mFocusToolTipY; + float mDelay; + float mRemainingDelay; // remaining time until tooltip will show + + int mLastMouseX; + int mLastMouseY; + bool mGameMode; bool mEnabled; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 891f85ca2..c3dc5d801 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -605,6 +605,7 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); + mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 9b5826765..2e53c2a4a 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -23,6 +23,21 @@ + + + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index a6623656c..883f32ae0 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -28,6 +28,9 @@ vsync = false # 1 is fully opaque menu transparency = 0.84 +# 0 - instantly, 1 - max. delay +tooltip delay = 0.2 + [General] # Camera field of view field of view = 55 From e1ee45a6d66f1eacfa7192d386ccfde42ef53761 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 10:50:00 +0200 Subject: [PATCH 210/289] Issue #297: Make the stats review dialog show correct values for attributes/skills/health/magicka/fatigue --- apps/openmw/mwgui/charactercreation.cpp | 62 +++++++++++++++++++++++-- apps/openmw/mwgui/charactercreation.hpp | 8 ++-- apps/openmw/mwgui/class.cpp | 10 ++-- apps/openmw/mwgui/review.cpp | 3 ++ apps/openmw/mwgui/stats_window.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 4 ++ apps/openmw/mwgui/window_manager.hpp | 5 ++ 7 files changed, 81 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 691fd4a91..cc7448646 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -122,6 +122,56 @@ CharacterCreation::CharacterCreation(WindowManager* _wm) mCreationStage = CSE_NotStarted; } +void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat& value) +{ + if (mReviewDialog) + { + static const char *ids[] = + { + "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", + "AttribVal6", "AttribVal7", "AttribVal8", + 0 + }; + + for (int i=0; ids[i]; ++i) + { + if (ids[i]==id) + mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value); + } + } +} + +void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat& value) +{ + if (mReviewDialog) + { + if (id == "HBar") + { + mReviewDialog->setHealth (value); + } + else if (id == "MBar") + { + mReviewDialog->setMagicka (value); + } + else if (id == "FBar") + { + mReviewDialog->setFatigue (value); + } + } +} + +void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value) +{ + if (mReviewDialog) + mReviewDialog->setSkillValue(parSkill, value); +} + +void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor) +{ + if (mReviewDialog) + mReviewDialog->configureSkills(major, minor); +} + void CharacterCreation::spawnDialog(const char id) { switch (id) @@ -208,20 +258,22 @@ void CharacterCreation::spawnDialog(const char id) mReviewDialog->setFatigue(mPlayerFatigue); { - std::map >::iterator end = mPlayerAttributes.end(); - for (std::map >::iterator it = mPlayerAttributes.begin(); it != end; ++it) + std::map > attributes = mWM->getPlayerAttributeValues(); + for (std::map >::iterator it = attributes.begin(); + it != attributes.end(); ++it) { mReviewDialog->setAttribute(it->first, it->second); } } { - std::map >::iterator end = mPlayerSkillValues.end(); - for (std::map >::iterator it = mPlayerSkillValues.begin(); it != end; ++it) + std::map > skills = mWM->getPlayerSkillValues(); + for (std::map >::iterator it = skills.begin(); + it != skills.end(); ++it) { mReviewDialog->setSkillValue(it->first, it->second); } - mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills); + mReviewDialog->configureSkills(mWM->getPlayerMajorSkills(), mWM->getPlayerMinorSkills()); } mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index dfb07853e..02b48ffe2 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -42,6 +42,11 @@ namespace MWGui void setPlayerFatigue (const MWMechanics::DynamicStat& value); + void setValue (const std::string& id, const MWMechanics::Stat& value); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); + void configureSkills (const SkillList& major, const SkillList& minor); + private: //Dialogs TextInputDialog* mNameDialog; @@ -61,9 +66,6 @@ namespace MWGui std::string mPlayerRaceId; std::string mPlayerBirthSignId; ESM::Class mPlayerClass; - std::map > mPlayerAttributes; - SkillList mPlayerMajorSkills, mPlayerMinorSkills; - std::map > mPlayerSkillValues; MWMechanics::DynamicStat mPlayerHealth; MWMechanics::DynamicStat mPlayerMagicka; MWMechanics::DynamicStat mPlayerFatigue; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index d3d261ab0..a7e5b8674 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -241,10 +241,10 @@ void PickClassDialog::updateStats() for (int i = 0; i < 5; ++i) { - majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); - minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); - ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][0]); - ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][1]); + minorSkill[i]->setSkillNumber(klass->data.skills[i][0]); + majorSkill[i]->setSkillNumber(klass->data.skills[i][1]); + ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][0]); + ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][1]); } classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); @@ -518,7 +518,7 @@ std::vector CreateClassDialog::getMinorSkills() const std::vector v; for(int i=0; i < 5; i++) { - v.push_back(majorSkill[i]->getSkillId()); + v.push_back(minorSkill[i]->getSkillId()); } return v; } diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index be537e854..67b6cc24a 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -211,6 +211,7 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic widget->setCaption(text); widget->_setWidgetState(state); } + } void ReviewDialog::configureSkills(const std::vector& major, const std::vector& minor) @@ -230,6 +231,8 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec if (skillSet.find(skill) == skillSet.end()) miscSkills.push_back(skill); } + + updateSkillArea(); } void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 061800bf0..75159f4db 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -255,6 +255,8 @@ void StatsWindow::configureSkills (const std::vector& major, const std::vec if (skillSet.find(skill) == skillSet.end()) miscSkills.push_back(skill); } + + updateSkillArea(); } void StatsWindow::onFrame () diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index c3dc5d801..4e786978f 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -302,6 +302,7 @@ void WindowManager::updateVisible() void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { mStatsWindow->setValue (id, value); + mCharGen->setValue(id, value); static const char *ids[] = { @@ -332,6 +333,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { mStatsWindow->setValue(parSkill, value); + mCharGen->setValue(parSkill, value); playerSkillValues[parSkill] = value; } @@ -339,6 +341,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS { mStatsWindow->setValue (id, value); hud->setValue (id, value); + mCharGen->setValue(id, value); if (id == "HBar") { playerHealth = value; @@ -391,6 +394,7 @@ void WindowManager::setPlayerClass (const ESM::Class &class_) void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) { mStatsWindow->configureSkills (major, minor); + mCharGen->configureSkills(major, minor); playerMajorSkills = major; playerMinorSkills = minor; } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 7082cc0bc..f3e6a436e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -211,6 +211,11 @@ namespace MWGui void onFrame (float frameDuration); + std::map > getPlayerSkillValues() { return playerSkillValues; } + std::map > getPlayerAttributeValues() { return playerAttributes; } + SkillList getPlayerMinorSkills() { return playerMinorSkills; } + SkillList getPlayerMajorSkills() { return playerMajorSkills; } + /** * Fetches a GMST string from the store, if there is no setting with the given * ID or it is not a string the default string is returned. From a54623bcd2a764e7622d282ea3a7117ab24cdfe2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 11:37:56 +0200 Subject: [PATCH 211/289] reset attributes when building player --- apps/openmw/mwmechanics/mechanicsmanager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 0c48d8894..331074ef7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -30,6 +30,15 @@ namespace MWMechanics for (int i=0; i<27; ++i) npcStats.mSkill[i].setBase (player->npdt52.skills[i]); + creatureStats.mAttributes[0].setBase (player->npdt52.strength); + creatureStats.mAttributes[1].setBase (player->npdt52.intelligence); + creatureStats.mAttributes[2].setBase (player->npdt52.willpower); + creatureStats.mAttributes[3].setBase (player->npdt52.agility); + creatureStats.mAttributes[4].setBase (player->npdt52.speed); + creatureStats.mAttributes[5].setBase (player->npdt52.endurance); + creatureStats.mAttributes[6].setBase (player->npdt52.personality); + creatureStats.mAttributes[7].setBase (player->npdt52.luck); + // race if (mRaceSelected) { From 0a17d6d710731152d543f866d805a1eb7e58e609 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 12:34:29 +0200 Subject: [PATCH 212/289] more resolution switching fixes --- apps/openmw/mwgui/confirmationdialog.cpp | 2 ++ apps/openmw/mwgui/confirmationdialog.hpp | 1 + apps/openmw/mwgui/hud.cpp | 4 ++- apps/openmw/mwgui/hud.hpp | 2 ++ apps/openmw/mwgui/settingswindow.cpp | 40 ++++++++++++++++++++++-- apps/openmw/mwgui/settingswindow.hpp | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index a54bdb1d8..5e12c3296 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -50,6 +50,8 @@ namespace MWGui void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) { + eventCancelClicked(); + close(); } diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index a20034171..d278274a0 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -17,6 +17,7 @@ namespace MWGui signature : void method()\n */ EventHandle_Void eventOkClicked; + EventHandle_Void eventCancelClicked; private: MyGUI::EditBox* mMessage; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 31952e993..7276218d6 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -43,6 +43,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mDragAndDrop(dragAndDrop) , mCellNameTimer(0.0f) , mCellNameBox(NULL) + , mMapVisible(true) { setCoord(0,0, width, height); @@ -234,6 +235,7 @@ void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible if (!minimapBoxVisible) effectsDx = minimapBoxBaseRight - effectBoxBaseRight; + mMapVisible = minimapBoxVisible; minimapBox->setVisible(minimapBoxVisible); effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop()); effectBox->setVisible(effectBoxVisible); @@ -337,7 +339,7 @@ void HUD::setCellName(const std::string& cellName) mCellName = cellName; mCellNameBox->setCaption(mCellName); - mCellNameBox->setVisible(true); + mCellNameBox->setVisible(mMapVisible); } } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 531dd7020..16749114c 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -57,6 +57,8 @@ namespace MWGui std::string mCellName; float mCellNameTimer; + bool mMapVisible; + void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 428e0e862..3f30516d9 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -113,6 +113,8 @@ namespace MWGui dialog->open("#{sNotifyMessage67}"); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); + dialog->eventCancelClicked.clear(); + dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); } void SettingsWindow::onResolutionAccept() @@ -130,6 +132,12 @@ namespace MWGui Settings::Manager::setInt("resolution y", "Video", resY); apply(); + mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); + } + + void SettingsWindow::onResolutionCancel() + { + mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); } void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) @@ -150,8 +158,36 @@ namespace MWGui if (_sender == mFullscreenButton) { - Settings::Manager::setBool("fullscreen", "Video", newState); - apply(); + // check if this resolution is supported in fullscreen + bool supported = false; + for (unsigned int i=0; igetItemCount(); ++i) + { + std::string resStr = mResolutionList->getItemNameAt(i); + size_t xPos = resStr.find("x"); + std::string resXStr = resStr.substr(0, xPos-1); + Ogre::StringUtil::trim(resXStr); + std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); + Ogre::StringUtil::trim(resYStr); + int resX = boost::lexical_cast(resXStr); + int resY = boost::lexical_cast(resYStr); + + if (resX == Settings::Manager::getInt("resolution x", "Video") + && resY == Settings::Manager::getInt("resolution y", "Video")) + supported = true; + } + + if (!supported) + { + std::string msg = "This resolution is not supported in Fullscreen mode. Please select a resolution from the list."; + MWBase::Environment::get().getWindowManager()-> + messageBox(msg, std::vector()); + _sender->castType()->setCaption(off); + } + else + { + Settings::Manager::setBool("fullscreen", "Video", newState); + apply(); + } } else if (_sender == mVSyncButton) { diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 09a93264d..9079cff54 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -41,6 +41,7 @@ namespace MWGui void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); void onResolutionAccept(); + void onResolutionCancel(); void apply(); }; From f75266e4bae64ab53515614934a569aedb918e2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 01:47:49 +0200 Subject: [PATCH 213/289] fixed race dialog bug --- apps/openmw/mwgui/charactercreation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index cc7448646..31696230c 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -471,14 +471,14 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) mWM->popGuiMode(); mWM->pushGuiMode(GM_Review); } - else if (mCreationStage >= CSE_NameChosen) + else if (mCreationStage >= CSE_RaceChosen) { mWM->popGuiMode(); mWM->pushGuiMode(GM_Class); } else { - mCreationStage = CSE_NameChosen; + mCreationStage = CSE_RaceChosen; mWM->popGuiMode(); } } From 8c7cb6909d937563247048e652946e3035a7fa8c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 01:59:16 +0200 Subject: [PATCH 214/289] addition to c7010623fb419f928fb369b5e93cbcfe39c0e0c8 : apparently talking _is_ allowed during the starting sequence, it is only disabled via scripts for certain actors --- apps/openmw/mwworld/actiontalk.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index b3b631653..a0f9d8c4c 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -11,9 +11,6 @@ namespace MWWorld void ActionTalk::execute() { - if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) - return; - MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } } From 6945afe95b8073b71719905fb3d7b4647c79052b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 02:57:19 +0200 Subject: [PATCH 215/289] alchemy window layout --- apps/openmw/mwgui/alchemywindow.cpp | 46 +++++++++++++++++++- files/mygui/openmw_alchemy_window_layout.xml | 40 ++++++++--------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 50d209524..9c26bfabe 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -128,6 +128,7 @@ namespace MWGui { ESM::ENAMstruct effect; effect.effectID = mEffects[i].mEffectID; + effect.area = 0; effect.range = ESM::RT_Self; effect.skill = mEffects[i].mSkill; effect.attribute = mEffects[i].mAttribute; @@ -167,10 +168,51 @@ namespace MWGui int random = rand() % names.size(); newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif"; newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds"; - std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + + // check if a similiar potion record exists already + bool found = false; + std::string objectId; + typedef std::map PotionMap; + PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list; + for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it) + { + if (found) break; + + if (it->second.data.value == newPotion.data.value + && it->second.data.weight == newPotion.data.weight + && it->second.name == newPotion.name + && it->second.effects.list.size() == newPotion.effects.list.size()) + { + // check effects + for (unsigned int i=0; i < it->second.effects.list.size(); ++i) + { + const ESM::ENAMstruct& a = it->second.effects.list[i]; + const ESM::ENAMstruct& b = newPotion.effects.list[i]; + if (a.effectID == b.effectID + && a.area == b.area + && a.range == b.range + && a.skill == b.skill + && a.attribute == b.attribute + && a.magnMin == b.magnMin + && a.magnMax == b.magnMax + && a.duration == b.duration) + { + found = true; + objectId = it->first; + break; + } + } + } + } + + if (!found) + { + std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + objectId = result.first; + } // create a reference and add it to player inventory - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId); MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); ref.getPtr().getRefData().setCount(1); store.add(ref.getPtr()); diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 8eb5e1265..2590f9db2 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -1,7 +1,7 @@ - + @@ -10,73 +10,73 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + From 5d03e866131372be578e5898b6b1d3bf63d2c7ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 04:54:54 +0200 Subject: [PATCH 216/289] added field of view and texture filtering to settings window --- apps/openmw/mwgui/settingswindow.cpp | 69 ++++++++++++++++++- apps/openmw/mwgui/settingswindow.hpp | 12 ++++ apps/openmw/mwrender/renderingmanager.cpp | 15 ++++ files/mygui/openmw_alchemy_window_layout.xml | 4 +- files/mygui/openmw_settings_window_layout.xml | 33 ++++++++- libs/openengine/gui/events.cpp | 19 +++-- libs/openengine/gui/events.hpp | 3 + libs/openengine/ogre/renderer.cpp | 5 ++ libs/openengine/ogre/renderer.hpp | 2 + 9 files changed, 151 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3f30516d9..82c8b554f 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -27,6 +27,18 @@ namespace else return "Detailed"; } + + std::string textureFilteringToStr(const std::string& val) + { + if (val == "none") + return "None"; + else if (val == "anisotropic") + return "Anisotropic"; + else if (val == "bilinear") + return "Bilinear"; + else + return "Trilinear"; + } } namespace MWGui @@ -42,20 +54,28 @@ namespace MWGui getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); getWidget(mFPSButton, "FPSButton"); + getWidget(mFOVSlider, "FOVSlider"); getWidget(mMasterVolumeSlider, "MasterVolume"); getWidget(mVoiceVolumeSlider, "VoiceVolume"); getWidget(mEffectsVolumeSlider, "EffectsVolume"); getWidget(mFootstepsVolumeSlider, "FootstepsVolume"); getWidget(mMusicVolumeSlider, "MusicVolume"); + getWidget(mAnisotropySlider, "AnisotropySlider"); + getWidget(mTextureFilteringButton, "TextureFilteringButton"); + getWidget(mAnisotropyLabel, "AnisotropyLabel"); + getWidget(mAnisotropyBox, "AnisotropyBox"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled); mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); + mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); @@ -84,7 +104,20 @@ namespace MWGui int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); mToolTipDelaySlider->setScrollPosition(tooltip_delay); - float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); + float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin); + mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1)); + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); + + float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; + mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); + std::string tf = Settings::Manager::getString("texture filtering", "General"); + mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); + mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(Settings::Manager::getInt("anisotropy", "General")) + ")"); + mAnisotropyBox->setVisible(tf == "anisotropic"); + + float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin); int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; mViewDistanceSlider->setScrollPosition(viewdist); @@ -205,6 +238,26 @@ namespace MWGui apply(); } + void SettingsWindow::onTextureFilteringToggled(MyGUI::Widget* _sender) + { + std::string current = Settings::Manager::getString("texture filtering", "General"); + std::string next; + if (current == "none") + next = "bilinear"; + else if (current == "bilinear") + next = "trilinear"; + else if (current == "trilinear") + next = "anisotropic"; + else + next = "none"; + + mTextureFilteringButton->setCaption(textureFilteringToStr(next)); + mAnisotropyBox->setVisible(next == "anisotropic"); + + Settings::Manager::setString("texture filtering", "General", next); + apply(); + } + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) { float val = pos / float(scroller->getScrollRange()-1); @@ -213,7 +266,19 @@ namespace MWGui else if (scroller == mToolTipDelaySlider) Settings::Manager::setFloat("tooltip delay", "GUI", val); else if (scroller == mViewDistanceSlider) - Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax); + else if (scroller == mFOVSlider) + { + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + fovText->setCaption("Field of View (" + boost::lexical_cast(int((1-val) * sFovMin + val * sFovMax)) + ")"); + Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); + } + else if (scroller == mAnisotropySlider) + { + mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(int(val*16)) + ")"); + Settings::Manager::setInt("anisotropy", "General", val * 16); + } else if (scroller == mMasterVolumeSlider) Settings::Manager::setFloat("master volume", "Sound", val); else if (scroller == mVoiceVolumeSlider) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 9079cff54..8924375d9 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -15,6 +15,12 @@ namespace MWGui public: SettingsWindow(WindowManager& parWindowManager); + private: + static const float sFovMin = 30; + static const float sFovMax = 140; + static const float sViewDistMin = 2000; + static const float sViewDistMax = 5600; + protected: MyGUI::Button* mOkButton; @@ -27,6 +33,11 @@ namespace MWGui MyGUI::Button* mVSyncButton; MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; + MyGUI::ScrollBar* mFOVSlider; + MyGUI::ScrollBar* mAnisotropySlider; + MyGUI::Button* mTextureFilteringButton; + MyGUI::TextBox* mAnisotropyLabel; + MyGUI::Widget* mAnisotropyBox; // audio MyGUI::ScrollBar* mMasterVolumeSlider; @@ -37,6 +48,7 @@ namespace MWGui void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); + void onTextureFilteringToggled(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 46e274ff5..89f42a5f1 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -590,6 +590,21 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = true; + else if (it->second == "field of view" && it->first == "General") + mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); + else if ((it->second == "texture filtering" && it->first == "General") + || (it->second == "anisotropy" && it->first == "General")) + { + TextureFilterOptions tfo; + std::string filter = Settings::Manager::getString("texture filtering", "General"); + if (filter == "anisotropic") tfo = TFO_ANISOTROPIC; + else if (filter == "trilinear") tfo = TFO_TRILINEAR; + else if (filter == "bilinear") tfo = TFO_BILINEAR; + else if (filter == "none") tfo = TFO_NONE; + + MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); + MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); + } } if (changeRes) diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 2590f9db2..68df748b1 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -60,9 +60,9 @@ - + - + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 2e53c2a4a..107e883c4 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -100,15 +100,44 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/openengine/gui/events.cpp b/libs/openengine/gui/events.cpp index a19c247c2..bce70704b 100644 --- a/libs/openengine/gui/events.cpp +++ b/libs/openengine/gui/events.cpp @@ -9,8 +9,13 @@ using namespace OEngine::GUI; EventInjector::EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) + , mMouseX(0) + , mMouseY(0) { assert(gui); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + mMouseX = viewSize.width/2; + mMouseY = viewSize.height/2; } void EventInjector::event(Type type, int index, const void *p) @@ -54,15 +59,19 @@ void EventInjector::event(Type type, int index, const void *p) MouseEvent *mouse = (MouseEvent*)p; MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Update mouse position - int mouseX = mouse->state.X.abs; - int mouseY = mouse->state.Y.abs; + mMouseX += mouse->state.X.rel; + mMouseY += mouse->state.Y.rel; + mMouseX = std::max(0, std::min(mMouseX, viewSize.width)); + mMouseY = std::max(0, std::min(mMouseY, viewSize.height)); if(type == EV_MouseDown) - MyGUI::InputManager::getInstance().injectMousePress(mouseX, mouseY, id); + MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, id); else if(type == EV_MouseUp) - MyGUI::InputManager::getInstance().injectMouseRelease(mouseX, mouseY, id); + MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, id); else - MyGUI::InputManager::getInstance().injectMouseMove(mouseX, mouseY, mouse->state.Z.abs); + MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mouse->state.Z.abs); } } diff --git a/libs/openengine/gui/events.hpp b/libs/openengine/gui/events.hpp index 1f506cffa..10c5309bc 100644 --- a/libs/openengine/gui/events.hpp +++ b/libs/openengine/gui/events.hpp @@ -17,6 +17,9 @@ namespace GUI { MyGUI::Gui *gui; + int mMouseX; + int mMouseY; + public: bool enabled; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 7a01ffce7..b525e76e3 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -155,3 +155,8 @@ void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) { Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } + +void OgreRenderer::setFov(float fov) +{ + mCamera->setFOVy(Degree(fov)); +} diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 9d1d0122d..f4ea8fbc8 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -124,6 +124,8 @@ namespace OEngine float nearClip=5 // Near clip distance ); + void setFov(float fov); + /// Kill the renderer. void cleanup(); From 69e6bc6588256be514f9dbc054fd8795a20583c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 06:45:44 +0200 Subject: [PATCH 217/289] add water settings to settings window --- apps/openmw/mwgui/settingswindow.cpp | 38 +++++ apps/openmw/mwgui/settingswindow.hpp | 4 + apps/openmw/mwrender/compositors.cpp | 7 + apps/openmw/mwrender/compositors.hpp | 2 + apps/openmw/mwrender/renderingmanager.cpp | 52 +++++-- apps/openmw/mwrender/renderingmanager.hpp | 4 + apps/openmw/mwrender/water.cpp | 134 +++++++++++++----- apps/openmw/mwrender/water.hpp | 8 ++ files/mygui/openmw_settings_window_layout.xml | 28 ++++ files/water/water.material | 25 ++++ 10 files changed, 252 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 82c8b554f..67ccf9d53 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -64,9 +64,17 @@ namespace MWGui getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mAnisotropyLabel, "AnisotropyLabel"); getWidget(mAnisotropyBox, "AnisotropyBox"); + getWidget(mWaterShaderButton, "WaterShaderButton"); + getWidget(mReflectObjectsButton, "ReflectObjectsButton"); + getWidget(mReflectActorsButton, "ReflectActorsButton"); + getWidget(mReflectTerrainButton, "ReflectTerrainButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled); mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); @@ -127,6 +135,19 @@ namespace MWGui mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); + mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); + + if (!MWRender::RenderingManager::waterShaderSupported()) + { + mWaterShaderButton->setEnabled(false); + mReflectObjectsButton->setEnabled(false); + mReflectActorsButton->setEnabled(false); + mReflectTerrainButton->setEnabled(false); + } + mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); @@ -228,6 +249,23 @@ namespace MWGui MWBase::Environment::get().getWindowManager()-> messageBox("VSync will be applied after a restart", std::vector()); } + else + { + if (_sender == mWaterShaderButton) + Settings::Manager::setBool("shader", "Water", newState); + else if (_sender == mReflectObjectsButton) + { + Settings::Manager::setBool("reflect misc", "Water", newState); + Settings::Manager::setBool("reflect statics", "Water", newState); + Settings::Manager::setBool("reflect statics small", "Water", newState); + } + else if (_sender == mReflectActorsButton) + Settings::Manager::setBool("reflect actors", "Water", newState); + else if (_sender == mReflectTerrainButton) + Settings::Manager::setBool("reflect terrain", "Water", newState); + + apply(); + } } void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 8924375d9..ce95edbd2 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -38,6 +38,10 @@ namespace MWGui MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; MyGUI::Widget* mAnisotropyBox; + MyGUI::Button* mWaterShaderButton; + MyGUI::Button* mReflectObjectsButton; + MyGUI::Button* mReflectActorsButton; + MyGUI::Button* mReflectTerrainButton; // audio MyGUI::ScrollBar* mMasterVolumeSlider; diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index d786c263b..6f97269ab 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -62,3 +62,10 @@ void Compositors::setCompositorEnabled (const std::string& name, const bool enab mCompositors[name].first = enabled; Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); } + +void Compositors::removeAll() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + + mCompositors.clear(); +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index f249ece42..bbd838b8e 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -44,6 +44,8 @@ namespace MWRender */ void addCompositor (const std::string& name, const int priority); + void removeAll (); + protected: /// maps compositor name to its "enabled" state CompositorMap mCompositors; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 89f42a5f1..a6f10fcd2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -67,25 +67,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // disable unsupported effects const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + if (!waterShaderSupported()) Settings::Manager::setBool("shader", "Water", false); if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) || !Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); - // note that the order is important here - if (useMRT()) - { - mCompositors->addCompositor("gbuffer", 0); - mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("Underwater", 1); - mCompositors->addCompositor("gbufferFinalizer", 2); - mCompositors->setCompositorEnabled("gbufferFinalizer", true); - } - else - { - mCompositors->addCompositor("UnderwaterNoMRT", 0); - } + applyCompositors(); // Turn the entire scene (represented by the 'root' node) -90 // degrees around the x axis. This makes Z go upwards, and Y go into @@ -605,6 +593,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); } + else if (it->second == "shader" && it->first == "Water") + { + applyCompositors(); + mShaderHelper->applyShaders(); + } } if (changeRes) @@ -618,6 +611,9 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec } mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } + + if (mWater) + mWater->processChangedSettings(settings); } void RenderingManager::setMenuTransparency(float val) @@ -649,4 +645,32 @@ void RenderingManager::windowClosed(Ogre::RenderWindow* rw) { } +bool RenderingManager::waterShaderSupported() +{ + const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); + if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + return false; + return true; +} + +void RenderingManager::applyCompositors() +{ + mCompositors->removeAll(); + if (useMRT()) + { + mCompositors->addCompositor("gbuffer", 0); + mCompositors->setCompositorEnabled("gbuffer", true); + mCompositors->addCompositor("Underwater", 1); + mCompositors->addCompositor("gbufferFinalizer", 2); + mCompositors->setCompositorEnabled("gbufferFinalizer", true); + } + else + { + mCompositors->addCompositor("UnderwaterNoMRT", 0); + } + + if (mWater) + mWater->assignTextures(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 562184c62..642c42930 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -165,6 +165,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList Ogre::Viewport* getViewport() { return mRendering.getViewport(); } + static bool waterShaderSupported(); + protected: virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); @@ -175,6 +177,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void setMenuTransparency(float val); + void applyCompositors(); + bool mSunEnabled; SkyManager* mSkyManager; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 981343e91..b4486a0ca 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -1,5 +1,5 @@ #include "water.hpp" -#include + #include "sky.hpp" #include "renderingmanager.hpp" #include "compositors.hpp" @@ -30,13 +30,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWater->setRenderQueueGroup(RQG_Water); mWater->setCastShadows(false); - mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") - + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") - + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") - + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") - + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") - + RV_Sky; - mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); mWaterNode->setPosition(0, mTop, 0); @@ -48,30 +41,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel } mWaterNode->attachObject(mWater); - // Create rendertarget for reflection - int rttsize = Settings::Manager::getInt("rtt size", "Water"); + applyRTT(); + applyVisibilityMask(); - TexturePtr tex; - if (Settings::Manager::getBool("shader", "Water")) - { - tex = TextureManager::getSingleton().createManual("WaterReflection", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); - - RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); - Viewport* vp = rtt->addViewport(mReflectionCamera); - vp->setOverlaysEnabled(false); - vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); - vp->setShadowsEnabled(false); - vp->setVisibilityMask( mVisibilityFlags ); - // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) - //vp->setMaterialScheme("Fallback"); - rtt->addListener(this); - rtt->setActive(true); - - mReflectionTarget = rtt; - } - - mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; createMaterial(); mWater->setMaterial(mMaterial); @@ -251,7 +223,15 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) void Water::createMaterial() { - mMaterial = MaterialManager::getSingleton().getByName("Water"); + if (mReflectionTarget == 0) + { + mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback"); + } + else + { + mMaterial = MaterialManager::getSingleton().getByName("Water"); + mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture); + } // these have to be set in code std::string textureNames[32]; @@ -259,11 +239,13 @@ void Water::createMaterial() { textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; } - mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); - - // use technique without shaders if reflection is disabled + Ogre::Technique* tech; if (mReflectionTarget == 0) - mMaterial->removeTechnique(0); + tech = mMaterial->getTechnique(0); + else + tech = mMaterial->getTechnique(1); + + tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); } void Water::assignTextures() @@ -320,4 +302,84 @@ void Water::update() { } +void Water::applyRTT() +{ + if (mReflectionTarget) + { + TextureManager::getSingleton().remove("WaterReflection"); + mReflectionTarget = 0; + } + + // Create rendertarget for reflection + int rttsize = Settings::Manager::getInt("rtt size", "Water"); + + if (Settings::Manager::getBool("shader", "Water")) + { + mReflectionTexture = TextureManager::getSingleton().createManual("WaterReflection", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); + + RenderTarget* rtt = mReflectionTexture->getBuffer()->getRenderTarget(); + Viewport* vp = rtt->addViewport(mReflectionCamera); + vp->setOverlaysEnabled(false); + vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); + vp->setShadowsEnabled(false); + // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) + //vp->setMaterialScheme("Fallback"); + rtt->addListener(this); + rtt->setActive(true); + + mReflectionTarget = rtt; + } + + mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; +} + +void Water::applyVisibilityMask() +{ + mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") + + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") + + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") + + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") + + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + + RV_Sky; + + if (mReflectionTarget) + { + mReflectionTexture->getBuffer()->getRenderTarget()->getViewport(0)->setVisibilityMask(mVisibilityFlags); + } +} + +void Water::processChangedSettings(const Settings::CategorySettingVector& settings) +{ + bool applyRT = false; + bool applyVisMask = false; + for (Settings::CategorySettingVector::const_iterator it=settings.begin(); + it != settings.end(); ++it) + { + if ( it->first == "Water" && ( + it->second == "shader" + || it->second == "rtt size")) + applyRT = true; + + if ( it->first == "Water" && ( + it->second == "reflect actors" + || it->second == "reflect terrain" + || it->second == "reflect misc" + || it->second == "reflect small statics" + || it->second == "reflect statics")) + applyVisMask = true; + } + + if(applyRT) + { + applyRTT(); + applyVisibilityMask(); + createMaterial(); + mWater->setMaterial(mMaterial); + assignTextures(); + } + if (applyVisMask) + applyVisibilityMask(); +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index edd217e84..4d617ea47 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -3,9 +3,11 @@ #include #include +#include #include "renderconst.hpp" + namespace MWRender { class SkyManager; @@ -38,6 +40,9 @@ namespace MWRender { void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); + void applyRTT(); + void applyVisibilityMask(); + void updateVisible(); RenderingManager* mRendering; @@ -50,6 +55,7 @@ namespace MWRender { Ogre::Camera* mReflectionCamera; + Ogre::TexturePtr mReflectionTexture; Ogre::RenderTarget* mReflectionTarget; bool mUnderwaterEffect; @@ -68,6 +74,8 @@ namespace MWRender { void setViewportBackground(const Ogre::ColourValue& bg); + void processChangedSettings(const Settings::CategorySettingVector& settings); + void checkUnderwater(float y); void changeCell(const ESM::Cell* cell); void setHeight(const float height); diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 107e883c4..7c508b1e9 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -153,6 +153,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/water/water.material b/files/water/water.material index 8b4ff96f5..a2a6b3e2d 100644 --- a/files/water/water.material +++ b/files/water/water.material @@ -90,6 +90,31 @@ material Water } } } + + technique + { + scheme Fallback + pass + { + cull_hardware none + scene_blend alpha_blend + depth_write off + diffuse 0 0 0 1 + emissive 0.6 0.7 1.0 + ambient 0 0 0 + texture_unit + { + // texture names set via code + scale 0.1 0.1 + alpha_op_ex source1 src_manual src_current 0.7 + } + } + } + +} + +material Water_Fallback +{ technique { scheme Fallback From c7268233df07351dc7c06251bac1158c64fce23d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 09:02:22 +0200 Subject: [PATCH 218/289] spell window layout & opening/closing/pinning logic --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellwindow.cpp | 20 ++++++++++++++++++++ apps/openmw/mwgui/spellwindow.hpp | 21 +++++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 14 ++++++++++---- apps/openmw/mwgui/window_manager.hpp | 2 ++ files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_spell_window_layout.xml | 19 +++++++++++++++++++ 8 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 apps/openmw/mwgui/spellwindow.cpp create mode 100644 apps/openmw/mwgui/spellwindow.hpp create mode 100644 files/mygui/openmw_spell_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index edbeab0a1..045f504a7 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,7 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow - confirmationdialog alchemywindow referenceinterface + confirmationdialog alchemywindow referenceinterface spellwindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2b224ab2c..1a715657a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -91,7 +91,7 @@ namespace MWGui mFilterAll->setStateSelected(true); - setCoord(0, 342, 600, 258); + setCoord(0, 342, 498, 258); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); openContainer(player); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp new file mode 100644 index 000000000..9c903134d --- /dev/null +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -0,0 +1,20 @@ +#include "spellwindow.hpp" + +#include "window_manager.hpp" + +namespace MWGui +{ + SpellWindow::SpellWindow(WindowManager& parWindowManager) + : WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager) + { + getWidget(mSpellView, "SpellView"); + getWidget(mEffectBox, "EffectsBox"); + + setCoord(498, 300, 302, 300); + } + + void SpellWindow::onPinToggled() + { + mWindowManager.setSpellVisibility(!mPinned); + } +} diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp new file mode 100644 index 000000000..0450be473 --- /dev/null +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -0,0 +1,21 @@ +#ifndef MWGUI_SPELLWINDOW_H +#define MWGUI_SPELLWINDOW_H + +#include "window_pinnable_base.hpp" + +namespace MWGui +{ + class SpellWindow : public WindowPinnableBase + { + public: + SpellWindow(WindowManager& parWindowManager); + + protected: + MyGUI::ScrollView* mSpellView; + MyGUI::Widget* mEffectBox; + + virtual void onPinToggled(); + }; +} + +#endif diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4e786978f..2db71438a 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -19,6 +19,7 @@ #include "settingswindow.hpp" #include "confirmationdialog.hpp" #include "alchemywindow.hpp" +#include "spellwindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -56,6 +57,7 @@ WindowManager::WindowManager( , mSettingsWindow(NULL) , mConfirmationDialog(NULL) , mAlchemyWindow(NULL) + , mSpellWindow(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -124,6 +126,7 @@ WindowManager::WindowManager( mSettingsWindow = new SettingsWindow(*this); mConfirmationDialog = new ConfirmationDialog(*this); mAlchemyWindow = new AlchemyWindow(*this); + mSpellWindow = new SpellWindow(*this); // The HUD is always on hud->setVisible(true); @@ -167,6 +170,7 @@ WindowManager::~WindowManager() delete mSettingsWindow; delete mConfirmationDialog; delete mAlchemyWindow; + delete mSpellWindow; cleanupGarbage(); } @@ -211,6 +215,7 @@ void WindowManager::updateVisible() mTradeWindow->setVisible(false); mSettingsWindow->setVisible(false); mAlchemyWindow->setVisible(false); + mSpellWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -224,7 +229,7 @@ void WindowManager::updateVisible() setMinimapVisibility((allowed & GW_Map) && !map->pinned()); setWeaponVisibility((allowed & GW_Inventory) && !mInventoryWindow->pinned()); - setSpellVisibility((allowed & GW_Magic)); /// \todo add pin state when spells window is implemented + setSpellVisibility((allowed & GW_Magic) && !mSpellWindow->pinned()); setHMSVisibility((allowed & GW_Stats) && !mStatsWindow->pinned()); // If in game mode, don't show anything. @@ -271,9 +276,10 @@ void WindowManager::updateVisible() int eff = shown & allowed; // Show the windows we want - map -> setVisible( (eff & GW_Map) ); - mStatsWindow -> setVisible( (eff & GW_Stats) ); - mInventoryWindow->setVisible( (eff & GW_Inventory)); + map -> setVisible(eff & GW_Map); + mStatsWindow -> setVisible(eff & GW_Stats); + mInventoryWindow->setVisible(eff & GW_Inventory); + mSpellWindow->setVisible(eff & GW_Magic); break; } case GM_Container: diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index f3e6a436e..872f46f3d 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -81,6 +81,7 @@ namespace MWGui class SettingsWindow; class ConfirmationDialog; class AlchemyWindow; + class SpellWindow; struct ClassPoint { @@ -250,6 +251,7 @@ namespace MWGui SettingsWindow* mSettingsWindow; ConfirmationDialog* mConfirmationDialog; AlchemyWindow* mAlchemyWindow; + SpellWindow* mSpellWindow; CharacterCreation* mCharGen; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 6b16e5f59..dad4afb46 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -60,6 +60,7 @@ configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_wi configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_confirmation_dialog_layout.xml" "${DDIR}/openmw_confirmation_dialog_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_alchemy_window_layout.xml" "${DDIR}/openmw_alchemy_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_spell_window_layout.xml" "${DDIR}/openmw_spell_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) diff --git a/files/mygui/openmw_spell_window_layout.xml b/files/mygui/openmw_spell_window_layout.xml new file mode 100644 index 000000000..66a685c38 --- /dev/null +++ b/files/mygui/openmw_spell_window_layout.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From 5412d6ed9effdc16ad3814a79c77f2a2665b9034 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 10:47:48 +0200 Subject: [PATCH 219/289] fixed a typo that prevented spells from getting added --- apps/openmw/mwmechanics/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index af43cdfb5..70eb78639 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -28,7 +28,7 @@ namespace MWMechanics void Spells::add (const std::string& spellId) { - if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end()) + if (std::find (mSpells.begin(), mSpells.end(), spellId)==mSpells.end()) mSpells.push_back (spellId); } From 30461438f62a45abea53100687f148a4c6d53286 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 12:35:03 +0200 Subject: [PATCH 220/289] still left: spell success formula --- apps/openmw/mwgui/container.cpp | 2 + apps/openmw/mwgui/container.hpp | 2 + apps/openmw/mwgui/hud.cpp | 5 +- apps/openmw/mwgui/inventorywindow.cpp | 8 + apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwgui/spellwindow.cpp | 358 +++++++++++++++++++++ apps/openmw/mwgui/spellwindow.hpp | 13 + apps/openmw/mwgui/tooltips.cpp | 5 + apps/openmw/mwgui/window_manager.cpp | 10 +- apps/openmw/mwgui/window_manager.hpp | 1 + apps/openmw/mwworld/containerstore.cpp | 1 + apps/openmw/mwworld/inventorystore.cpp | 13 + apps/openmw/mwworld/inventorystore.hpp | 13 +- files/mygui/openmw_spell_window_layout.xml | 1 + files/mygui/openmw_text.skin.xml | 30 ++ 15 files changed, 456 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 1cfbc1b2b..33ee8bf49 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -535,6 +535,8 @@ void ContainerBase::drawItems() 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) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 5cd8167c2..88e445a7b 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -120,6 +120,8 @@ namespace MWGui virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } + + virtual void notifyContentChanged() { ; } }; class ContainerWindow : public ContainerBase, public WindowBase diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 7276218d6..fdd1c8821 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -112,6 +112,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) void HUD::setFpsLevel(int level) { + fpscounter = 0; + MyGUI::Widget* fps; getWidget(fps, "FPSBoxAdv"); fps->setVisible(false); @@ -134,7 +136,8 @@ void HUD::setFpsLevel(int level) void HUD::setFPS(float fps) { - fpscounter->setCaption(boost::lexical_cast((int)fps)); + if (fpscounter) + fpscounter->setCaption(boost::lexical_cast((int)fps)); } void HUD::setTriangleCount(size_t count) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 1a715657a..e1d4cc998 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -20,6 +20,7 @@ #include "widgets.hpp" #include "bookwindow.hpp" #include "scrollwindow.hpp" +#include "spellwindow.hpp" namespace { @@ -259,4 +260,11 @@ namespace MWGui { mTrading = true; } + + void InventoryWindow::notifyContentChanged() + { + // update the spell window just in case new enchanted items were added to inventory + if (mWindowManager.getSpellWindow()) + mWindowManager.getSpellWindow()->updateSpells(); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index ecff75f10..bc4cb08ef 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -50,6 +50,8 @@ namespace MWGui virtual void _unequipItem(MWWorld::Ptr item); virtual void onReferenceUnavailable() { ; } + + virtual void notifyContentChanged(); }; } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 9c903134d..f761e00db 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -1,20 +1,378 @@ #include "spellwindow.hpp" +#include +#include + +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwbase/environment.hpp" +#include "../mwmechanics/spells.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwsound/soundmanager.hpp" + #include "window_manager.hpp" +#include "inventorywindow.hpp" + +namespace +{ + bool sortSpells(const std::string& left, const std::string& right) + { + const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left); + const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right); + + int cmp = a->name.compare(b->name); + return cmp < 0; + } + + bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right) + { + int cmp = MWWorld::Class::get(left).getName(left).compare( + MWWorld::Class::get(right).getName(right)); + return cmp < 0; + } +} namespace MWGui { SpellWindow::SpellWindow(WindowManager& parWindowManager) : WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager) + , mHeight(0) + , mWidth(0) { getWidget(mSpellView, "SpellView"); getWidget(mEffectBox, "EffectsBox"); setCoord(498, 300, 302, 300); + updateSpells(); + + mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); } void SpellWindow::onPinToggled() { mWindowManager.setSpellVisibility(!mPinned); } + + void SpellWindow::open() + { + updateSpells(); + } + + void SpellWindow::updateSpells() + { + const int spellHeight = 18; + + mHeight = 0; + while (mSpellView->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mSpellView->getChildAt(0)); + + // retrieve all player spells, divide them into Powers and Spells and sort them + std::vector spellList; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.mSpells; + + // the following code switches between selected enchanted item and selected spell (only one of these + // can be active at a time) + std::string selectedSpell = spells.getSelectedSpell(); + MWWorld::Ptr selectedItem; + if (store.getSelectedEnchantItem() != store.end()) + { + selectedSpell = ""; + selectedItem = *store.getSelectedEnchantItem(); + + bool allowSelectedItem = true; + + // if the selected item can be equipped, make sure that it actually is equipped + std::pair, bool> slots; + slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem); + if (!slots.first.empty()) + { + bool equipped = false; + for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) + { + if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem) + { + equipped = true; + break; + } + } + + if (!equipped) + allowSelectedItem = false; + } + + if (!allowSelectedItem) + { + store.setSelectedEnchantItem(store.end()); + selectedItem = MWWorld::Ptr(); + } + } + + + + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) + { + spellList.push_back(*it); + } + + std::vector powers; + std::vector::iterator it = spellList.begin(); + while (it != spellList.end()) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + if (spell->data.type == ESM::Spell::ST_Power) + { + powers.push_back(*it); + it = spellList.erase(it); + } + else if (spell->data.type == ESM::Spell::ST_Ability) + { + // abilities are always active and don't show in the spell window. + it = spellList.erase(it); + } + else + ++it; + } + std::sort(powers.begin(), powers.end(), sortSpells); + std::sort(spellList.begin(), spellList.end(), sortSpells); + + // retrieve player's enchanted items + std::vector items; + for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) + { + std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it); + if (enchantId != "") + { + // only add items with "Cast once" or "Cast on use" + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId); + int type = enchant->data.type; + if (type != ESM::Enchantment::CastOnce + && type != ESM::Enchantment::WhenUsed) + continue; + + items.push_back(*it); + } + } + std::sort(items.begin(), items.end(), sortItems); + + + int height = estimateHeight(items.size() + powers.size() + spellList.size()); + bool scrollVisible = height > mSpellView->getHeight(); + mWidth = mSpellView->getWidth() - (scrollVisible ? 18 : 0); + + // powers + addGroup("#{sPowers}", ""); + + for (std::vector::const_iterator it = powers.begin(); it != powers.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); + + if (*it == selectedSpell) + t->setStateSelected(true); + + mHeight += spellHeight; + } + + // other spells + addGroup("#{sSpells}", "#{sCostChance}"); + for (std::vector::const_iterator it = spellList.begin(); it != spellList.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); + + if (*it == selectedSpell) + t->setStateSelected(true); + + // cost / success chance + MyGUI::TextBox* costChance = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + std::string cost = boost::lexical_cast(spell->data.cost); + costChance->setCaption(cost + "/" + "100"); /// \todo + costChance->setTextAlign(MyGUI::Align::Right); + costChance->setNeedMouseFocus(false); + + + mHeight += spellHeight; + } + + + // enchanted items + addGroup("#{sMagicItem}", "#{sCostCharge}"); + + for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + MWWorld::Ptr item = *it; + + // check if the item is currently equipped (will display in a different color) + bool equipped = false; + for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) + { + if (store.getSlot(i) != store.end() && *store.getSlot(i) == item) + { + equipped = true; + break; + } + } + + MyGUI::Button* t = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(MWWorld::Class::get(item).getName(item)); + t->setTextAlign(MyGUI::Align::Left); + t->setUserData(item); + t->setUserString("ToolTipType", "ItemPtr"); + t->setUserString("Equipped", equipped ? "true" : "false"); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected); + t->setStateSelected(item == selectedItem); + + // cost / charge + MyGUI::TextBox* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); + std::string cost = boost::lexical_cast(enchant->data.cost); + std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge + costCharge->setCaption(cost + "/" + charge); + costCharge->setTextAlign(MyGUI::Align::Right); + costCharge->setNeedMouseFocus(false); + + mHeight += spellHeight; + } + + mSpellView->setCanvasSize(mSpellView->getWidth(), std::max(mSpellView->getHeight(), mHeight)); + } + + void SpellWindow::addGroup(const std::string &label, const std::string& label2) + { + if (mSpellView->getChildCount() > 0) + { + MyGUI::ImageBox* separator = mSpellView->createWidget("MW_HLine", + MyGUI::IntCoord(4, mHeight, mWidth-8, 18), + MyGUI::Align::Left | MyGUI::Align::Top); + separator->setNeedMouseFocus(false); + mHeight += 18; + } + + MyGUI::TextBox* groupWidget = mSpellView->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth, 24), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + groupWidget->setCaptionWithReplacing(label); + groupWidget->setTextAlign(MyGUI::Align::Left); + groupWidget->setNeedMouseFocus(false); + + if (label2 != "") + { + MyGUI::TextBox* groupWidget2 = mSpellView->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth-4, 24), + MyGUI::Align::Left | MyGUI::Align::Top); + groupWidget2->setCaptionWithReplacing(label2); + groupWidget2->setTextAlign(MyGUI::Align::Right); + groupWidget2->setNeedMouseFocus(false); + } + + mHeight += 24; + } + + void SpellWindow::onWindowResize(MyGUI::Window* _sender) + { + updateSpells(); + } + + void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::Spells& spells = stats.mSpells; + MWWorld::Ptr item = *_sender->getUserData(); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = store.begin(); + for (; it != store.end(); ++it) + { + if (*it == item) + { + break; + } + } + assert(it != store.end()); + + // equip, if it is not already equipped + if (_sender->getUserString("Equipped") == "false") + { + // sound + MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0); + + // Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping + + /// \todo the following code is pretty much copy&paste from ActionEquip, put it in a function? + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + + + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + // if all slots are occupied, replace the last slot + if (slot == --slots.first.end()) + { + store.equip(*slot, it); + break; + } + + if (store.getSlot(*slot) == store.end()) + { + // slot is not occupied + store.equip(*slot, it); + break; + } + } + /// \todo scripts? + + // since we changed equipping status, update the inventory window + mWindowManager.getInventoryWindow()->drawItems(); + } + + store.setSelectedEnchantItem(it); + spells.setSelectedSpell(""); + + updateSpells(); + } + + void SpellWindow::onSpellSelected(MyGUI::Widget* _sender) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::Spells& spells = stats.mSpells; + + spells.setSelectedSpell(_sender->getUserString("Spell")); + store.setSelectedEnchantItem(store.end()); + + updateSpells(); + } + + int SpellWindow::estimateHeight(int numSpells) const + { + int height = 0; + height += 24 * 3 + 18 * 2; // group headings + height += numSpells * 18; + return height; + } } diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 0450be473..16a1c7ff8 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -10,11 +10,24 @@ namespace MWGui public: SpellWindow(WindowManager& parWindowManager); + void updateSpells(); + protected: MyGUI::ScrollView* mSpellView; MyGUI::Widget* mEffectBox; + int mHeight; + int mWidth; + + void addGroup(const std::string& label, const std::string& label2); + + int estimateHeight(int numSpells) const; + virtual void onPinToggled(); + void onWindowResize(MyGUI::Window* _sender); + void onEnchantedItemSelected(MyGUI::Widget* _sender); + void onSpellSelected(MyGUI::Widget* _sender); + virtual void open(); }; } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index bdce61a44..dc34ee86c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -67,6 +67,11 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); + const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); + + if (mousePos == lastPressed) // mouseclick makes tooltip disappear + return; + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) { mRemainingDelay -= frameDuration; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2db71438a..4eaaf72a4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -191,12 +191,10 @@ void WindowManager::cleanupGarbage() void WindowManager::update() { cleanupGarbage(); - if (showFPSLevel > 0) - { - hud->setFPS(mFPS); - hud->setTriangleCount(mTriangleCount); - hud->setBatchCount(mBatchCount); - } + + hud->setFPS(mFPS); + hud->setTriangleCount(mTriangleCount); + hud->setBatchCount(mBatchCount); } void WindowManager::updateVisible() diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 872f46f3d..2a7794f70 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -154,6 +154,7 @@ namespace MWGui MWGui::CountDialog* getCountDialog() {return mCountDialog;} MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} + MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} MyGUI::Gui* getGui() const { return gui; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index b669508b2..3304d0e6d 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -61,6 +61,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID && 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->owner == ptr2.mCellRef->owner && ptr1.mCellRef->soul == ptr2.mCellRef->soul && ptr1.mCellRef->charge == ptr2.mCellRef->charge) diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 98ab1665b..6df73004b 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -39,15 +39,18 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots) } MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false) + , mSelectedEnchantItem(end()) { initSlots (mSlots); } MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) : ContainerStore (store) + , mSelectedEnchantItem(end()) { mMagicEffects = store.mMagicEffects; mMagicEffectsUpToDate = store.mMagicEffectsUpToDate; + mSelectedEnchantItem = store.mSelectedEnchantItem; copySlots (store); } @@ -260,3 +263,13 @@ bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) return true; } + +void MWWorld::InventoryStore::setSelectedEnchantItem(const ContainerStoreIterator& iterator) +{ + mSelectedEnchantItem = iterator; +} + +MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem() +{ + return mSelectedEnchantItem; +} diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index dcfb21f30..45b3cab26 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -50,6 +50,9 @@ namespace MWWorld mutable TSlots mSlots; + // selected magic item (for using enchantments of type "Cast once" or "Cast when used") + ContainerStoreIterator mSelectedEnchantItem; + void copySlots (const InventoryStore& store); void initSlots (TSlots& slots); @@ -63,7 +66,15 @@ namespace MWWorld InventoryStore& operator= (const InventoryStore& store); void equip (int slot, const ContainerStoreIterator& iterator); - ///< \note \a iteartor can be an end-iterator + ///< \note \a iterator can be an end-iterator + + void setSelectedEnchantItem(const ContainerStoreIterator& iterator); + ///< set the selected magic item (for using enchantments of type "Cast once" or "Cast when used") + /// \note to unset the selected item, call this method with end() iterator + + ContainerStoreIterator getSelectedEnchantItem(); + ///< @return selected magic item (for using enchantments of type "Cast once" or "Cast when used") + /// \note if no item selected, return end() iterator ContainerStoreIterator getSlot (int slot); diff --git a/files/mygui/openmw_spell_window_layout.xml b/files/mygui/openmw_spell_window_layout.xml index 66a685c38..d489f41b8 100644 --- a/files/mygui/openmw_spell_window_layout.xml +++ b/files/mygui/openmw_spell_window_layout.xml @@ -12,6 +12,7 @@ + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index bfa970de5..e29483e35 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -99,6 +99,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 48ba293e88febaed2d0efaca9fac7c5f5eeaac83 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 15:13:44 +0200 Subject: [PATCH 221/289] added the success formula, and spell deleting (shift+click) --- apps/openmw/mwgui/spellwindow.cpp | 83 ++++++++++++++++++++---- apps/openmw/mwgui/spellwindow.hpp | 7 +- apps/openmw/mwmechanics/spellsuccess.hpp | 83 ++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 apps/openmw/mwmechanics/spellsuccess.hpp diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index f761e00db..168578831 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -9,10 +10,12 @@ #include "../mwbase/environment.hpp" #include "../mwmechanics/spells.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellsuccess.hpp" #include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "inventorywindow.hpp" +#include "confirmationdialog.hpp" namespace { @@ -175,6 +178,7 @@ namespace MWGui t->setTextAlign(MyGUI::Align::Left); t->setUserString("ToolTipType", "Spell"); t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); if (*it == selectedSpell) @@ -194,18 +198,19 @@ namespace MWGui t->setTextAlign(MyGUI::Align::Left); t->setUserString("ToolTipType", "Spell"); t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); - - if (*it == selectedSpell) - t->setStateSelected(true); + t->setStateSelected(*it == selectedSpell); // cost / success chance - MyGUI::TextBox* costChance = mSpellView->createWidget("SpellText", + MyGUI::Button* costChance = mSpellView->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); std::string cost = boost::lexical_cast(spell->data.cost); - costChance->setCaption(cost + "/" + "100"); /// \todo + std::string chance = boost::lexical_cast(int(MWMechanics::getSpellSuccessChance(*it, player))); + costChance->setCaption(cost + "/" + chance); costChance->setTextAlign(MyGUI::Align::Right); costChance->setNeedMouseFocus(false); + costChance->setStateSelected(*it == selectedSpell); mHeight += spellHeight; @@ -219,6 +224,8 @@ namespace MWGui { MWWorld::Ptr item = *it; + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); + // check if the item is currently equipped (will display in a different color) bool equipped = false; for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) @@ -238,18 +245,26 @@ namespace MWGui t->setUserString("ToolTipType", "ItemPtr"); t->setUserString("Equipped", equipped ? "true" : "false"); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->setStateSelected(item == selectedItem); // cost / charge - MyGUI::TextBox* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::Button* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); - const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); std::string cost = boost::lexical_cast(enchant->data.cost); std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge + if (enchant->data.type != ESM::Enchantment::CastOnce) + { + // this is Morrowind behaviour + cost = "100"; + charge = "100"; + } + costCharge->setCaption(cost + "/" + charge); costCharge->setTextAlign(MyGUI::Align::Right); costCharge->setNeedMouseFocus(false); + costCharge->setStateSelected(item == selectedItem); mHeight += spellHeight; } @@ -312,8 +327,9 @@ namespace MWGui } assert(it != store.end()); - // equip, if it is not already equipped - if (_sender->getUserString("Equipped") == "false") + // equip, if it can be equipped and is not already equipped + if (_sender->getUserString("Equipped") == "false" + && !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) { // sound MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0); @@ -324,7 +340,6 @@ namespace MWGui // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) @@ -362,8 +377,33 @@ namespace MWGui MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); MWMechanics::Spells& spells = stats.mSpells; - spells.setSelectedSpell(_sender->getUserString("Spell")); - store.setSelectedEnchantItem(store.end()); + if (MyGUI::InputManager::getInstance().isShiftPressed()) + { + // delete spell, if allowed + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(_sender->getUserString("Spell")); + if (spell->data.flags & ESM::Spell::F_Always + || spell->data.type == ESM::Spell::ST_Power) + { + mWindowManager.messageBox("#{sDeleteSpellError}", std::vector()); + } + else + { + // ask for confirmation + mSpellToDelete = _sender->getUserString("Spell"); + ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); + question = boost::str(boost::format(question) % spell->name); + dialog->open(question); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept); + dialog->eventCancelClicked.clear(); + } + } + else + { + spells.setSelectedSpell(_sender->getUserString("Spell")); + store.setSelectedEnchantItem(store.end()); + } updateSpells(); } @@ -375,4 +415,23 @@ namespace MWGui height += numSpells * 18; return height; } + + void SpellWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) + { + if (mSpellView->getViewOffset().top + _rel*0.3 > 0) + mSpellView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mSpellView->setViewOffset(MyGUI::IntPoint(0, mSpellView->getViewOffset().top + _rel*0.3)); + } + + void SpellWindow::onDeleteSpellAccept() + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.mSpells; + + spells.remove(mSpellToDelete); + + updateSpells(); + } } diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 16a1c7ff8..87e4783ba 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -19,14 +19,19 @@ namespace MWGui int mHeight; int mWidth; + std::string mSpellToDelete; + void addGroup(const std::string& label, const std::string& label2); int estimateHeight(int numSpells) const; - virtual void onPinToggled(); void onWindowResize(MyGUI::Window* _sender); void onEnchantedItemSelected(MyGUI::Widget* _sender); void onSpellSelected(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onDeleteSpellAccept(); + + virtual void onPinToggled(); virtual void open(); }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp new file mode 100644 index 000000000..532f9eb4e --- /dev/null +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -0,0 +1,83 @@ +#ifndef MWMECHANICS_SPELLSUCCESS_H +#define MWMECHANICS_SPELLSUCCESS_H + +#include "../mwworld/ptr.hpp" +#include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + +#include "npcstats.hpp" + +namespace MWMechanics +{ + // UESP wiki / Morrowind/Spells: + // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 + + /** + * @param spellId ID of spell + * @param actor calculate spell success chance for this actor (depends on actor's skills) + * @attention actor has to be an NPC and not a creature! + * @return success chance from 0 to 100 (in percent) + */ + float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + + if (spell->data.flags & ESM::Spell::F_Always) // spells with this flag always succeed (usually birthsign spells) + return 100.0; + + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); + CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); + + std::map schoolSkillMap; // maps spell school to skill id + schoolSkillMap[0] = 11; // alteration + schoolSkillMap[1] = 13; // conjuration + schoolSkillMap[3] = 12; // illusion + schoolSkillMap[2] = 10; // destruction + schoolSkillMap[4] = 14; // mysticism + schoolSkillMap[5] = 15; // restoration + + // determine the spell's school + // this is always the school where the player's respective skill is the least advanced + // out of all the magic effects' schools + const std::vector& effects = spell->effects.list; + int skill = -1; + int skillLevel = -1; + for (std::vector::const_iterator it = effects.begin(); + it != effects.end(); ++it) + { + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->effectID); + int school = effect->data.school; + assert(schoolSkillMap.find(school) != schoolSkillMap.end()); + int _skillLevel = stats.mSkill[schoolSkillMap[school]].getModified(); + + if (skill == -1) + { + skill = schoolSkillMap[school]; + skillLevel = _skillLevel; + } + else if (_skillLevel < skillLevel) + { + skill = schoolSkillMap[school]; + skillLevel = _skillLevel; + } + } + + // Sound magic effect (reduces spell casting chance) + int soundMagnitude = creatureStats.mMagicEffects.get (MWMechanics::EffectKey (48)).mMagnitude; + + int willpower = creatureStats.mAttributes[ESM::Attribute::Willpower].getModified(); + int luck = creatureStats.mAttributes[ESM::Attribute::Luck].getModified(); + int currentFatigue = creatureStats.mDynamic[2].getCurrent(); + int maxFatigue = creatureStats.mDynamic[2].getModified(); + int spellCost = spell->data.cost; + + // There we go, all needed variables are there, lets go + float chance = (float(skillLevel * 2) + float(willpower)/5.0 + float(luck)/ 10.0 - spellCost - soundMagnitude) * (float(currentFatigue + maxFatigue * 1.5)) / float(maxFatigue * 2.0); + + chance = std::max(0.0f, std::min(100.0f, chance)); // clamp to 0 .. 100 + + return chance; + } +} + +#endif From 8b7baa808e719663f65e4ba08c80f416ac0e45bc Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 15:36:48 +0200 Subject: [PATCH 222/289] fixed the hud icon positioning issues --- apps/openmw/mwgui/hud.cpp | 17 +++++++++++------ apps/openmw/mwgui/hud.hpp | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index fdd1c8821..6b0cdbd5c 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -48,11 +48,12 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setCoord(0,0, width, height); // Energy bars + getWidget(mHealthFrame, "HealthFrame"); getWidget(health, "Health"); getWidget(magicka, "Magicka"); getWidget(stamina, "Stamina"); - hmsBaseLeft = health->getLeft(); + hmsBaseLeft = mHealthFrame->getLeft(); MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame; getWidget(healthFrame, "HealthFrame"); @@ -62,6 +63,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Item and spell images and status bars getWidget(weapBox, "WeapBox"); getWidget(weapImage, "WeapImage"); @@ -77,11 +80,11 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(effectBox, "EffectBox"); getWidget(effect1, "Effect1"); - effectBoxBaseRight = effectBox->getRight(); + effectBoxBaseRight = viewSize.width - effectBox->getRight(); effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(minimapBox, "MiniMapBox"); - minimapBoxBaseRight = minimapBox->getRight(); + minimapBoxBaseRight = viewSize.width - minimapBox->getRight(); minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); @@ -220,7 +223,7 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft; if (!weapVisible) - spellDx -= spellBoxBaseLeft - weapBoxBaseLeft; + spellDx += spellBoxBaseLeft - weapBoxBaseLeft; health->setVisible(hmsVisible); stamina->setVisible(hmsVisible); @@ -233,14 +236,16 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible) { + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // effect box can have variable width -> variable left coordinate int effectsDx = 0; if (!minimapBoxVisible) - effectsDx = minimapBoxBaseRight - effectBoxBaseRight; + effectsDx = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight); mMapVisible = minimapBoxVisible; minimapBox->setVisible(minimapBoxVisible); - effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop()); + effectBox->setPosition((viewSize.width - effectBoxBaseRight) - effectBox->getWidth() + effectsDx, effectBox->getTop()); effectBox->setVisible(effectBoxVisible); } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 16749114c..6d4bf0559 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -31,6 +31,7 @@ namespace MWGui void setCellName(const std::string& cellName); MyGUI::ProgressPtr health, magicka, stamina; + MyGUI::Widget* mHealthFrame; MyGUI::Widget *weapBox, *spellBox; MyGUI::ImageBox *weapImage, *spellImage; MyGUI::ProgressPtr weapStatus, spellStatus; From 298ae4f7f8c8cde5d689c3b5013854f95a183493 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 18:33:01 +0200 Subject: [PATCH 223/289] HUD icons for selected weapon / selected spell / selected enchanted item --- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 171 +++++++++++++++++++---- apps/openmw/mwgui/hud.hpp | 16 ++- apps/openmw/mwgui/inventorywindow.cpp | 18 +++ apps/openmw/mwgui/spellwindow.cpp | 17 ++- apps/openmw/mwgui/tooltips.cpp | 1 - apps/openmw/mwgui/tradewindow.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 25 ++++ apps/openmw/mwgui/window_manager.hpp | 6 + apps/openmw/mwmechanics/spellsuccess.hpp | 66 +++++---- files/mygui/openmw_hud_layout.xml | 8 ++ 11 files changed, 270 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 33ee8bf49..bf6b4add0 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -347,7 +347,6 @@ void ContainerBase::setFilter(ContainerBase::Filter filter) void ContainerBase::openContainer(MWWorld::Ptr container) { mPtr = container; - drawItems(); } void ContainerBase::drawItems() @@ -638,6 +637,7 @@ void ContainerWindow::open(MWWorld::Ptr container) { openContainer(container); setTitle(MWWorld::Class::get(container).getName(container)); + drawItems(); } void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 6b0cdbd5c..95017579b 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -90,6 +90,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(compass, "Compass"); getWidget(mCellNameBox, "CellName"); + getWidget(mWeaponSpellBox, "WeaponSpellName"); getWidget(crosshair, "Crosshair"); @@ -98,14 +99,11 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(trianglecounter, "TriangleCounter"); getWidget(batchcounter, "BatchCounter"); - // These are just demo values, you should replace these with - // real calls from outside the class later. - setWeapIcon("icons\\w\\tx_knife_iron.dds"); - setWeapStatus(90, 100); - setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); - setSpellStatus(65, 100); setEffect("icons\\s\\tx_s_chameleon.dds"); + unsetSelectedSpell(); + unsetSelectedWeapon(); + LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); @@ -153,28 +151,6 @@ void HUD::setBatchCount(size_t count) batchcounter->setCaption(boost::lexical_cast(count)); } -void HUD::setWeapIcon(const char *str) -{ - weapImage->setImageTexture(str); -} - -void HUD::setSpellIcon(const char *str) -{ - spellImage->setImageTexture(str); -} - -void HUD::setWeapStatus(int s, int smax) -{ - weapStatus->setProgressRange(smax); - weapStatus->setProgressPosition(s); -} - -void HUD::setSpellStatus(int s, int smax) -{ - spellStatus->setProgressRange(smax); - spellStatus->setProgressPosition(s); -} - void HUD::setEffect(const char *img) { effect1->setImageTexture(img); @@ -354,11 +330,150 @@ void HUD::setCellName(const std::string& cellName) void HUD::onFrame(float dt) { mCellNameTimer -= dt; + mWeaponSpellTimer -= dt; if (mCellNameTimer < 0) mCellNameBox->setVisible(false); + if (mWeaponSpellTimer < 0) + mWeaponSpellBox->setVisible(false); } void HUD::onResChange(int width, int height) { setCoord(0, 0, width, height); } + +void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) +{ + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + std::string spellName = spell->name; + if (spellName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = spellName; + mWeaponSpellBox->setCaption(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(successChancePercent); + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + + spellBox->setUserString("ToolTipType", "Spell"); + spellBox->setUserString("Spell", spellId); + + // use the icon of the first effect + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->effects.list.front().effectID); + std::string icon = effect->icon; + int slashPos = icon.find("\\"); + icon.insert(slashPos+1, "b_"); + icon = std::string("icons\\") + icon; + Widgets::fixTexturePath(icon); + spellImage->setImageTexture(icon); +} + +void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) +{ + std::string itemName = MWWorld::Class::get(item).getName(item); + if (itemName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = itemName; + mWeaponSpellBox->setCaption(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(chargePercent); + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + + spellBox->setUserString("ToolTipType", "ItemPtr"); + spellBox->setUserData(item); + + spellImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); + MyGUI::ImageBox* itemBox = spellImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) + , MyGUI::Align::Stretch); + + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(item).getInventoryIcon(item); + Widgets::fixTexturePath(path); + itemBox->setImageTexture(path); + itemBox->setNeedMouseFocus(false); +} + +void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) +{ + std::string itemName = MWWorld::Class::get(item).getName(item); + if (itemName != mWeaponName) + { + mWeaponSpellTimer = 5.0f; + mWeaponName = itemName; + mWeaponSpellBox->setCaption(mWeaponName); + mWeaponSpellBox->setVisible(true); + } + + weapBox->setUserString("ToolTipType", "ItemPtr"); + weapBox->setUserData(item); + + weapStatus->setProgressRange(100); + weapStatus->setProgressPosition(durabilityPercent); + + if (weapImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0)); + + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(item).getInventoryIcon(item); + Widgets::fixTexturePath(path); + + if (MWWorld::Class::get(item).getEnchantment(item) != "") + { + weapImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); + MyGUI::ImageBox* itemBox = weapImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) + , MyGUI::Align::Stretch); + itemBox->setImageTexture(path); + itemBox->setNeedMouseFocus(false); + } + else + weapImage->setImageTexture(path); +} + +void HUD::unsetSelectedSpell() +{ + std::string spellName = "#{sNone}"; + if (spellName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = spellName; + mWeaponSpellBox->setCaptionWithReplacing(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(0); + spellImage->setImageTexture(""); + spellBox->clearUserStrings(); +} + +void HUD::unsetSelectedWeapon() +{ + std::string itemName = "#{sSkillHandtohand}"; + if (itemName != mWeaponName) + { + mWeaponSpellTimer = 5.0f; + mWeaponName = itemName; + mWeaponSpellBox->setCaptionWithReplacing(mWeaponName); + mWeaponSpellBox->setVisible(true); + } + + if (weapImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0)); + weapStatus->setProgressRange(100); + weapStatus->setProgressPosition(0); + weapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); + weapBox->clearUserStrings(); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 6d4bf0559..f51110637 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -3,6 +3,7 @@ #include #include "../mwmechanics/stat.hpp" +#include "../mwworld/ptr.hpp" namespace MWGui { @@ -12,10 +13,6 @@ namespace MWGui { public: HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); - void setWeapIcon(const char *str); - void setSpellIcon(const char *str); - void setWeapStatus(int s, int smax); - void setSpellStatus(int s, int smax); void setEffect(const char *img); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); void setFPS(float fps); @@ -25,6 +22,12 @@ namespace MWGui void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); + void setSelectedSpell(const std::string& spellId, int successChancePercent); + void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); + void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + void unsetSelectedSpell(); + void unsetSelectedWeapon(); + void onFrame(float dt); void onResChange(int width, int height); @@ -41,6 +44,7 @@ namespace MWGui MyGUI::ImageBox* compass; MyGUI::ImageBox* crosshair; MyGUI::TextBox* mCellNameBox; + MyGUI::TextBox* mWeaponSpellBox; MyGUI::WidgetPtr fpsbox; MyGUI::TextBox* fpscounter; @@ -58,6 +62,10 @@ namespace MWGui std::string mCellName; float mCellNameTimer; + std::string mWeaponName; + std::string mSpellName; + float mWeaponSpellTimer; + bool mMapVisible; void onWorldClicked(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e1d4cc998..103f5ebf3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -188,6 +188,15 @@ namespace MWGui mWindowManager.setDragDrop(false); drawItems(); + + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } } @@ -266,5 +275,14 @@ namespace MWGui // update the spell window just in case new enchanted items were added to inventory if (mWindowManager.getSpellWindow()) mWindowManager.getSpellWindow()->updateSpells(); + + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 168578831..aae3d878d 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -110,6 +110,8 @@ namespace MWGui if (!allowSelectedItem) { store.setSelectedEnchantItem(store.end()); + spells.setSelectedSpell(""); + mWindowManager.unsetSelectedSpell(); selectedItem = MWWorld::Ptr(); } } @@ -366,12 +368,14 @@ namespace MWGui store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); + mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge % updateSpells(); } void SpellWindow::onSpellSelected(MyGUI::Widget* _sender) { + std::string spellId = _sender->getUserString("Spell"); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); @@ -380,7 +384,7 @@ namespace MWGui if (MyGUI::InputManager::getInstance().isShiftPressed()) { // delete spell, if allowed - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(_sender->getUserString("Spell")); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); if (spell->data.flags & ESM::Spell::F_Always || spell->data.type == ESM::Spell::ST_Power) { @@ -389,7 +393,7 @@ namespace MWGui else { // ask for confirmation - mSpellToDelete = _sender->getUserString("Spell"); + mSpellToDelete = spellId; ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); question = boost::str(boost::format(question) % spell->name); @@ -401,8 +405,9 @@ namespace MWGui } else { - spells.setSelectedSpell(_sender->getUserString("Spell")); + spells.setSelectedSpell(spellId); store.setSelectedEnchantItem(store.end()); + mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); } updateSpells(); @@ -430,6 +435,12 @@ namespace MWGui MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWMechanics::Spells& spells = stats.mSpells; + if (spells.getSelectedSpell() == mSpellToDelete) + { + spells.setSelectedSpell(""); + mWindowManager.unsetSelectedSpell(); + } + spells.remove(mSpellToDelete); updateSpells(); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index dc34ee86c..0f6892190 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -402,7 +402,6 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) TextBox* chargeText = enchantArea->createWidget("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText"); chargeText->setCaption(store.gameSettings.search("sCharges")->str); - chargeText->setProperty("Static", "true"); const int chargeTextWidth = chargeText->getTextSize().width + 5; const int chargeAndTextWidth = chargeWidth + chargeTextWidth; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 0a12a82a0..2089ed4af 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -104,6 +104,8 @@ namespace MWGui ContainerBase::openContainer(actor); updateLabels(); + + drawItems(); } void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4eaaf72a4..bd1ad46b6 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -674,3 +674,28 @@ void WindowManager::removeGuiMode(GuiMode mode) updateVisible(); } + +void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) +{ + hud->setSelectedSpell(spellId, successChancePercent); +} + +void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) +{ + hud->setSelectedEnchantItem(item, chargePercent); +} + +void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) +{ + hud->setSelectedWeapon(item, durabilityPercent); +} + +void WindowManager::unsetSelectedSpell() +{ + hud->unsetSelectedSpell(); +} + +void WindowManager::unsetSelectedWeapon() +{ + hud->unsetSelectedWeapon(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 2a7794f70..037022b42 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -204,6 +204,12 @@ namespace MWGui void setWeaponVisibility(bool visible); void setSpellVisibility(bool visible); + void setSelectedSpell(const std::string& spellId, int successChancePercent); + void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); + void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + void unsetSelectedSpell(); + void unsetSelectedWeapon(); + template void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index 532f9eb4e..11ac7cda7 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -4,30 +4,14 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "npcstats.hpp" namespace MWMechanics { - // UESP wiki / Morrowind/Spells: - // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 - - /** - * @param spellId ID of spell - * @param actor calculate spell success chance for this actor (depends on actor's skills) - * @attention actor has to be an NPC and not a creature! - * @return success chance from 0 to 100 (in percent) - */ - float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + inline int spellSchoolToSkill(int school) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - - if (spell->data.flags & ESM::Spell::F_Always) // spells with this flag always succeed (usually birthsign spells) - return 100.0; - - NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); - CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); - std::map schoolSkillMap; // maps spell school to skill id schoolSkillMap[0] = 11; // alteration schoolSkillMap[1] = 13; // conjuration @@ -35,33 +19,65 @@ namespace MWMechanics schoolSkillMap[2] = 10; // destruction schoolSkillMap[4] = 14; // mysticism schoolSkillMap[5] = 15; // restoration + assert(schoolSkillMap.find(school) != schoolSkillMap.end()); + return schoolSkillMap[school]; + } + + inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); // determine the spell's school // this is always the school where the player's respective skill is the least advanced // out of all the magic effects' schools const std::vector& effects = spell->effects.list; - int skill = -1; + int school = -1; int skillLevel = -1; for (std::vector::const_iterator it = effects.begin(); it != effects.end(); ++it) { const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->effectID); - int school = effect->data.school; - assert(schoolSkillMap.find(school) != schoolSkillMap.end()); - int _skillLevel = stats.mSkill[schoolSkillMap[school]].getModified(); + int _school = effect->data.school; + int _skillLevel = stats.mSkill[spellSchoolToSkill(_school)].getModified(); - if (skill == -1) + if (school == -1) { - skill = schoolSkillMap[school]; + school = _school; skillLevel = _skillLevel; } else if (_skillLevel < skillLevel) { - skill = schoolSkillMap[school]; + school = _school; skillLevel = _skillLevel; } } + return school; + } + + + // UESP wiki / Morrowind/Spells: + // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 + /** + * @param spellId ID of spell + * @param actor calculate spell success chance for this actor (depends on actor's skills) + * @attention actor has to be an NPC and not a creature! + * @return success chance from 0 to 100 (in percent) + */ + inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + + if (spell->data.flags & ESM::Spell::F_Always // spells with this flag always succeed (usually birthsign spells) + || spell->data.type == ESM::Spell::ST_Power) // powers always succeed, but can be cast only once per day + return 100.0; + + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); + CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); + + int skillLevel = stats.mSkill[getSpellSchool(spellId, actor)].getModified(); + // Sound magic effect (reduces spell casting chance) int soundMagnitude = creatureStats.mMagicEffects.get (MWMechanics::EffectKey (48)).mMagnitude; diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index d0026bf25..cf353a205 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -28,6 +28,14 @@ + + + + + + + + From c5a685d11fead58106c62c30acb18f74c5f84f3e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 18:59:11 +0200 Subject: [PATCH 224/289] addition to last commit: show the selected weapon/spell names as inventory/spell window caption --- apps/openmw/mwgui/hud.cpp | 20 ++++++++++++-------- apps/openmw/mwgui/hud.hpp | 2 ++ apps/openmw/mwgui/spellwindow.cpp | 1 + apps/openmw/mwgui/window_manager.cpp | 9 +++++++++ libs/openengine/gui/layout.hpp | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 95017579b..14212c2f9 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -44,6 +44,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mCellNameTimer(0.0f) , mCellNameBox(NULL) , mMapVisible(true) + , mWeaponVisible(true) + , mSpellVisible(true) { setCoord(0,0, width, height); @@ -101,9 +103,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setEffect("icons\\s\\tx_s_chameleon.dds"); - unsetSelectedSpell(); - unsetSelectedWeapon(); - LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); @@ -201,6 +200,11 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV if (!weapVisible) spellDx += spellBoxBaseLeft - weapBoxBaseLeft; + mWeaponVisible = weapVisible; + mSpellVisible = spellVisible; + if (!mWeaponVisible && !mSpellVisible) + mWeaponSpellBox->setVisible(false); + health->setVisible(hmsVisible); stamina->setVisible(hmsVisible); magicka->setVisible(hmsVisible); @@ -346,7 +350,7 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); std::string spellName = spell->name; - if (spellName != mSpellName) + if (spellName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = spellName; @@ -376,7 +380,7 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) { std::string itemName = MWWorld::Class::get(item).getName(item); - if (itemName != mSpellName) + if (itemName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = itemName; @@ -407,7 +411,7 @@ void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) { std::string itemName = MWWorld::Class::get(item).getName(item); - if (itemName != mWeaponName) + if (itemName != mWeaponName && mWeaponVisible) { mWeaponSpellTimer = 5.0f; mWeaponName = itemName; @@ -443,7 +447,7 @@ void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) void HUD::unsetSelectedSpell() { std::string spellName = "#{sNone}"; - if (spellName != mSpellName) + if (spellName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = spellName; @@ -462,7 +466,7 @@ void HUD::unsetSelectedSpell() void HUD::unsetSelectedWeapon() { std::string itemName = "#{sSkillHandtohand}"; - if (itemName != mWeaponName) + if (itemName != mWeaponName && mWeaponVisible) { mWeaponSpellTimer = 5.0f; mWeaponName = itemName; diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index f51110637..47bd93eef 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -67,6 +67,8 @@ namespace MWGui float mWeaponSpellTimer; bool mMapVisible; + bool mWeaponVisible; + bool mSpellVisible; void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index aae3d878d..04338aa11 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -47,6 +47,7 @@ namespace MWGui getWidget(mEffectBox, "EffectsBox"); setCoord(498, 300, 302, 300); + updateSpells(); mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index bd1ad46b6..8ddbfe929 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -144,6 +144,9 @@ WindowManager::WindowManager( playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat())); } + unsetSelectedSpell(); + unsetSelectedWeapon(); + // Set up visibility updateVisible(); } @@ -678,24 +681,30 @@ void WindowManager::removeGuiMode(GuiMode mode) void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) { hud->setSelectedSpell(spellId, successChancePercent); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + mSpellWindow->setTitle(spell->name); } void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) { hud->setSelectedEnchantItem(item, chargePercent); + mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item)); } void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) { hud->setSelectedWeapon(item, durabilityPercent); + mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item)); } void WindowManager::unsetSelectedSpell() { hud->unsetSelectedSpell(); + mSpellWindow->setTitle("#{sNone}"); } void WindowManager::unsetSelectedWeapon() { hud->unsetSelectedWeapon(); + mInventoryWindow->setTitle("#{sSkillHandtohand}"); } diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index d9eefe051..e6feb3d0e 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -118,7 +118,7 @@ namespace GUI void setTitle(const std::string& title) { // NOTE: this assume that mMainWidget is of type Window. - static_cast(mMainWidget)->setCaption(title); + static_cast(mMainWidget)->setCaptionWithReplacing(title); adjustWindowCaption(); } From 72bb7a2d2c987e97c65e11d8f79b89e0b546bf2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 08:04:07 +0200 Subject: [PATCH 225/289] fix a typo --- apps/openmw/mwgui/spellwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 04338aa11..502754feb 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -257,7 +257,7 @@ namespace MWGui std::string cost = boost::lexical_cast(enchant->data.cost); std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge - if (enchant->data.type != ESM::Enchantment::CastOnce) + if (enchant->data.type == ESM::Enchantment::CastOnce) { // this is Morrowind behaviour cost = "100"; From 2c90654401aff4de56c057130fb9e917c2721b86 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 09:21:41 +0200 Subject: [PATCH 226/289] fix a typo that caused a crash when trying to disable an already disabled object --- apps/openmw/mwworld/refdata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 528f49c33..e1c14b907 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -123,7 +123,7 @@ namespace MWWorld void RefData::disable() { - mEnabled = true; + mEnabled = false; } ESM::Position& RefData::getPosition() From 36d26e0681260005843ae7bdd63c366157aef310 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 15:52:39 +0200 Subject: [PATCH 227/289] set the camera orientation after using teleport doors --- apps/openmw/mwrender/player.cpp | 18 ++++++++++++++++++ apps/openmw/mwrender/player.hpp | 3 +++ apps/openmw/mwworld/player.cpp | 5 +++++ apps/openmw/mwworld/player.hpp | 3 +++ apps/openmw/mwworld/scene.cpp | 5 ++++- 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 7ed921218..d6baac4b5 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -6,4 +6,22 @@ namespace MWRender Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) : mCamera (camera), mNode (node) {} + + void Player::setRot(float x, float y, float z) + { + Ogre::SceneNode *sceneNode = mNode; + Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); + Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); + + // we are only interested in X and Y rotation + + // Rotate around X axis + Ogre::Quaternion xr(Ogre::Radian(x), Ogre::Vector3::UNIT_X); + + // Rotate around Y axis + Ogre::Quaternion yr(Ogre::Radian(-z), Ogre::Vector3::UNIT_Y); + + pitchNode->setOrientation(xr); + yawNode->setOrientation(yr); + } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 4306b8a95..406bedb0a 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -23,6 +23,9 @@ namespace MWRender Ogre::Camera *getCamera() { return mCamera; } + /// Set where the player is looking at. Uses Morrowind (euler) angles + void setRot(float x, float y, float z); + std::string getHandle() const { return mNode->getName(); } Ogre::SceneNode* getNode() {return mNode;} }; diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b1483ff8..91b030d1c 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -40,6 +40,11 @@ namespace MWWorld mWorld.moveObject (getPlayer(), x, y, z); } + void Player::setRot(float x, float y, float z) + { + mRenderer->setRot(x, y, z); + } + void Player::setClass (const ESM::Class& class_) { ESM::Class *new_class = new ESM::Class (class_); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index e199f17e9..166d4cfee 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -42,6 +42,9 @@ namespace MWWorld /// Set the player position. Uses Morrowind coordinates. void setPos(float x, float y, float z); + /// Set where the player is looking at. Uses Morrowind (euler) angles + void setRot(float x, float y, float z); + void setCell (MWWorld::Ptr::CellStore *cellStore) { mCellStore = cellStore; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 47238ee71..a47137d25 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -145,10 +145,13 @@ namespace MWWorld bool hasWater = cell->cell->data.flags & cell->cell->HasWater; mPhysics->setCurrentWater(hasWater, cell->cell->water); if (adjustPlayerPos) + { mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]); + mWorld->getPlayer().setRot (position.rot[0], position.rot[1], position.rot[2]); + } mWorld->getPlayer().setCell (cell); - // TODO orientation + MWBase::Environment::get().getMechanicsManager()->addActor (mWorld->getPlayer().getPlayer()); MWBase::Environment::get().getMechanicsManager()->watchActor (mWorld->getPlayer().getPlayer()); From fbaedd2c3a4cccb7d0ea7ab595286ad851584244 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 16:20:35 +0200 Subject: [PATCH 228/289] new underwater colors --- files/water/underwater.cg | 20 ++++++++++---------- files/water/water.cg | 4 ++-- files/water/water.material | 2 -- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/files/water/underwater.cg b/files/water/underwater.cg index b853dd535..829d34347 100644 --- a/files/water/underwater.cg +++ b/files/water/underwater.cg @@ -28,14 +28,15 @@ float4 main_fp_nomrt (float2 iTexCoord : TEXCOORD0, float3 noiseCoord : TEXCOORD1, uniform sampler2D RT : register(s0), uniform sampler2D NormalMap : register(s1), - uniform sampler2D CausticMap : register(s2), - uniform float4 tintColour) : COLOR + uniform sampler2D CausticMap : register(s2)) : COLOR { float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; - return tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5) + - tintColour ; + float4 col = tex2D(RT, iTexCoord + normal.xy * 0.015) + + (tex2D(CausticMap, noiseCoord) / 5); + col.xyz = lerp(col.xyz, float3(0.15, 0.40, 0.40), 0.4); + return col; + } @@ -45,8 +46,7 @@ float4 main_fp (float2 iTexCoord : TEXCOORD0, uniform sampler2D RT : register(s0), uniform sampler2D NormalMap : register(s1), uniform sampler2D CausticMap : register(s2), - uniform sampler2D DepthMap : register(s3), - uniform float4 tintColour) : COLOR + uniform sampler2D DepthMap : register(s3)) : COLOR { float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; @@ -54,8 +54,8 @@ float4 main_fp (float2 iTexCoord : TEXCOORD0, depth = saturate(depth / 2000.f); float4 color = tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5) + - tintColour; + (tex2D(CausticMap, noiseCoord) / 5); + color.xyz = lerp(color.xyz, float3(0.15, 0.40, 0.40), 0.4); - return lerp(color, float4(0, 0.65, 0.65, 1), depth); + return lerp(color, float4(0.15, 0.40, 0.40, 1), depth); } diff --git a/files/water/water.cg b/files/water/water.cg index bf6d04c5c..ad0ff57f7 100644 --- a/files/water/water.cg +++ b/files/water/water.cg @@ -112,8 +112,8 @@ void main_fp oColor.xyz = lerp(refraction.xyz, reflection.xyz, opacity); - oColor.xyz += isUnderwater * float3(0, 0.35, 0.35); // underwater tint color - oColor.xyz = lerp(oColor.xyz, float3(0, 0.65, 0.65), saturate(isUnderwater * (iDepth / 2000.f))); // underwater fog + oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), isUnderwater*0.6); // underwater tint color + oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), saturate(isUnderwater * (iDepth / 2000.f))); // underwater fog // add fog //float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); diff --git a/files/water/water.material b/files/water/water.material index a2a6b3e2d..d1f7fcf49 100644 --- a/files/water/water.material +++ b/files/water/water.material @@ -151,7 +151,6 @@ material Water/CompositorNoMRT fragment_program_ref UnderwaterEffectFP_NoMRT { - param_named tintColour float4 0 0.35 0.35 1 } texture_unit RT @@ -194,7 +193,6 @@ material Water/Compositor fragment_program_ref UnderwaterEffectFP { - param_named tintColour float4 0 0.35 0.35 1 param_named_auto far far_clip_distance } From a9a582f858ef272f048bcdcb96934ea1e1a53573 Mon Sep 17 00:00:00 2001 From: Edmondo Tommasina Date: Wed, 30 May 2012 23:18:59 +0200 Subject: [PATCH 229/289] renderer.cpp: fix std::runtime_error compile error --- libs/openengine/ogre/renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index b525e76e3..a5eca76ed 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -10,6 +10,7 @@ #include "OgreHardwarePixelBuffer.h" #include +#include using namespace Ogre; using namespace OEngine::Render; From 0ba0b2122e3ac3505d2b90a82784cd13fd3d48aa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 12:25:24 +0200 Subject: [PATCH 230/289] set the implicit object for script excution by clicking on it --- apps/openmw/mwgui/console.cpp | 12 +- apps/openmw/mwgui/console.hpp | 16 +- apps/openmw/mwgui/hud.cpp | 32 ++- apps/openmw/mwgui/hud.hpp | 4 + apps/openmw/mwgui/tooltips.cpp | 297 ++++++++++++++------------ apps/openmw/mwgui/window_manager.cpp | 23 ++ apps/openmw/mwgui/window_manager.hpp | 4 + apps/openmw/mwworld/physicssystem.cpp | 26 ++- apps/openmw/mwworld/physicssystem.hpp | 3 + apps/openmw/mwworld/world.cpp | 30 ++- 10 files changed, 308 insertions(+), 139 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index bf80a77b2..c9ba752e9 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -240,7 +240,7 @@ namespace MWGui { try { - ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr()); + ConsoleInterpreterContext interpreterContext (*this, mPtr); Interpreter::Interpreter interpreter; MWScript::installOpcodes (interpreter); std::vector code; @@ -375,4 +375,14 @@ namespace MWGui { setCoord(10,10, width-10, height/2); } + + void Console::setSelectedObject(const MWWorld::Ptr& object) + { + mPtr = object; + } + + void Console::onReferenceUnavailable() + { + mPtr = MWWorld::Ptr(); + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 117285847..eadf4aa4e 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -16,9 +16,11 @@ #include "../mwscript/compilercontext.hpp" #include "../mwscript/interpretercontext.hpp" +#include "referenceinterface.hpp" + namespace MWGui { - class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler + class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler, public ReferenceInterface { private: @@ -39,7 +41,17 @@ namespace MWGui /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same /// time). - public: + public: + + void setSelectedObject(const MWWorld::Ptr& object); + ///< Set the implicit object for script execution + + protected: + + virtual void onReferenceUnavailable(); + + + public: MyGUI::EditPtr command; MyGUI::EditPtr history; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 14212c2f9..2f275cd33 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -14,6 +14,7 @@ #include "window_manager.hpp" #include "container.hpp" +#include "console.hpp" using namespace MWGui; @@ -46,6 +47,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mMapVisible(true) , mWeaponVisible(true) , mSpellVisible(true) + , mWorldMouseOver(false) { setCoord(0,0, width, height); @@ -265,12 +267,39 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getWindowManager()->setDragDrop(false); } + else + { + GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); + + if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) + return; + + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + MWWorld::Ptr object; + try + { + object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + if (mode == GM_Console) + MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); + else if (mode == GM_Console || GM_Inventory) + { + // pick up object + } + } } void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) { if (mDragAndDrop->mIsOnDragAndDrop) { + mWorldMouseOver = false; + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); float mouseX = cursorPosition.left / float(viewSize.width); @@ -290,13 +319,14 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) else { MyGUI::PointerManager::getInstance().setPointer("arrow"); - /// \todo make it possible to pick up objects with the mouse, if inventory or container window is open + mWorldMouseOver = true; } } void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { MyGUI::PointerManager::getInstance().setPointer("arrow"); + mWorldMouseOver = false; } void HUD::onHMSClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 47bd93eef..0bfe5c20f 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -33,6 +33,8 @@ namespace MWGui void setCellName(const std::string& cellName); + bool getWorldMouseOver() { return mWorldMouseOver; } + MyGUI::ProgressPtr health, magicka, stamina; MyGUI::Widget* mHealthFrame; MyGUI::Widget *weapBox, *spellBox; @@ -70,6 +72,8 @@ namespace MWGui bool mWeaponVisible; bool mSpellVisible; + bool mWorldMouseOver; + void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 0f6892190..1f614d56b 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -67,158 +67,193 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); - const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mousePos == lastPressed) // mouseclick makes tooltip disappear - return; - - if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) + if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console) + || (mWindowManager->getMode() == GM_Container) + || (mWindowManager->getMode() == GM_Inventory))) { - mRemainingDelay -= frameDuration; + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + try + { + mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + MyGUI::IntSize tooltipSize = getToolTipViaPtr(true); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); } + else { - mRemainingDelay = mDelay; - } - mLastMouseX = mousePos.left; - mLastMouseY = mousePos.top; + const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mRemainingDelay > 0) - return; - - Widget* focus = InputManager::getInstance().getMouseFocusWidget(); - if (focus == 0) - { - return; - } - - IntSize tooltipSize; - - // try to go 1 level up until there is a widget that has tooltip - // this is necessary because some skin elements are actually separate widgets - int i=0; - while (!focus->isUserString("ToolTipType")) - { - focus = focus->getParent(); - if (!focus) + if (mousePos == lastPressed) // mouseclick makes tooltip disappear return; - ++i; - } - std::string type = focus->getUserString("ToolTipType"); - std::string text = focus->getUserString("ToolTipText"); - - ToolTipInfo info; - if (type == "") - { - return; - } - else if (type == "ItemPtr") - { - mFocusObject = *focus->getUserData(); - tooltipSize = getToolTipViaPtr(false); - } - else if (type == "Spell") - { - ToolTipInfo info; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); - info.caption = spell->name; - Widgets::SpellEffectList effects; - std::vector::const_iterator end = spell->effects.list.end(); - for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) { - Widgets::SpellEffectParams params; - params.mEffectID = it->effectID; - params.mSkill = it->skill; - params.mAttribute = it->attribute; - params.mDuration = it->duration; - params.mMagnMin = it->magnMin; - params.mMagnMax = it->magnMax; - params.mRange = it->range; - params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); - effects.push_back(params); - } - info.effects = effects; - tooltipSize = createToolTip(info); - } - else if (type == "Layout") - { - // tooltip defined in the layout - MyGUI::Widget* tooltip; - getWidget(tooltip, focus->getUserString("ToolTipLayout")); - - tooltip->setVisible(true); - if (!tooltip->isUserString("DontResize")) - { - tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping - - tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + mRemainingDelay -= frameDuration; } else - tooltipSize = tooltip->getSize(); - - std::map userStrings = focus->getUserStrings(); - for (std::map::iterator it = userStrings.begin(); - it != userStrings.end(); ++it) { - if (it->first == "ToolTipType" - || it->first == "ToolTipLayout") - continue; + mRemainingDelay = mDelay; + } + mLastMouseX = mousePos.left; + mLastMouseY = mousePos.top; + if (mRemainingDelay > 0) + return; - size_t underscorePos = it->first.find("_"); - std::string propertyKey = it->first.substr(0, underscorePos); - std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); - - MyGUI::Widget* w; - getWidget(w, widgetName); - w->setProperty(propertyKey, it->second); + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); + if (focus == 0) + { + return; } - for (unsigned int i=0; igetChildCount(); ++i) + IntSize tooltipSize; + + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) { - MyGUI::Widget* w = tooltip->getChildAt(i); - - if (w->isUserString("AutoResizeHorizontal")) - { - MyGUI::TextBox* text = w->castType(); - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); - } - else if (!tooltip->isUserString("DontResize")) - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); - - if (w->isUserString("AutoResizeVertical")) - { - MyGUI::TextBox* text = w->castType(); - int height = text->getTextSize().height; - if (height > w->getHeight()) - { - tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); - } - if (height < w->getHeight()) - { - tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); - } - } + focus = focus->getParent(); + if (!focus) + return; + ++i; } - tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); - } - else - throw std::runtime_error ("unknown tooltip type"); - IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + std::string type = focus->getUserString("ToolTipType"); + std::string text = focus->getUserString("ToolTipText"); - // make the tooltip stay completely in the viewport - if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) - { - tooltipPosition.left = viewSize.width - tooltipSize.width; - } - if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) - { - tooltipPosition.top = viewSize.height - tooltipSize.height; - } + ToolTipInfo info; + if (type == "") + { + return; + } + else if (type == "ItemPtr") + { + mFocusObject = *focus->getUserData(); + tooltipSize = getToolTipViaPtr(false); + } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } + else if (type == "Layout") + { + // tooltip defined in the layout + MyGUI::Widget* tooltip; + getWidget(tooltip, focus->getUserString("ToolTipLayout")); - setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + tooltip->setVisible(true); + if (!tooltip->isUserString("DontResize")) + { + tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping + + tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + } + else + tooltipSize = tooltip->getSize(); + + std::map userStrings = focus->getUserStrings(); + for (std::map::iterator it = userStrings.begin(); + it != userStrings.end(); ++it) + { + if (it->first == "ToolTipType" + || it->first == "ToolTipLayout") + continue; + + + size_t underscorePos = it->first.find("_"); + std::string propertyKey = it->first.substr(0, underscorePos); + std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); + + MyGUI::Widget* w; + getWidget(w, widgetName); + w->setProperty(propertyKey, it->second); + } + + for (unsigned int i=0; igetChildCount(); ++i) + { + MyGUI::Widget* w = tooltip->getChildAt(i); + + if (w->isUserString("AutoResizeHorizontal")) + { + MyGUI::TextBox* text = w->castType(); + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); + } + else if (!tooltip->isUserString("DontResize")) + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); + + if (w->isUserString("AutoResizeVertical")) + { + MyGUI::TextBox* text = w->castType(); + int height = text->getTextSize().height; + if (height > w->getHeight()) + { + tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); + } + if (height < w->getHeight()) + { + tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); + } + } + } + tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); + } + else + throw std::runtime_error ("unknown tooltip type"); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + } } else { diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 8ddbfe929..5275ae19d 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -487,6 +487,7 @@ void WindowManager::onFrame (float frameDuration) mDialogueWindow->checkReferenceAvailable(); mTradeWindow->checkReferenceAvailable(); mContainerWindow->checkReferenceAvailable(); + console->checkReferenceAvailable(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -708,3 +709,25 @@ void WindowManager::unsetSelectedWeapon() hud->unsetSelectedWeapon(); mInventoryWindow->setTitle("#{sSkillHandtohand}"); } + +void WindowManager::getMousePosition(int &x, int &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; +} + +void WindowManager::getMousePosition(float &x, float &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + x /= viewSize.width; + y /= viewSize.height; +} + +bool WindowManager::getWorldMouseOver() +{ + return hud->getWorldMouseOver(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 037022b42..19ad7702a 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -155,6 +155,7 @@ namespace MWGui MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} + MWGui::Console* getConsole() {return console;} MyGUI::Gui* getGui() const { return gui; } @@ -188,7 +189,10 @@ namespace MWGui void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setMouseVisible(bool visible); + void getMousePosition(int &x, int &y); + void getMousePosition(float &x, float &y); void setDragDrop(bool dragDrop); + bool getWorldMouseOver(); void toggleFogOfWar(); void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 808c712a0..5598ff3c0 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -66,7 +66,23 @@ namespace MWWorld return mEngine->rayTest2(from,to); } - void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){ + + std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) + { + Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + Ogre::Vector3 from = ray.getOrigin(); + Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable + + btVector3 _from, _to; + // OGRE to MW coordinates + _from = btVector3(from.x, -from.z, from.y); + _to = btVector3(to.x, -to.z, to.y); + + return mEngine->rayTest2(_from,_to); + } + + void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight) + { playerphysics->hasWater = hasWater; if(hasWater){ playerphysics->waterHeight = waterHeight; @@ -84,6 +100,14 @@ namespace MWWorld return result; } + btVector3 PhysicsSystem::getRayPoint(float extent, float mouseX, float mouseY) + { + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable + return result; + } + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { btVector3 _from, _to; diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 9b03d2124..1a8bd87ae 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -47,9 +47,12 @@ namespace MWWorld std::pair getFacedHandle (MWWorld::World& world); btVector3 getRayPoint(float extent); + btVector3 getRayPoint(float extent, float mouseX, float mouseY); std::vector < std::pair > getFacedObjects (); + std::vector < std::pair > getFacedObjects (float mouseX, float mouseY); + // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6802d5cc1..e8d555689 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -818,7 +818,15 @@ namespace MWWorld // send new query // figure out which object we want to test against - std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects(); + std::vector < std::pair < float, std::string > > results; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + results = mPhysics->getFacedObjects(x, y); + } + else + results = mPhysics->getFacedObjects(); // ignore the player and other things we're not interested in std::vector < std::pair < float, std::string > >::iterator it = results.begin(); @@ -843,7 +851,15 @@ namespace MWWorld mFaced1Name = results.front().second; mNumFacing = 1; - btVector3 p = mPhysics->getRayPoint(results.front().first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results.front().first, x, y); + } + else + p = mPhysics->getRayPoint(results.front().first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); @@ -860,7 +876,15 @@ namespace MWWorld mFaced2 = getPtrViaHandle(results[1].second); mNumFacing = 2; - btVector3 p = mPhysics->getRayPoint(results[1].first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results[1].first, x, y); + } + else + p = mPhysics->getRayPoint(results[1].first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode(); Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode(); From b886aea2989e0a5276bf637c4328372a43117377 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 12:31:23 +0200 Subject: [PATCH 231/289] change console skin to MW_Window and set the selected object refID as window title --- apps/openmw/mwgui/console.cpp | 2 ++ files/mygui/openmw_console.skin.xml | 35 --------------------------- files/mygui/openmw_console_layout.xml | 8 +++--- 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index c9ba752e9..25cd90eae 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -379,10 +379,12 @@ namespace MWGui void Console::setSelectedObject(const MWWorld::Ptr& object) { mPtr = object; + setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); } void Console::onReferenceUnavailable() { mPtr = MWWorld::Ptr(); + setTitle("#{sConsoleTitle}"); } } diff --git a/files/mygui/openmw_console.skin.xml b/files/mygui/openmw_console.skin.xml index 598252734..1758c728d 100644 --- a/files/mygui/openmw_console.skin.xml +++ b/files/mygui/openmw_console.skin.xml @@ -1,41 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/files/mygui/openmw_console_layout.xml b/files/mygui/openmw_console_layout.xml index a2b883cdb..732684ad1 100644 --- a/files/mygui/openmw_console_layout.xml +++ b/files/mygui/openmw_console_layout.xml @@ -1,17 +1,17 @@  - - + + - + - + From b8464d4ce50c4852a9b2375cf684582baa5f7331 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 14:19:02 +0200 Subject: [PATCH 232/289] allow picking up objects from the gameworld with the mouse in inventory mode --- apps/openmw/mwgui/console.cpp | 9 ++-- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 5 +- apps/openmw/mwgui/inventorywindow.cpp | 68 ++++++++++++++++++++++++--- apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwgui/spellwindow.cpp | 10 ++++ apps/openmw/mwgui/tradewindow.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 1 + 8 files changed, 87 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 25cd90eae..2f8a95306 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -138,6 +138,7 @@ namespace MWGui void Console::disable() { setVisible(false); + setSelectedObject(MWWorld::Ptr()); // Remove keyboard focus from the console input whenever the // console is turned off MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL); @@ -379,12 +380,14 @@ namespace MWGui void Console::setSelectedObject(const MWWorld::Ptr& object) { mPtr = object; - setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); + if (!mPtr.isEmpty()) + setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); + else + setTitle("#{sConsoleTitle}"); } void Console::onReferenceUnavailable() { - mPtr = MWWorld::Ptr(); - setTitle("#{sConsoleTitle}"); + setSelectedObject(MWWorld::Ptr()); } } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index bf6b4add0..eb5cbc92b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -470,7 +470,7 @@ void ContainerBase::drawItems() if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); + 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) != ""); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 2f275cd33..95d66eb81 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -12,6 +12,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" +#include "inventorywindow.hpp" #include "window_manager.hpp" #include "container.hpp" #include "console.hpp" @@ -266,6 +267,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) mDragAndDrop->mDraggedWidget = 0; MWBase::Environment::get().getWindowManager()->setDragDrop(false); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } else { @@ -287,9 +289,10 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if (mode == GM_Console) MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); - else if (mode == GM_Console || GM_Inventory) + else if ((mode == GM_Container) || (mode == GM_Inventory)) { // pick up object + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object); } } } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 103f5ebf3..f75c9afdc 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -15,6 +15,8 @@ #include "../mwworld/player.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" +#include "../mwworld/actiontake.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "widgets.hpp" @@ -276,13 +278,65 @@ namespace MWGui if (mWindowManager.getSpellWindow()) mWindowManager.getSpellWindow()->updateSpells(); - // update selected weapon icon - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (weaponSlot == invStore.end()) - mWindowManager.unsetSelectedWeapon(); - else - mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } + 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()) + && (type != typeid(ESM::Armor).name()) + && (type != typeid(ESM::Book).name()) + && (type != typeid(ESM::Clothing).name()) + && (type != typeid(ESM::Ingredient).name()) + && (type != typeid(ESM::Light).name()) + && (type != typeid(ESM::Miscellaneous).name()) + && (type != typeid(ESM::Tool).name()) + && (type != typeid(ESM::Probe).name()) + && (type != typeid(ESM::Repair).name()) + && (type != typeid(ESM::Potion).name())) + return; + + // sound + std::string sound = MWWorld::Class::get(object).getUpSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1); + + int count = object.getRefData().getCount(); + MWWorld::ActionTake action(object); + action.execute(); + mDragAndDrop->mIsOnDragAndDrop = true; + mDragAndDrop->mDraggedCount = count; + + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(object).getInventoryIcon(object); + MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); + baseWidget->detachFromWidget(); + baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget); + baseWidget->setUserData(object); + mDragAndDrop->mDraggedWidget = baseWidget; + ImageBox* image = baseWidget->createWidget("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("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; } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index bc4cb08ef..82da3efea 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -18,6 +18,8 @@ namespace MWGui void onFrame(); + void pickUpObject (MWWorld::Ptr object); + int getPlayerGold(); protected: diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 502754feb..d34ce68d9 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -89,6 +89,16 @@ namespace MWGui bool allowSelectedItem = true; + // make sure that the item is still in the player inventory, otherwise it can't be selected + bool found = false; + for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) + { + if (*it == selectedItem) + found = true; + } + if (!found) + allowSelectedItem = false; + // if the selected item can be equipped, make sure that it actually is equipped std::pair, bool> slots; slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 2089ed4af..47d299fdc 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -300,6 +300,8 @@ namespace MWGui services = ref->base->AI.services; } + /// \todo what about potions, there doesn't seem to be a flag for them?? + if (item.getTypeName() == typeid(ESM::Weapon).name()) return services & ESM::NPC::Weapon; else if (item.getTypeName() == typeid(ESM::Armor).name()) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 5275ae19d..800125f27 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -638,6 +638,7 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector hud->onResChange(x, y); console->onResChange(x, y); mSettingsWindow->center(); + mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); } } From 8e96871acdbb6a5784e634a0f1481ea63bf1f2d4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Jun 2012 18:40:10 +0200 Subject: [PATCH 233/289] remove something unused --- apps/openmw/mwgui/dialogue.cpp | 3 --- apps/openmw/mwgui/dialogue.hpp | 1 - 2 files changed, 4 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index ce687424c..17552b09d 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -140,7 +140,6 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) setTitle(npcName); topicsList->clear(); - pTopicsText.clear(); history->eraseText(0,history->getTextLength()); updateOptions(); } @@ -169,7 +168,6 @@ void DialogueWindow::removeKeyword(std::string keyWord) if(topicsList->hasItem(keyWord)) { topicsList->removeItem(keyWord); - pTopicsText.erase(keyWord); } topicsList->adjustSize(); } @@ -245,7 +243,6 @@ void DialogueWindow::updateOptions() { //Clear the list of topics topicsList->clear(); - pTopicsText.clear(); history->eraseText(0,history->getTextLength()); pDispositionBar->setProgressRange(100); diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 8e9aba003..aa66cd579 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -77,7 +77,6 @@ namespace MWGui Widgets::MWList* topicsList; MyGUI::ProgressPtr pDispositionBar; MyGUI::EditPtr pDispositionText; - std::map pTopicsText;// this map links keyword and "real" text. }; } #endif From d56defd4f4c013587ffd628d299b7bdb1196e4b0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Jun 2012 21:19:48 +0200 Subject: [PATCH 234/289] set input focus to console after selecting objects in console mode --- apps/openmw/mwgui/console.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 2f8a95306..8e6dd8019 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -384,6 +384,7 @@ namespace MWGui setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); else setTitle("#{sConsoleTitle}"); + MyGUI::InputManager::getInstance().setKeyFocusWidget(command); } void Console::onReferenceUnavailable() From 1ecc6f97ed2529ae7c9b22f1fdd85dd829e7f99d Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Jun 2012 20:56:13 +0200 Subject: [PATCH 235/289] alchemy effect fix --- apps/openmw/mwgui/widgets.hpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index c66bf5dd0..04866b176 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -54,9 +54,20 @@ namespace MWGui bool operator==(const SpellEffectParams& other) const { - return (other.mEffectID == mEffectID - && other.mSkill == mSkill - && other.mAttribute == mAttribute); + if (mEffectID != other.mEffectID) + return false; + + bool involvesAttribute = (mEffectID == 74 // restore attribute + || mEffectID == 85 // absorb attribute + || mEffectID == 17 // drain attribute + || mEffectID == 79 // fortify attribute + || mEffectID == 22); // damage attribute + bool involvesSkill = (mEffectID == 78 // restore skill + || mEffectID == 89 // absorb skill + || mEffectID == 21 // drain skill + || mEffectID == 83 // fortify skill + || mEffectID == 26); // damage skill + return ((other.mSkill == mSkill) || !involvesSkill) && ((other.mAttribute == mAttribute) && !involvesAttribute); } }; From ea8e3ca1c8809aa5625dc9af4b5d6e05be2b67b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Jun 2012 21:09:51 +0200 Subject: [PATCH 236/289] fix item duplication bug when picking up object with the mouse and immediately dropping again --- apps/openmw/mwgui/inventorywindow.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index f75c9afdc..7409aed72 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -311,17 +311,23 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1); int count = object.getRefData().getCount(); - MWWorld::ActionTake action(object); - action.execute(); + + // add to player inventory + // can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Ptr newObject = *MWWorld::Class::get (player).getContainerStore (player).add (object); + // 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(object).getInventoryIcon(object); + path += MWWorld::Class::get(newObject).getInventoryIcon(newObject); MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); baseWidget->detachFromWidget(); baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget); - baseWidget->setUserData(object); + baseWidget->setUserData(newObject); mDragAndDrop->mDraggedWidget = baseWidget; ImageBox* image = baseWidget->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); int pos = path.rfind("."); From dfac5f26c3a504a20377271525af89c819b4fde8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Jun 2012 21:48:20 +0200 Subject: [PATCH 237/289] fixed some issues: - probes were not showing up in inventory category "misc" - lights, probes, lockpicks were not equippable - weapons could not be picked up --- apps/openmw/mwclass/light.cpp | 8 ++++++++ apps/openmw/mwclass/light.hpp | 4 ++++ apps/openmw/mwclass/lockpick.cpp | 8 ++++++++ apps/openmw/mwclass/lockpick.hpp | 4 ++++ apps/openmw/mwclass/probe.cpp | 8 ++++++++ apps/openmw/mwclass/probe.hpp | 4 ++++ apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 1 + 8 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 12ae517ef..154033433 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/nullaction.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -176,4 +177,11 @@ namespace MWClass return info; } + + boost::shared_ptr Light::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index cd963d842..91193dfdc 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -48,6 +48,10 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 5bb677646..27e292bc0 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" #include "../mwgui/window_manager.hpp" @@ -155,4 +156,11 @@ namespace MWClass return info; } + + boost::shared_ptr Lockpick::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index b8683c5e9..26aab584c 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -48,6 +48,10 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 1e713f0a5..0b256d729 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" #include "../mwgui/window_manager.hpp" @@ -154,4 +155,11 @@ namespace MWClass return info; } + + boost::shared_ptr Probe::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 5e0059e14..51b046fda 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -48,6 +48,10 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index eb5cbc92b..6ba4923d9 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -384,7 +384,7 @@ void ContainerBase::drawItems() 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_Apparatus + MWWorld::ContainerStore::Type_Probe; } else if (mFilter == Filter_Ingredients) categories = MWWorld::ContainerStore::Type_Ingredient; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7409aed72..a26a958bd 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -303,6 +303,7 @@ namespace MWGui && (type != typeid(ESM::Tool).name()) && (type != typeid(ESM::Probe).name()) && (type != typeid(ESM::Repair).name()) + && (type != typeid(ESM::Weapon).name()) && (type != typeid(ESM::Potion).name())) return; From c85c794c869080d778b99efe14b6bdc5c4e3c359 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Jun 2012 20:29:30 +0200 Subject: [PATCH 238/289] fixed some cppcheck issues --- apps/mwiniimporter/importer.cpp | 22 ++++++++++++---------- apps/openmw/mwdialogue/dialoguemanager.cpp | 2 +- apps/openmw/mwgui/charactercreation.cpp | 1 + apps/openmw/mwgui/class.cpp | 9 +++------ apps/openmw/mwgui/console.cpp | 6 +++--- apps/openmw/mwgui/container.cpp | 4 ---- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/journalwindow.cpp | 4 ++-- apps/openmw/mwgui/review.cpp | 4 ++-- apps/openmw/mwgui/review.hpp | 4 ++-- apps/openmw/mwgui/stats_window.cpp | 2 +- apps/openmw/mwgui/stats_window.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 1 - apps/openmw/mwgui/widgets.cpp | 2 +- apps/openmw/mwgui/widgets.hpp | 2 +- apps/openmw/mwgui/window_manager.cpp | 4 ++-- apps/openmw/mwgui/window_manager.hpp | 4 ++-- apps/openmw/mwrender/debugging.cpp | 6 +++--- apps/openmw/mwrender/npcanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.hpp | 2 +- apps/openmw/mwrender/objects.hpp | 5 +++-- apps/openmw/mwrender/terrainmaterial.hpp | 2 +- apps/openmw/mwsound/sound_output.hpp | 2 +- apps/openmw/mwworld/physicssystem.cpp | 1 + apps/openmw/mwworld/player.hpp | 2 +- apps/openmw/mwworld/weather.cpp | 3 ++- components/bsa/bsa_archive.cpp | 4 ++-- components/compiler/generator.cpp | 8 ++++---- components/compiler/generator.hpp | 8 ++++---- components/esm/esm_reader.hpp | 12 ++++++------ components/files/filelibrary.cpp | 4 ++-- components/nifogre/ogre_nif_loader.cpp | 6 +++--- libs/mangle/input/servers/ois_driver.cpp | 3 +-- libs/openengine/bullet/CMotionState.cpp | 2 ++ libs/openengine/gui/manager.cpp | 2 +- libs/openengine/ogre/renderer.cpp | 11 +++++------ libs/openengine/ogre/renderer.hpp | 4 ++-- 37 files changed, 81 insertions(+), 83 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 5503a7c1a..d396df648 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -8,7 +8,9 @@ #include #include -MwIniImporter::MwIniImporter() { +MwIniImporter::MwIniImporter() + : mVerbose(false) +{ const char *map[][2] = { { "fps", "General:Show FPS" }, @@ -124,9 +126,9 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) { void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) { multistrmap::iterator cfgIt; multistrmap::iterator iniIt; - for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) { + for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); ++it) { if((iniIt = ini.find(it->second)) != ini.end()) { - for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { + for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); ++vc) { cfg.erase(it->first); insertMultistrmap(cfg, it->first, *vc); } @@ -139,9 +141,9 @@ void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) { multistrmap::iterator cfgIt; multistrmap::iterator iniIt; - for(std::vector::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); it++) { + for(std::vector::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); ++it) { if((iniIt = ini.find(*it)) != ini.end()) { - for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { + for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); ++vc) { std::string value(*it); std::replace( value.begin(), value.end(), ' ', '_' ); std::replace( value.begin(), value.end(), ':', '_' ); @@ -176,7 +178,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { break; } - for(std::vector::iterator entry = it->second.begin(); entry!=it->second.end(); entry++) { + for(std::vector::iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) { std::string filetype(entry->substr(entry->length()-4, 3)); std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); @@ -194,22 +196,22 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { cfg.erase("master"); cfg.insert( std::make_pair > ("master", std::vector() ) ); - for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { + for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); ++it) { cfg["master"].push_back(*it); } cfg.erase("plugin"); cfg.insert( std::make_pair > ("plugin", std::vector() ) ); - for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { + for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); ++it) { cfg["plugin"].push_back(*it); } } void MwIniImporter::writeToFile(boost::iostreams::stream &out, multistrmap &cfg) { - for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); it++) { - for(std::vector::iterator entry=it->second.begin(); entry != it->second.end(); entry++) { + for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); ++it) { + for(std::vector::iterator entry=it->second.begin(); entry != it->second.end(); ++entry) { out << (it->first) << "=" << (*entry) << std::endl; } } diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index 716f472a0..a19356d07 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -607,7 +607,7 @@ namespace MWDialogue void DialogueManager::parseText(std::string text) { std::list::iterator it; - for(it = actorKnownTopics.begin();it != actorKnownTopics.end();it++) + for(it = actorKnownTopics.begin();it != actorKnownTopics.end();++it) { size_t pos = find_str_ci(text,*it,0); if(pos !=std::string::npos) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 31696230c..3f9a94e2d 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -117,6 +117,7 @@ CharacterCreation::CharacterCreation(WindowManager* _wm) , mCreateClassDialog(0) , mBirthSignDialog(0) , mReviewDialog(0) + , mGenerateClassStep(0) , mWM(_wm) { mCreationStage = CSE_NotStarted; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index a7e5b8674..0961f6327 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -581,8 +581,7 @@ void CreateClassDialog::onDialogCancel() void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) { - if (specDialog) - delete specDialog; + delete specDialog; specDialog = new SelectSpecializationDialog(mWindowManager); specDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); specDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected); @@ -613,8 +612,7 @@ void CreateClassDialog::setSpecialization(int id) void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) { - if (attribDialog) - delete attribDialog; + delete attribDialog; attribDialog = new SelectAttributeDialog(mWindowManager); attribDialog->setAffectedWidget(_sender); attribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); @@ -645,8 +643,7 @@ void CreateClassDialog::onAttributeSelected() void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) { - if (skillDialog) - delete skillDialog; + delete skillDialog; skillDialog = new SelectSkillDialog(mWindowManager); skillDialog->setAffectedWidget(_sender); skillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 8e6dd8019..8115835f4 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -268,7 +268,7 @@ namespace MWGui /* Are there quotation marks? */ if( tmp.find('"') != string::npos ) { int numquotes=0; - for(string::iterator it=tmp.begin(); it < tmp.end(); it++) { + for(string::iterator it=tmp.begin(); it < tmp.end(); ++it) { if( *it == '"' ) numquotes++; } @@ -311,7 +311,7 @@ namespace MWGui } /* Iterate through the vector. */ - for(vector::iterator it=mNames.begin(); it < mNames.end();it++) { + for(vector::iterator it=mNames.begin(); it < mNames.end();++it) { bool string_different=false; /* Is the string shorter than the input string? If yes skip it. */ @@ -359,7 +359,7 @@ namespace MWGui int i = tmp.length(); for(string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) { - for(vector::iterator it=matches.begin(); it < matches.end();it++) { + for(vector::iterator it=matches.begin(); it < matches.end();++it) { if( tolower((*it)[i]) != tolower(*iter) ) { /* Append the longest match to the end of the output string*/ output.append(matches.front().substr( 0, i)); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6ba4923d9..6775fa643 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -361,9 +361,6 @@ void ContainerBase::drawItems() int y = 0; int maxHeight = mItemView->getSize().height - 58; - int index = 0; - - bool onlyMagic = false; int categories; if (mFilter == Filter_All) @@ -459,7 +456,6 @@ void ContainerBase::drawItems() for (std::vector< std::pair >::const_iterator it=items.begin(); it != items.end(); ++it) { - index++; const MWWorld::Ptr* iter = &((*it).first); int displayCount = iter->getRefData().getCount(); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 17552b09d..79b2d68ba 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -156,7 +156,7 @@ void DialogueWindow::setKeywords(std::list keyWords) if (anyService) topicsList->addSeparator(); - for(std::list::iterator it = keyWords.begin(); it != keyWords.end(); it++) + for(std::list::iterator it = keyWords.begin(); it != keyWords.end(); ++it) { topicsList->addItem(*it); } diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index e4c38496d..7f9000bc7 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -131,7 +131,7 @@ void MWGui::JournalWindow::open() book journal; journal.endLine = 0; - for(std::deque::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();it++) + for(std::deque::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();++it) { std::string a = it->getText(MWBase::Environment::get().getWorld()->getStore()); journal = formatText(a,journal,10,17); @@ -141,7 +141,7 @@ void MWGui::JournalWindow::open() //std::string a = MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore()); //std::list journal = formatText(a,10,20,1); bool left = true; - for(std::list::iterator it = journal.pages.begin(); it != journal.pages.end();it++) + for(std::list::iterator it = journal.pages.begin(); it != journal.pages.end();++it) { if(left) { diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 67b6cc24a..97a3a6e15 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -257,7 +257,7 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M coord2.top += lineHeight; } -MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillValueWidget; @@ -280,7 +280,7 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st return skillValueWidget; } -void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +void ReviewDialog::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* skillNameWidget; diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index bae4dc459..6118168d5 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -74,8 +74,8 @@ namespace MWGui void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); void updateSkillArea(); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 75159f4db..3584af7c7 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -340,7 +340,7 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st return skillValueWidget; } -MyGUI::Widget* StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* skillNameWidget; diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index bbd916585..10b794cc0 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -47,7 +47,7 @@ namespace MWGui void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); void setFactions (const FactionList& factions); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 1f614d56b..7ec444168 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -142,7 +142,6 @@ void ToolTips::onFrame(float frameDuration) std::string type = focus->getUserString("ToolTipType"); std::string text = focus->getUserString("ToolTipText"); - ToolTipInfo info; if (type == "") { return; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index b85074805..65de7ce0a 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -767,7 +767,7 @@ void MWDynamicStat::setValue(int cur, int max_) static_cast(barTextWidget)->setCaption(""); } } -void MWDynamicStat::setTitle(const std::string text) +void MWDynamicStat::setTitle(const std::string& text) { if (textWidget) static_cast(textWidget)->setCaption(text); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 04866b176..5d00baf87 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -282,7 +282,7 @@ namespace MWGui MWDynamicStat(); void setValue(int value, int max); - void setTitle(const std::string text); + void setTitle(const std::string& text); int getValue() const { return value; } int getMax() const { return max; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 800125f27..5b963d3ae 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -39,7 +39,7 @@ using namespace MWGui; WindowManager::WindowManager( - const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath) + const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath) : mGuiManager(NULL) , hud(NULL) , map(NULL) @@ -657,7 +657,7 @@ void WindowManager::pushGuiMode(GuiMode mode) void WindowManager::popGuiMode() { - if (mGuiModes.size()) + if (!mGuiModes.empty()) mGuiModes.pop_back(); bool gameMode = !isGuiMode(); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 19ad7702a..37f30c59a 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -98,7 +98,7 @@ namespace MWGui typedef std::vector FactionList; typedef std::vector SkillList; - WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); + WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath); virtual ~WindowManager(); /** @@ -141,7 +141,7 @@ namespace MWGui updateVisible(); } - bool isAllowed(GuiWindow wnd) + bool isAllowed(GuiWindow wnd) const { return allowed & wnd; } diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index be8afbae6..9086a9bc4 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -68,7 +68,7 @@ ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid) result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST); for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->edges.begin(); it != pathgrid->edges.end(); - it++) + ++it) { const ESM::Pathgrid::Edge &edge = *it; const ESM::Pathgrid::Point &p1 = pathgrid->points[edge.v0], &p2 = pathgrid->points[edge.v1]; @@ -197,7 +197,7 @@ void Debugging::togglePathgrid() // add path grid meshes to already loaded cells mPathGridRoot = mMwRoot->createChildSceneNode(); - for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) + for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it) { enableCellPathgrid(*it); } @@ -205,7 +205,7 @@ void Debugging::togglePathgrid() else { // remove path grid meshes from already loaded cells - for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) + for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it) { disableCellPathgrid(*it); } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index c35fff1ce..5ceafca36 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -528,7 +528,7 @@ void NpcAnimation::insertFootPart(int type, const std::string &mesh){ } -std::pair*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix){ +std::pair*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string& suffix){ std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; NIFLoader::load(meshNumbered); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index a37becc26..8f4f8181d 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -84,7 +84,7 @@ private: NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); virtual ~NpcAnimation(); Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); - std::pair*> insertFreePart(const std::string &mesh, const std::string suffix); + std::pair*> insertFreePart(const std::string &mesh, const std::string& suffix); void insertFootPart(int type, const std::string &mesh); virtual void runAnimation(float timepassed); void updateParts(); diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index fb26808b9..6132879e6 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -39,7 +39,8 @@ struct LightInfo LightInfo() : flickerVariation(0), resetTime(0.5), - flickerSlowVariation(0), time(0), interior(true) + flickerSlowVariation(0), time(0), interior(true), + type(LT_Normal), radius(1.0) { } }; @@ -68,7 +69,7 @@ class Objects{ ///< Remove all movable objects from \a node. public: - Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {} + Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mIsStatic(false) {} ~Objects(){} void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); diff --git a/apps/openmw/mwrender/terrainmaterial.hpp b/apps/openmw/mwrender/terrainmaterial.hpp index db916bf25..e94e20b7e 100644 --- a/apps/openmw/mwrender/terrainmaterial.hpp +++ b/apps/openmw/mwrender/terrainmaterial.hpp @@ -167,7 +167,7 @@ namespace Ogre class ShaderHelper : public TerrainAlloc { public: - ShaderHelper() {} + ShaderHelper() : mShadowSamplerStartHi(0), mShadowSamplerStartLo(0) {} virtual ~ShaderHelper() {} virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 7efed8129..100b2208c 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -46,7 +46,7 @@ namespace MWSound public: virtual ~Sound_Output() { } - bool isInitialized() { return mInitialized; } + bool isInitialized() const { return mInitialized; } friend class OpenAL_Output; friend class SoundManager; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 5598ff3c0..7c1ff31b4 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -32,6 +32,7 @@ namespace MWWorld PhysicsSystem::~PhysicsSystem() { delete mEngine; + delete playerphysics; } OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 166d4cfee..a5c5ff308 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -107,7 +107,7 @@ namespace MWWorld return *mClass; } - bool getAutoMove() + bool getAutoMove() const { return mAutoMove; } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 316463f53..3d6547d6a 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -38,7 +38,8 @@ const float WeatherGlobals::mThunderSoundDelay = 0.25; WeatherManager::WeatherManager(MWRender::RenderingManager* rendering) : mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0), - mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0) + mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0), + mRemainingTransitionTime(0), mMonth(0), mDay(0) { mRendering = rendering; diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index fa197d960..d3b75d4ae 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -93,12 +93,12 @@ class DirArchive: public Ogre::FileSystemArchive return true; std::string folder; - int delimiter = 0; + //int delimiter = 0; size_t lastSlash = copy.rfind('/'); if (lastSlash != std::string::npos) { folder = copy.substr(0, lastSlash); - delimiter = lastSlash+1; + //delimiter = lastSlash+1; } std::vector current; diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index ee9876a14..26a80387b 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -727,7 +727,7 @@ namespace Compiler opStopScript (code); } - void getDistance (CodeContainer& code, Literals& literals, const std::string id) + void getDistance (CodeContainer& code, Literals& literals, const std::string& id) { if (id.empty()) { @@ -746,7 +746,7 @@ namespace Compiler opGetSecondsPassed (code); } - void getDisabled (CodeContainer& code, Literals& literals, const std::string id) + void getDisabled (CodeContainer& code, Literals& literals, const std::string& id) { if (id.empty()) { @@ -760,7 +760,7 @@ namespace Compiler } } - void enable (CodeContainer& code, Literals& literals, const std::string id) + void enable (CodeContainer& code, Literals& literals, const std::string& id) { if (id.empty()) { @@ -774,7 +774,7 @@ namespace Compiler } } - void disable (CodeContainer& code, Literals& literals, const std::string id) + void disable (CodeContainer& code, Literals& literals, const std::string& id) { if (id.empty()) { diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index fd1f954ca..89e198431 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -109,15 +109,15 @@ namespace Compiler void stopScript (CodeContainer& code); - void getDistance (CodeContainer& code, Literals& literals, const std::string id); + void getDistance (CodeContainer& code, Literals& literals, const std::string& id); void getSecondsPassed (CodeContainer& code); - void getDisabled (CodeContainer& code, Literals& literals, const std::string id); + void getDisabled (CodeContainer& code, Literals& literals, const std::string& id); - void enable (CodeContainer& code, Literals& literals, const std::string id); + void enable (CodeContainer& code, Literals& literals, const std::string& id); - void disable (CodeContainer& code, Literals& literals, const std::string id); + void disable (CodeContainer& code, Literals& literals, const std::string& id); } } diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 0420f37cd..340482891 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -152,15 +152,15 @@ public: * *************************************************************************/ - int getVer() { return mCtx.header.version; } + int getVer() const { return mCtx.header.version; } float getFVer() { if(mCtx.header.version == VER_12) return 1.2; else return 1.3; } - int getSpecial() { return mSpf; } + int getSpecial() const { return mSpf; } const std::string getAuthor() { return mCtx.header.author.toString(); } const std::string getDesc() { return mCtx.header.desc.toString(); } - const SaveData &getSaveData() { return mSaveData; } + const SaveData &getSaveData() const { return mSaveData; } const MasterList &getMasters() { return mMasters; } const NAME &retSubName() { return mCtx.subName; } - uint32_t getSubSize() { return mCtx.leftSub; } + uint32_t getSubSize() const { return mCtx.leftSub; } /************************************************************************* * @@ -323,8 +323,8 @@ public: void getRecHeader() { uint32_t u; getRecHeader(u); } void getRecHeader(uint32_t &flags); - bool hasMoreRecs() { return mCtx.leftFile > 0; } - bool hasMoreSubs() { return mCtx.leftRec > 0; } + bool hasMoreRecs() const { return mCtx.leftFile > 0; } + bool hasMoreSubs() const { return mCtx.leftRec > 0; } /************************************************************************* diff --git a/components/files/filelibrary.cpp b/components/files/filelibrary.cpp index c11415929..ce67f0c66 100644 --- a/components/files/filelibrary.cpp +++ b/components/files/filelibrary.cpp @@ -11,7 +11,7 @@ namespace Files bool containsVectorString(const StringVector& list, const std::string& str) { for (StringVector::const_iterator iter = list.begin(); - iter != list.end(); iter++) + iter != list.end(); ++iter) { if (*iter == str) return true; @@ -112,7 +112,7 @@ namespace Files void FileLibrary::printSections() { for(StringPathContMap::const_iterator mapIter = mMap.begin(); - mapIter != mMap.end(); mapIter++) + mapIter != mMap.end(); ++mapIter) { std::cout << mapIter->first <recType == RC_NiTexturingProperty) - t = (NiTexturingProperty*)pr; + t = static_cast(pr); else if (pr->recType == RC_NiMaterialProperty) - m = (NiMaterialProperty*)pr; + m = static_cast(pr); else if (pr->recType == RC_NiAlphaProperty) - a = (NiAlphaProperty*)pr; + a = static_cast(pr); } // Texture diff --git a/libs/mangle/input/servers/ois_driver.cpp b/libs/mangle/input/servers/ois_driver.cpp index acca69df4..b8e4f5eb9 100644 --- a/libs/mangle/input/servers/ois_driver.cpp +++ b/libs/mangle/input/servers/ois_driver.cpp @@ -121,8 +121,7 @@ OISDriver::OISDriver(Ogre::RenderWindow *window, bool exclusive) OISDriver::~OISDriver() { // Delete the listener object - if(listener) - delete listener; + delete listener; if(inputMgr == NULL) return; diff --git a/libs/openengine/bullet/CMotionState.cpp b/libs/openengine/bullet/CMotionState.cpp index 5ddef5175..d7746cbc5 100644 --- a/libs/openengine/bullet/CMotionState.cpp +++ b/libs/openengine/bullet/CMotionState.cpp @@ -11,6 +11,8 @@ namespace Physic { CMotionState::CMotionState(PhysicEngine* eng,std::string name) + : isPC(false) + , isNPC(true) { pEng = eng; tr.setIdentity(); diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 1bf8ec325..022c5efb5 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -36,7 +36,7 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool void MyGUIManager::shutdown() { - if(mGui) delete mGui; + delete mGui; if(mPlatform) { mPlatform->shutdown(); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index a5eca76ed..fadfa8d8c 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -17,11 +17,10 @@ using namespace OEngine::Render; void OgreRenderer::cleanup() { - if (mFader) - delete mFader; + delete mFader; + mFader = NULL; - if(mRoot) - delete mRoot; + OGRE_DELETE mRoot; mRoot = NULL; } @@ -30,7 +29,7 @@ void OgreRenderer::start() mRoot->startRendering(); } -bool OgreRenderer::loadPlugins() +bool OgreRenderer::loadPlugins() const { #ifdef ENABLE_PLUGIN_GL mGLPlugin = new Ogre::GLPlugin(); @@ -125,7 +124,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); } -void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) +void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip) { assert(mRoot); assert(mWindow); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index f4ea8fbc8..f188e2051 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -119,7 +119,7 @@ namespace OEngine void createWindow(const std::string &title, const WindowSettings& settings); /// Set up the scene manager, camera and viewport - void createScene(const std::string camName="Camera",// Camera name + void createScene(const std::string& camName="Camera",// Camera name float fov=55, // Field of view angle float nearClip=5 // Near clip distance ); @@ -132,7 +132,7 @@ namespace OEngine /// Start the main rendering loop void start(); - bool loadPlugins(); + bool loadPlugins() const; void update(float dt); From 42e44ac1b5d095f6d0ecd7760b2f4597759bb983 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Jun 2012 21:08:20 +0200 Subject: [PATCH 239/289] fixed some leaks --- apps/openmw/mwrender/renderingmanager.cpp | 4 +++- libs/openengine/bullet/physic.cpp | 15 ++++++++++++--- libs/openengine/bullet/physic.hpp | 10 ++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a6f10fcd2..a771eb12e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -97,7 +97,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mTerrainManager = new TerrainManager(mRendering.getScene(), this); - //mSkyManager = 0; mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); @@ -116,10 +115,13 @@ RenderingManager::~RenderingManager () delete mPlayer; delete mSkyManager; delete mDebugging; + delete mShaderHelper; + delete mShadows; delete mTerrainManager; delete mLocalMap; delete mOcclusionQuery; delete mCompositors; + delete mWater; } MWRender::SkyManager* RenderingManager::getSkyManager() diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index d30d5e9f1..a94434e5b 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -300,7 +300,13 @@ namespace Physic body->collide = true; body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); - addRigidBody(body); + HeightField hf; + hf.mBody = body; + hf.mShape = hfShape; + + mHeightFieldMap [name] = hf; + + dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); } void PhysicEngine::removeHeightField(int x, int y) @@ -309,8 +315,11 @@ namespace Physic + boost::lexical_cast(x) + "_" + boost::lexical_cast(y); - removeRigidBody(name); - deleteRigidBody(name); + HeightField hf = mHeightFieldMap [name]; + + dynamicsWorld->removeRigidBody(hf.mBody); + delete hf.mShape; + delete hf.mBody; } RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index ba241b2b7..811572320 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -15,6 +15,7 @@ class btSequentialImpulseConstraintSolver; class btCollisionDispatcher; class btDiscreteDynamicsWorld; class btKinematicCharacterController; +class btHeightfieldTerrainShape; namespace BtOgre { @@ -115,6 +116,12 @@ namespace Physic bool collide; }; + struct HeightField + { + btHeightfieldTerrainShape* mShape; + RigidBody* mBody; + }; + /** * The PhysicEngine class contain everything which is needed for Physic. * It's needed that Ogre Resources are set up before the PhysicEngine is created. @@ -240,6 +247,9 @@ namespace Physic //the NIF file loader. BulletShapeLoader* mShapeLoader; + typedef std::map HeightFieldContainer; + HeightFieldContainer mHeightFieldMap; + typedef std::map RigidBodyContainer; RigidBodyContainer RigidBodyMap; From 72fca4009057169a63b05da9ff86d5f75ec2f1b7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 11:59:45 +0200 Subject: [PATCH 240/289] Issue #181: member variable access in interpreter context --- apps/openmw/mwscript/interpretercontext.cpp | 66 +++++++++++++++++++++ apps/openmw/mwscript/interpretercontext.hpp | 12 ++++ apps/openmw/mwscript/scriptmanager.cpp | 39 ++++++++++++ apps/openmw/mwscript/scriptmanager.hpp | 4 ++ components/interpreter/context.hpp | 13 ++++ 5 files changed, 134 insertions(+) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index a369486fa..55059b522 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -270,6 +270,72 @@ namespace MWScript MWBase::Environment::get().getWorld()->disable (ref); } + int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + return ptr.getRefData().getLocals().mShorts[index]; + } + + int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + return ptr.getRefData().getLocals().mLongs[index]; + } + + float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + return ptr.getRefData().getLocals().mFloats[index]; + } + + void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + ptr.getRefData().getLocals().mShorts[index] = value; + } + + void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + ptr.getRefData().getLocals().mLongs[index] = value; + } + + void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + ptr.getRefData().getLocals().mFloats[index] = value; + } + MWWorld::Ptr InterpreterContext::getReference() { return getReference ("", true); diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 40f53337d..9fdc3c21a 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -107,6 +107,18 @@ namespace MWScript virtual void disable (const std::string& id = ""); + virtual int getMemberShort (const std::string& id, const std::string& name) const; + + virtual int getMemberLong (const std::string& id, const std::string& name) const; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value); + + virtual void setMemberLong (const std::string& id, const std::string& name, int value); + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value); + MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 506cf049c..6ae506483 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -156,4 +156,43 @@ namespace MWScript { return mGlobalScripts; } + + int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable, + char type) + { + const ESM::Script *script = mStore.scripts.find (scriptId); + + int offset = 0; + int size = 0; + + switch (type) + { + case 's': + + offset = 0; + size = script->data.numShorts; + break; + + case 'l': + + offset = script->data.numShorts; + size = script->data.numLongs; + break; + + case 'f': + + offset = script->data.numShorts+script->data.numLongs; + size = script->data.numFloats; + + default: + + throw std::runtime_error ("invalid variable type"); + } + + for (int i=0; ivarNames.at (i+offset)==variable) + return i; + + throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId); + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index 35c1fadd9..34cc0defe 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -67,6 +67,10 @@ namespace MWScript ///< Return locals for script \a name. GlobalScripts& getGlobalScripts(); + + int getLocalIndex (const std::string& scriptId, const std::string& variable, char type); + ///< Return index of the variable of the given name and type in the given script. Will + /// throw an exception, if there is no such script or variable or the type does not match. }; }; diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 973b22d35..4221da36e 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -65,6 +65,19 @@ namespace Interpreter virtual void enable (const std::string& id = "") = 0; virtual void disable (const std::string& id = "") = 0; + + virtual int getMemberShort (const std::string& id, const std::string& name) const = 0; + + virtual int getMemberLong (const std::string& id, const std::string& name) const = 0; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const = 0; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberLong (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value) + = 0; }; } From 6ec2a2091c6a5d63349542a182cef502fc9ba78a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 12:16:03 +0200 Subject: [PATCH 241/289] Issue #305: Allow the use of = as a synonym for == --- components/compiler/scanner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 080ca7d98..d0397e8cf 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -368,8 +368,10 @@ namespace Compiler special = S_cmpEQ; else { + special = S_cmpEQ; putback (c); - return false; +// return false; +// Allow = as synonym for ==. \todo optionally disable for post-1.0 scripting improvements. } } else From ff84fbbfa70725daadee5b22d9e73124dd67888a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 12:36:51 +0200 Subject: [PATCH 242/289] Added DontSaveObject script instruction We are ignoring it for now and unless users protest we will probably keep it that way. --- apps/openmw/mwscript/docs/vmformat.txt | 1 + apps/openmw/mwscript/miscextensions.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index de7248c0c..4423f17cf 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -146,4 +146,5 @@ op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye +op 0x2000153: DontSaveObject (left unimplemented) opcodes 0x2000154-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 4ba523937..c7569ccdd 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -194,6 +194,17 @@ namespace MWScript } }; + class OpDontSaveObject : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + // We are ignoring the DontSaveObject statement for now. Probably not worth + /// bothering with. The incompatibility we are creating should be marginal at most. + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -208,6 +219,7 @@ namespace MWScript const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; + const int opcodeDontSaveObject = 0x2000153; void registerExtensions (Compiler::Extensions& extensions) { @@ -229,6 +241,7 @@ namespace MWScript extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); + extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -247,6 +260,7 @@ namespace MWScript interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); + interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject); } } } From ce43ff8d0520729e4d36e7b3fd40e7460d3e2909 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Jun 2012 13:56:49 +0200 Subject: [PATCH 243/289] Issue #181: added member variable access opcodes --- components/interpreter/docs/vmformat.txt | 8 +- components/interpreter/installopcodes.cpp | 6 + components/interpreter/localopcodes.hpp | 217 ++++++++++++++++------ 3 files changed, 178 insertions(+), 53 deletions(-) diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 3e513aa44..91e0c060e 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -121,5 +121,11 @@ op 58: report string literal index in stack[0]; additional arguments (if any) in stack[n]..stack[1]; n is determined according to the message string all arguments are removed from stack -opcodes 59-33554431 unused +op 59: store stack[0] in member short stack[2] of object with ID stack[1] +op 60: store stack[0] in member long stack[2] of object with ID stack[1] +op 61: store stack[0] in member float stack[2] of object with ID stack[1] +op 62: replace stack[0] with member short stack[1] of object with ID stack[0] +op 63: replace stack[0] with member short stack[1] of object with ID stack[0] +op 64: replace stack[0] with member short stack[1] of object with ID stack[0] +opcodes 65-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 556477af2..05f71f1cc 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -40,6 +40,12 @@ namespace Interpreter interpreter.installSegment5 (42, new OpFetchGlobalShort); interpreter.installSegment5 (43, new OpFetchGlobalLong); interpreter.installSegment5 (44, new OpFetchGlobalFloat); + interpreter.installSegment5 (59, new OpStoreMemberShort); + interpreter.installSegment5 (60, new OpStoreMemberLong); + interpreter.installSegment5 (61, new OpStoreMemberFloat); + interpreter.installSegment5 (62, new OpFetchMemberShort); + interpreter.installSegment5 (63, new OpFetchMemberLong); + interpreter.installSegment5 (64, new OpFetchMemberFloat); // math interpreter.installSegment5 (9, new OpAddInt); diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index ea62b7ad8..852fa7099 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -6,11 +6,11 @@ #include "context.hpp" namespace Interpreter -{ +{ class OpStoreLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -20,13 +20,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -36,13 +36,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -52,71 +52,71 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchIntLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger); runtime[0].mInteger = intValue; - } - }; - + } + }; + class OpFetchFloatLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger); runtime[0].mFloat = floatValue; - } - }; - + } + }; + class OpFetchLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; int value = runtime.getContext().getLocalShort (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; int value = runtime.getContext().getLocalLong (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; float value = runtime.getContext().getLocalFloat (index); runtime[0].mFloat = value; - } - }; - + } + }; + class OpStoreGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -128,13 +128,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -146,13 +146,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -164,48 +164,161 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalShort (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalLong (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Float value = runtime.getContext().getGlobalFloat (name); runtime[0].mFloat = value; - } - }; + } + }; + + class OpStoreMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberShort (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberLong (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + Type_Float data = runtime[1].mFloat; + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberFloat (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpFetchMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + int value = runtime.getContext().getMemberShort (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + int value = runtime.getContext().getMemberLong (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + index = runtime[0].mInteger; + float value = runtime.getContext().getMemberFloat (id, variable); + runtime[0].mFloat = value; + } + }; } #endif - From 7354d1eccb4dcd6a432ca88588c1d0ada911d72a Mon Sep 17 00:00:00 2001 From: Sylvain THESNIERES Date: Fri, 8 Jun 2012 19:54:12 +0200 Subject: [PATCH 244/289] CMake fixes: - Fix environment variable in Bullet - Remove spurious message in MyGUI --- cmake/FindBullet.cmake | 2 ++ cmake/FindMyGUI.cmake | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/FindBullet.cmake b/cmake/FindBullet.cmake index 552a0651a..8d5ea2f1e 100644 --- a/cmake/FindBullet.cmake +++ b/cmake/FindBullet.cmake @@ -19,6 +19,8 @@ # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. +set(BULLET_ROOT $ENV{BULLET_ROOT}) + macro(_FIND_BULLET_LIBRARY _var) find_library(${_var} NAMES diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index c79ee5998..7278fe200 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -22,7 +22,7 @@ IF (WIN32) #Windows SET(MYGUISDK $ENV{MYGUI_HOME}) IF (MYGUISDK) findpkg_begin ( "MYGUI" ) - MESSAGE(STATUS "Using MyGUI in OGRE SDK") + MESSAGE(STATUS "Using MyGUI in MyGUI SDK") STRING(REGEX REPLACE "[\\]" "/" MYGUISDK "${MYGUISDK}" ) find_path ( MYGUI_INCLUDE_DIRS @@ -35,7 +35,7 @@ MyGUI_OgrePlatform.h "${MYGUISDK}/Platforms/Ogre/OgrePlatform/include" NO_DEFAULT_PATH ) -SET ( MYGUI_LIB_DIR ${MYGUISDK}/*/lib ) +SET ( MYGUI_LIB_DIR ${MYGUISDK}/lib ${MYGUISDK}/*/lib ) find_library ( MYGUI_LIBRARIES_REL NAMES MyGUIEngine.lib @@ -69,7 +69,7 @@ make_library_set ( MYGUI_PLATFORM_LIBRARIES ) MESSAGE ("${MYGUI_LIBRARIES}") MESSAGE ("${MYGUI_PLATFORM_LIBRARIES}") -findpkg_finish ( "MYGUI" ) +#findpkg_finish ( "MYGUI" ) ENDIF (MYGUISDK) IF (OGRESOURCE) From fc3a3fc173ce4dc04685bb9ced2e0e4faf0fb556 Mon Sep 17 00:00:00 2001 From: Sylvain THESNIERES Date: Fri, 8 Jun 2012 19:55:39 +0200 Subject: [PATCH 245/289] MSVC build compliance: - static const float member is not ISO - callback do not match DLL signature --- apps/openmw/mwgui/settingswindow.hpp | 8 ++++---- apps/openmw/mwsound/audiere_decoder.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index ce95edbd2..e3827c7b0 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -16,10 +16,10 @@ namespace MWGui SettingsWindow(WindowManager& parWindowManager); private: - static const float sFovMin = 30; - static const float sFovMax = 140; - static const float sViewDistMin = 2000; - static const float sViewDistMax = 5600; + static int const sFovMin = 30; + static int const sFovMax = 140; + static int const sViewDistMin = 2000; + static int const sViewDistMax = 5600; protected: MyGUI::Button* mOkButton; diff --git a/apps/openmw/mwsound/audiere_decoder.cpp b/apps/openmw/mwsound/audiere_decoder.cpp index acc2e5283..4e73573a7 100644 --- a/apps/openmw/mwsound/audiere_decoder.cpp +++ b/apps/openmw/mwsound/audiere_decoder.cpp @@ -41,8 +41,8 @@ class OgreFile : public audiere::File } size_t refs; - virtual void ref() { ++refs; } - virtual void unref() + ADR_METHOD(void) ref() { ++refs; } + ADR_METHOD(void) unref() { if(--refs == 0) delete this; From 0c7476b88c91f7143708d17c1f63a658846d0d39 Mon Sep 17 00:00:00 2001 From: Sylvain THESNIERES Date: Fri, 8 Jun 2012 19:56:27 +0200 Subject: [PATCH 246/289] Fix build in DEBUG mode for MSVC - commented stall code --- libs/openengine/bullet/pmove.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp index 591f1869f..5cf0951c0 100644 --- a/libs/openengine/bullet/pmove.cpp +++ b/libs/openengine/bullet/pmove.cpp @@ -1833,13 +1833,13 @@ void PmoveSingle (playerMove* const pmove) pml.hasWater = pmove->hasWater; pml.isInterior = pmove->isInterior; pml.waterHeight = pmove->waterHeight; -#ifdef _DEBUG - if (!pml.traceObj) - __debugbreak(); - - if (!pml.traceObj->incellptr) - __debugbreak(); -#endif +//#ifdef _DEBUG + //if (!pml.traceObj) + // __debugbreak(); + // + //if (!pml.traceObj->incellptr) + // __debugbreak(); +//#endif // determine the time pml.msec = pmove->cmd.serverTime - pm->ps.commandTime; From 447158e9d62540f9386fdc024460e493afbfc7f4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 9 Jun 2012 19:15:11 +0200 Subject: [PATCH 247/289] shutdown crash fix --- apps/openmw/mwrender/renderingmanager.cpp | 2 ++ apps/openmw/mwrender/water.cpp | 3 +++ libs/openengine/ogre/renderer.cpp | 5 +++++ libs/openengine/ogre/renderer.hpp | 1 + 4 files changed, 11 insertions(+) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a771eb12e..266362f9b 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -112,6 +112,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const RenderingManager::~RenderingManager () { + mRendering.removeWindowEventListener(this); + delete mPlayer; delete mSkyManager; delete mDebugging; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index b4486a0ca..dc9e1fbee 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -114,6 +114,9 @@ Water::~Water() { MeshManager::getSingleton().remove("water"); + if (mReflectionTarget) + mReflectionTexture->getBuffer()->getRenderTarget()->removeListener(this); + mWaterNode->detachObject(mWater); mSceneManager->destroyEntity(mWater); mSceneManager->destroySceneNode(mWaterNode); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index fadfa8d8c..7c0f88bd7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -156,6 +156,11 @@ void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } +void OgreRenderer::removeWindowEventListener(Ogre::WindowEventListener* listener) +{ + Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); +} + void OgreRenderer::setFov(float fov) { mCamera->setFOVy(Degree(fov)); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index f188e2051..f1520a3db 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -106,6 +106,7 @@ namespace OEngine ~OgreRenderer() { cleanup(); } void setWindowEventListener(Ogre::WindowEventListener* listener); + void removeWindowEventListener(Ogre::WindowEventListener* listener); /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ From 0bcec32c70dceb33142302a2ee7048b6bb3e0881 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 11 Jun 2012 02:50:29 +0200 Subject: [PATCH 248/289] Changed launcher logo to the new one done by Necrod --- .../resources/images/openmw-header.png | Bin 50727 -> 51091 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/launcher/resources/images/openmw-header.png b/apps/launcher/resources/images/openmw-header.png index a2ffab68b8b447193d1153950e5c4d7f43348641..98c0cbe6fd3d52dbb24a844a235328aa676d365a 100644 GIT binary patch literal 51091 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 A@c;k- literal 50727 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 Ai~s-t From 82fba53771b6048d80f268a6d36b51cd2455b7cb Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Wed, 13 Jun 2012 14:58:27 +0200 Subject: [PATCH 249/289] Removed the license screen and changed so all licenses are instead installed to the game folder. --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e11ad0c0a..b83935bdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,6 +370,10 @@ if(WIN32) INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" "${OpenMW_SOURCE_DIR}/readme.txt" + "${OpenMW_SOURCE_DIR}/GPL3.txt" + "${OpenMW_SOURCE_DIR}/OFL.txt" + "${OpenMW_SOURCE_DIR}/Bitstream Vera License.txt" + "${OpenMW_SOURCE_DIR}/Daedric Font License.txt" "${OpenMW_BINARY_DIR}/launcher.qss" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" @@ -391,8 +395,8 @@ if(WIN32) !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\" ") + SET(CPACK_RESOURCE_FILE_README "${OpenMW_SOURCE_DIR}/readme.txt") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt") - SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt") SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") SET(CPACK_NSIS_DISPLAY_NAME "OpenMW") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") From 9f84518910a3dd8bdfb47435d9caadd819c962aa Mon Sep 17 00:00:00 2001 From: Sylvain THESNIERES Date: Thu, 14 Jun 2012 08:09:03 +0200 Subject: [PATCH 250/289] Remove dead code Object class is quake specific stuff and these parts were *dead*. There is more references to the pointer but it is commented and seems to be used as "reference code" for future implementation of player functions, so I prefered not touching them. --- libs/openengine/bullet/pmove.cpp | 10 ---------- libs/openengine/bullet/pmove.h | 1 - 2 files changed, 11 deletions(-) diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp index 5cf0951c0..b723f67e4 100644 --- a/libs/openengine/bullet/pmove.cpp +++ b/libs/openengine/bullet/pmove.cpp @@ -15,8 +15,6 @@ Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc. //#include "GameTime.h" -//#include "Object.h" - //#include "Sound.h" //#include "..\..\ESMParser\ESMParser\SNDG.h" @@ -68,7 +66,6 @@ static struct playermoveLocal int waterHeight; bool hasWater; bool isInterior; - //Object* traceObj; } pml; @@ -1833,13 +1830,6 @@ void PmoveSingle (playerMove* const pmove) pml.hasWater = pmove->hasWater; pml.isInterior = pmove->isInterior; pml.waterHeight = pmove->waterHeight; -//#ifdef _DEBUG - //if (!pml.traceObj) - // __debugbreak(); - // - //if (!pml.traceObj->incellptr) - // __debugbreak(); -//#endif // determine the time pml.msec = pmove->cmd.serverTime - pm->ps.commandTime; diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h index e46eb9d2e..6cedd3599 100644 --- a/libs/openengine/bullet/pmove.h +++ b/libs/openengine/bullet/pmove.h @@ -190,7 +190,6 @@ struct playerMove int waterHeight; bool hasWater; bool isInterior; - //Object* traceObj; OEngine::Physic::PhysicEngine* mEngine; }; From e4984955894d5c0593e966f454bda5bb7d095dec Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Jun 2012 21:27:55 +0200 Subject: [PATCH 251/289] fix a leak: physics heightfield was only destroyed on cell change and not on exit --- libs/openengine/bullet/physic.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index a94434e5b..354b4d589 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -222,6 +222,14 @@ namespace Physic PhysicEngine::~PhysicEngine() { + HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin(); + for (; hf_it != mHeightFieldMap.end(); ++hf_it) + { + dynamicsWorld->removeRigidBody(hf_it->second.mBody); + delete hf_it->second.mShape; + delete hf_it->second.mBody; + } + RigidBodyContainer::iterator rb_it = RigidBodyMap.begin(); for (; rb_it != RigidBodyMap.end(); ++rb_it) { From 0b850a2cb5280114fd003b3b8f6d6c899e9fb11b Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 15 Jun 2012 09:15:37 +0200 Subject: [PATCH 252/289] fix crash introduced by last commit --- libs/openengine/bullet/physic.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 354b4d589..f7caa54b4 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -328,6 +328,8 @@ namespace Physic dynamicsWorld->removeRigidBody(hf.mBody); delete hf.mShape; delete hf.mBody; + + mHeightFieldMap.erase(name); } RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) From 584ae30213b27c37b2534cb2036406af7193c0be Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 15 Jun 2012 10:09:46 +0200 Subject: [PATCH 253/289] don't show diseases and curses in the spell list --- apps/openmw/mwgui/spellwindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index d34ce68d9..909798f1a 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -144,9 +144,11 @@ namespace MWGui powers.push_back(*it); it = spellList.erase(it); } - else if (spell->data.type == ESM::Spell::ST_Ability) + else if (spell->data.type == ESM::Spell::ST_Ability + || spell->data.type == ESM::Spell::ST_Blight + || spell->data.type == ESM::Spell::ST_Curse + || spell->data.type == ESM::Spell::ST_Disease) { - // abilities are always active and don't show in the spell window. it = spellList.erase(it); } else From 7caf72760624d0b84bc83bf18028db3989776599 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 15 Jun 2012 17:43:23 +0200 Subject: [PATCH 254/289] added new contributor to readme file --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 513474dd6..4cc31343b 100644 --- a/readme.txt +++ b/readme.txt @@ -110,6 +110,7 @@ Nikolay “corristo” Kasyanov Pieter “pvdk” van der Kloet Roman "Kromgart" Melnik Sebastian “swick” Wick +Sylvain "Garvek" T. Retired Developers: Ardekantur From 050559d2e2f20883faa15aa7426369d0189d8627 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 10:31:33 +0200 Subject: [PATCH 255/289] Issue #181: added member variable access token --- components/compiler/scanner.cpp | 2 ++ components/compiler/scanner.hpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index d0397e8cf..962699dfa 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -360,6 +360,8 @@ namespace Compiler special = S_open; else if (c==')') special = S_close; + else if (c=='.') + special = S_member; else if (c=='=') { if (get (c)) diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 53cb92ef2..19f4ca96a 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -65,7 +65,8 @@ namespace Compiler S_cmpEQ, S_cmpNE, S_cmpLT, S_cmpLE, S_cmpGT, S_cmpGE, S_plus, S_minus, S_mult, S_div, S_comma, - S_ref + S_ref, + S_member }; private: From d1441d79e7611f7a226a816b317bc005b217b048 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 10:49:34 +0200 Subject: [PATCH 256/289] Issue #181: added code generation for member variable access --- components/compiler/generator.cpp | 112 +++++++++++++++++++++++++++++- components/compiler/generator.hpp | 6 ++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 26a80387b..b619ad67a 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -260,6 +260,36 @@ namespace code.push_back (Compiler::Generator::segment5 (44)); } + void opStoreMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (59)); + } + + void opStoreMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (60)); + } + + void opStoreMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (61)); + } + + void opFetchMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (62)); + } + + void opFetchMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (63)); + } + + void opFetchMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (64)); + } + void opRandom (Compiler::Generator::CodeContainer& code) { code.push_back (Compiler::Generator::segment5 (45)); @@ -644,7 +674,7 @@ namespace Compiler if (localType!=valueType) { - if (localType=='f' && valueType=='l') + if (localType=='f' && (valueType=='l' || valueType=='s')) { opIntToFloat (code); } @@ -707,6 +737,86 @@ namespace Compiler } } + void assignToMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + opPushInt (code, index); + + std::copy (value.begin(), value.end(), std::back_inserter (code)); + + if (localType!=valueType) + { + if (localType=='f' && (valueType=='l' || valueType=='s')) + { + opIntToFloat (code); + } + else if ((localType=='l' || localType=='s') && valueType=='f') + { + opFloatToInt (code); + } + } + + switch (localType) + { + case 'f': + + opStoreMemberFloat (code); + break; + + case 's': + + opStoreMemberShort (code); + break; + + case 'l': + + opStoreMemberLong (code); + break; + + default: + + assert (0); + } + } + + void fetchMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + switch (localType) + { + case 'f': + + opFetchMemberFloat (code); + break; + + case 's': + + opFetchMemberShort (code); + break; + + case 'l': + + opFetchMemberLong (code); + break; + + default: + + assert (0); + } + } + void random (CodeContainer& code) { opRandom (code); diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 89e198431..feab26c93 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -101,6 +101,12 @@ namespace Compiler void fetchGlobal (CodeContainer& code, Literals& literals, char localType, const std::string& name); + void assignToMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType); + + void fetchMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id); + void random (CodeContainer& code); void scriptRunning (CodeContainer& code); From 6a89d76321f415942872f9c4bbdbb4e7c43f49a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 11:52:35 +0200 Subject: [PATCH 257/289] Issue #181: Improved script error reporting for local and global scripts --- apps/openmw/mwscript/scriptmanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 6ae506483..67414a06f 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "extensions.hpp" @@ -46,8 +47,13 @@ namespace MWScript if (!mErrorHandler.isGood()) Success = false; } - catch (...) + catch (const Compiler::SourceException&) { + // error has already been reported via error handler + } + catch (const std::exception& error) + { + std::cerr << "An exception has been thrown: " << error.what() << std::endl; Success = false; } From 6c5b21fa42dcd7e66ff8640e146cbb0fc86e3649 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:06:23 +0200 Subject: [PATCH 258/289] Issue #181: Member variable access in expressions; error reporting fix for the previous commit --- apps/openmw/mwscript/compilercontext.cpp | 14 +++++++++ apps/openmw/mwscript/compilercontext.hpp | 3 ++ apps/openmw/mwscript/scriptmanager.cpp | 4 +++ components/compiler/context.hpp | 20 +++++++------ components/compiler/exprparser.cpp | 37 ++++++++++++++++++++++-- components/compiler/exprparser.hpp | 3 ++ 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 078d0da5e..0a6ffd0c7 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -5,6 +5,8 @@ #include "../mwworld/world.hpp" +#include "scriptmanager.hpp" + namespace MWScript { CompilerContext::CompilerContext (Type type) @@ -21,6 +23,18 @@ namespace MWScript return MWBase::Environment::get().getWorld()->getGlobalVariableType (name); } + char CompilerContext::getMemberType (const std::string& name, const std::string& id) const + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (script.empty()) + return ' '; + + return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name); + } + bool CompilerContext::isId (const std::string& name) const { return diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 32b2f1881..5ec98e09a 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -30,6 +30,9 @@ namespace MWScript /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; + virtual char getMemberType (const std::string& name, const std::string& id) const; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + virtual bool isId (const std::string& name) const; ///< Does \a name match an ID, that can be referenced? }; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 67414a06f..d8bd269c6 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -50,6 +50,7 @@ namespace MWScript catch (const Compiler::SourceException&) { // error has already been reported via error handler + Success = false; } catch (const std::exception& error) { @@ -146,6 +147,9 @@ namespace MWScript { if (!compile (name)) { + /// \todo Handle case of cyclic member variable access. Currently this could look up + /// the whole application in an endless recursion. + // failed -> ignore script from now on. std::vector empty; mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index 929119cf4..1b02613c5 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -10,33 +10,35 @@ namespace Compiler class Context { const Extensions *mExtensions; - + public: - + Context() : mExtensions (0) {} - + virtual ~Context() {} - + virtual bool canDeclareLocals() const = 0; ///< Is the compiler allowed to declare local variables? - + void setExtensions (const Extensions *extensions = 0) { mExtensions = extensions; } - + const Extensions *getExtensions() const { return mExtensions; } - + virtual char getGlobalType (const std::string& name) const = 0; ///< 'l: long, 's': short, 'f': float, ' ': does not exist. - + + virtual char getMemberType (const std::string& name, const std::string& id) const = 0; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + virtual bool isId (const std::string& name) const = 0; ///< Does \a name match an ID, that can be referenced? }; } #endif - diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 95480c023..8041a7c8a 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -195,10 +195,31 @@ namespace Compiler return parseArguments (arguments, scanner, mCode); } + bool ExprParser::handleMemberAccess (const std::string& name) + { + mMemberOp = false; + + std::string name2 = toLower (name); + std::string id = toLower (mExplicit); + + char type = getContext().getMemberType (name2, id); + + if (type!=' ') + { + Generator::fetchMember (mCode, mLiterals, type, name2, id); + mNextOperand = false; + mExplicit.clear(); + mOperands.push_back (type=='f' ? 'f' : 'l'); + return true; + } + + return false; + } + ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals, bool argument) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), - mNextOperand (true), mFirst (true), mArgument (argument) + mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false) {} bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) @@ -251,7 +272,12 @@ namespace Compiler Scanner& scanner) { if (!mExplicit.empty()) + { + if (mMemberOp && handleMemberAccess (name)) + return true; + return Parser::parseName (name, loc, scanner); + } mFirst = false; @@ -281,7 +307,7 @@ namespace Compiler return true; } - if (mExplicit.empty() && getContext().isId (name)) + if (mExplicit.empty() && getContext().isId (name2)) { mExplicit = name; return true; @@ -497,6 +523,12 @@ namespace Compiler return true; } + if (!mMemberOp && code==Scanner::S_member) + { + mMemberOp = true; + return true; + } + return Parser::parseSpecial (code, loc, scanner); } @@ -609,6 +641,7 @@ namespace Compiler mFirst = true; mExplicit.clear(); mRefOp = false; + mMemberOp = false; Parser::reset(); } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 87945c628..8ce5409d2 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -26,6 +26,7 @@ namespace Compiler bool mArgument; std::string mExplicit; bool mRefOp; + bool mMemberOp; int getPriority (char op) const; @@ -53,6 +54,8 @@ namespace Compiler int parseArguments (const std::string& arguments, Scanner& scanner); + bool handleMemberAccess (const std::string& name); + public: ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, From 8b19de17b6371d4cb2afa647c39dca69209b24eb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:21:01 +0200 Subject: [PATCH 259/289] Iisue #181: enable member variable access from expressions in console --- components/compiler/lineparser.cpp | 17 ++++++++++++++++- components/compiler/lineparser.hpp | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 834cd27b4..db21cce9b 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -18,7 +18,10 @@ namespace Compiler if (!mExplicit.empty()) { mExprParser.parseName (mExplicit, loc, scanner); - mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); + if (mState==MemberState) + mExprParser.parseSpecial (Scanner::S_member, loc, scanner); + else + mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); } scanner.scan (mExprParser); @@ -256,6 +259,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } @@ -269,6 +273,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -342,6 +347,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -366,6 +372,14 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==PotentialExplicitState) + { + mState = MemberState; + parseExpression (scanner, loc); + mState = EndState; + return true; + } + if (code==Scanner::S_newline && mState==MessageButtonState) { Generator::message (mCode, mLiterals, mName, mButtons); @@ -383,6 +397,7 @@ namespace Compiler { scanner.putbackSpecial (code, loc); parseExpression (scanner, loc); + mState = EndState; return true; } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 531b7762f..6f331b7bf 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -24,7 +24,7 @@ namespace Compiler SetState, SetLocalVarState, SetGlobalVarState, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, EndState, - PotentialExplicitState, ExplicitState + PotentialExplicitState, ExplicitState, MemberState }; Locals& mLocals; From 10b27e582b5e0959db0219e91aa82aa7a9d5f567 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 13:51:13 +0200 Subject: [PATCH 260/289] Issue #181: various fixed to member variable access --- apps/openmw/mwscript/interpretercontext.cpp | 12 ++++++++++++ components/compiler/generator.cpp | 2 ++ components/interpreter/localopcodes.hpp | 3 --- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 55059b522..152fcf85c 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -278,6 +278,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mShorts[index]; } @@ -289,6 +291,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mLongs[index]; } @@ -300,6 +304,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); return ptr.getRefData().getLocals().mFloats[index]; } @@ -311,6 +317,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mShorts[index] = value; } @@ -322,6 +330,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mLongs[index] = value; } @@ -333,6 +343,8 @@ namespace MWScript int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); ptr.getRefData().getLocals().mFloats[index] = value; } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index b619ad67a..9b02e4273 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -794,6 +794,8 @@ namespace Compiler index = literals.addString (id); + opPushInt (code, index); + switch (localType) { case 'f': diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 852fa7099..4b0edff9c 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -278,7 +278,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; int value = runtime.getContext().getMemberShort (id, variable); runtime[0].mInteger = value; } @@ -296,7 +295,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; int value = runtime.getContext().getMemberLong (id, variable); runtime[0].mInteger = value; } @@ -314,7 +312,6 @@ namespace Interpreter std::string variable = runtime.getStringLiteral (index); runtime.pop(); - index = runtime[0].mInteger; float value = runtime.getContext().getMemberFloat (id, variable); runtime[0].mFloat = value; } From fe85de5ea7d7cebf0d09ffccfc7a5f9e76a34caf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 14:29:55 +0200 Subject: [PATCH 261/289] Issue #181: assignment to member variables --- components/compiler/lineparser.cpp | 39 +++++++++++++++++++++++-- components/compiler/lineparser.hpp | 4 ++- components/interpreter/localopcodes.hpp | 4 +-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index db21cce9b..a4cbc1ffe 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -113,12 +113,13 @@ namespace Compiler if (mState==SetState) { std::string name2 = toLower (name); + mName = name2; // local variable? char type = mLocals.getType (name2); if (type!=' ') { - mName = name2; + mType = type; mState = SetLocalVarState; return true; } @@ -126,12 +127,27 @@ namespace Compiler type = getContext().getGlobalType (name2); if (type!=' ') { - mName = name2; mType = type; mState = SetGlobalVarState; return true; } + mState = SetPotentialMemberVarState; + return true; + } + + if (mState==SetMemberVarState) + { + mMemberName = toLower (name); + char type = getContext().getMemberType (mMemberName, mName); + + if (type!=' ') + { + mState = SetMemberVarState2; + mType = type; + return true; + } + getErrorHandler().error ("unknown variable", loc); SkipParser skip (getErrorHandler(), getContext()); scanner.scan (skip); @@ -338,6 +354,19 @@ namespace Compiler mState = EndState; return true; } + else if (mState==SetMemberVarState2 && keyword==Scanner::K_to) + { + mExprParser.reset(); + scanner.scan (mExprParser); + + std::vector code; + char type = mExprParser.append (code); + + Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type); + + mState = EndState; + return true; + } if (mAllowExpression) { @@ -392,6 +421,12 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==SetPotentialMemberVarState) + { + mState = SetMemberVarState; + return true; + } + if (mAllowExpression && mState==BeginState && (code==Scanner::S_open || code==Scanner::S_minus)) { diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 6f331b7bf..aa74cd232 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -21,7 +21,8 @@ namespace Compiler { BeginState, ShortState, LongState, FloatState, - SetState, SetLocalVarState, SetGlobalVarState, + SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState, + SetMemberVarState, SetMemberVarState2, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, EndState, PotentialExplicitState, ExplicitState, MemberState @@ -32,6 +33,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + std::string mMemberName; int mButtons; std::string mExplicit; char mType; diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 4b0edff9c..731c16276 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -252,9 +252,9 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - Type_Integer index = runtime[0].mInteger; + Type_Float data = runtime[0].mFloat; + Type_Integer index = runtime[1].mInteger; std::string id = runtime.getStringLiteral (index); - Type_Float data = runtime[1].mFloat; index = runtime[2].mInteger; std::string variable = runtime.getStringLiteral (index); From 3167ae9473e49ad1720fd398329077db7d02ca54 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 15:49:03 +0200 Subject: [PATCH 262/289] added force/clearforce instructions for run and sneak --- apps/openmw/mwscript/controlextensions.cpp | 87 ++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 10 ++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 363a09b6b..1a7b45246 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -11,7 +11,10 @@ #include "../mwworld/player.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "interpretercontext.hpp" +#include "ref.hpp" #include @@ -54,11 +57,71 @@ namespace MWScript } }; + template + class OpClearForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = false; + } + }; + + template + class OpForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = true; + } + }; + + template + class OpClearForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = false; + } + }; + + template + class OpForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = true; + } + }; + const int numberOfControls = 7; const int opcodeEnable = 0x200007e; const int opcodeDisable = 0x2000085; const int opcodeToggleCollision = 0x2000130; + const int opcodeClearForceRun = 0x2000154; + const int opcodeClearForceRunExplicit = 0x2000155; + const int opcodeForceRun = 0x2000156; + const int opcodeForceRunExplicit = 0x2000157; + const int opcodeClearForceSneak = 0x2000158; + const int opcodeClearForceSneakExplicit = 0x2000159; + const int opcodeForceSneak = 0x200015a; + const int opcodeForceSneakExplicit = 0x200015b; const char *controls[numberOfControls] = { @@ -79,6 +142,16 @@ namespace MWScript extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision); extensions.registerInstruction ("tcl", "", opcodeToggleCollision); + + extensions.registerInstruction ("clearforcerun", "", opcodeClearForceRun, + opcodeClearForceRunExplicit); + extensions.registerInstruction ("forcerun", "", opcodeForceRun, + opcodeForceRunExplicit); + + extensions.registerInstruction ("clearforcesneak", "", opcodeClearForceSneak, + opcodeClearForceSneakExplicit); + extensions.registerInstruction ("forcesneak", "", opcodeForceSneak, + opcodeForceSneakExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -90,6 +163,20 @@ namespace MWScript } interpreter.installSegment5 (opcodeToggleCollision, new OpToggleCollision); + + interpreter.installSegment5 (opcodeClearForceRun, new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRun, new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneak, new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneak, new OpForceSneak); + + interpreter.installSegment5 (opcodeClearForceRunExplicit, + new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRunExplicit, + new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneakExplicit, + new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneakExplicit, + new OpForceSneak); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 4423f17cf..eb13a8722 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -147,4 +147,12 @@ op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye op 0x2000153: DontSaveObject (left unimplemented) -opcodes 0x2000154-0x3ffffff unused +op 0x2000154: ClearForceRun +op 0x2000155: ClearForceRun, explicit reference +op 0x2000156: ForceRun +op 0x2000156: ForceRun, explicit reference +op 0x2000157: ClearForceSneak +op 0x2000158: ClearForceSneak, explicit reference +op 0x2000159: ForceSneak +op 0x200015a: ForceSneak, explicit reference +opcodes 0x200015b-0x3ffffff unused From b16157a618115214b3b5f19e1a49287470a5765c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 15:49:39 +0200 Subject: [PATCH 263/289] documentation fix --- apps/openmw/mwscript/docs/vmformat.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index eb13a8722..219af9a0b 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -150,9 +150,9 @@ op 0x2000153: DontSaveObject (left unimplemented) op 0x2000154: ClearForceRun op 0x2000155: ClearForceRun, explicit reference op 0x2000156: ForceRun -op 0x2000156: ForceRun, explicit reference -op 0x2000157: ClearForceSneak -op 0x2000158: ClearForceSneak, explicit reference -op 0x2000159: ForceSneak -op 0x200015a: ForceSneak, explicit reference +op 0x2000157: ForceRun, explicit reference +op 0x2000158: ClearForceSneak +op 0x2000159: ClearForceSneak, explicit reference +op 0x200015a: ForceSneak +op 0x200015b: ForceSneak, explicit reference opcodes 0x200015b-0x3ffffff unused From 7454713a9be6fdfc4ede96f52b787423e941d4a0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:06:15 +0200 Subject: [PATCH 264/289] addet provisional implementation of AiWander (doesn't do anything yet) --- apps/openmw/mwscript/aiextensions.cpp | 30 ++++++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index aa541e55d..54a67a8cd 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -88,7 +88,31 @@ namespace MWScript } }; + template + class OpAiWander : public Interpreter::Opcode1 + { + public: + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + +// Interpreter::Type_Float range = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float duration = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float time = runtime[0].mFloat; + runtime.pop(); + + // discard additional idle arguments for now + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i); interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort); interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscort); + interpreter.installSegment3 (opcodeAiWander, new OpAiWander); + interpreter.installSegment3 (opcodeAiWanderExplicit, new OpAiWander); interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 219af9a0b..7faba7f41 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -29,7 +29,9 @@ op 0x2000c: PCLowerRank op 0x2000d: PCJoinFaction op 0x2000e: PCGetRank implicit op 0x2000f: PCGetRank explicit -opcodes 0x20010-0x3ffff unused +op 0x20010: AiWander +op 0x20011: AiWander, explicit reference +opcodes 0x20012-0x3ffff unused Segment 4: (not implemented yet) From ea29b74bb439a9ea5a73210c60a2fe30705e0bb6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:17:42 +0200 Subject: [PATCH 265/289] added per NPC/creature basic AI-settings (hello, fight, flee, alarm) --- apps/openmw/mwclass/creature.cpp | 5 +++++ apps/openmw/mwclass/npc.cpp | 7 ++++++- apps/openmw/mwmechanics/creaturestats.hpp | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e33fd322a..c9b43896b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -57,6 +57,11 @@ namespace MWClass data->mCreatureStats.mLevel = ref->base->data.level; + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4c964c700..f30e164f9 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -70,12 +70,12 @@ namespace MWClass } } + // creature stats if(ref->base->npdt52.gold != -10) { for (int i=0; i<27; ++i) data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]); - // creature stats data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength); data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence); data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower); @@ -95,6 +95,11 @@ namespace MWClass /// \todo do something with npdt12 maybe:p } + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index cc3c409da..8d40e1942 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -19,6 +19,10 @@ namespace MWMechanics Spells mSpells; ActiveSpells mActiveSpells; MagicEffects mMagicEffects; + int mHello; + int mFight; + int mFlee; + int mAlarm; }; } From 8283f5f13597420ab83417951c89498ffa2043ef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:31:32 +0200 Subject: [PATCH 266/289] added setHello/Fight/Flee/Alarm instructions --- apps/openmw/mwscript/aiextensions.cpp | 88 ++++++++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 10 ++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 54a67a8cd..08b1f6f8c 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwmechanics/creaturestats.hpp" + #include "interpretercontext.hpp" #include "ref.hpp" @@ -114,6 +116,71 @@ namespace MWScript } }; + template + class OpSetHello : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mHello = value; + } + }; + + template + class OpSetFight : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFight = value; + } + }; + + template + class OpSetFlee : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFlee = value; + } + }; + + template + class OpSetAlarm : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mAlarm = value; + } + }; + + const int opcodeAiTravel = 0x20000; const int opcodeAiTravelExplicit = 0x20001; const int opcodeAiEscort = 0x20002; @@ -122,6 +189,14 @@ namespace MWScript const int opcodeGetAiPackageDoneExplicit = 0x200007d; const int opcodeAiWander = 0x20010; const int opcodeAiWanderExplicit = 0x20011; + const int opcodeSetHello = 0x200015e; + const int opcodeSetHelloExplicit = 0x200015d; + const int opcodeSetFight = 0x200015e; + const int opcodeSetFightExplicit = 0x200015f; + const int opcodeSetFlee = 0x2000160; + const int opcodeSetFleeExplicit = 0x2000161; + const int opcodeSetAlarm = 0x2000162; + const int opcodeSetAlarmExplicit = 0x2000163; void registerExtensions (Compiler::Extensions& extensions) { @@ -134,6 +209,11 @@ namespace MWScript extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone, opcodeGetAiPackageDoneExplicit); + + extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit); + extensions.registerInstruction ("setfight", "l", opcodeSetFight, opcodeSetFightExplicit); + extensions.registerInstruction ("setflee", "l", opcodeSetFlee, opcodeSetFleeExplicit); + extensions.registerInstruction ("setalarm", "l", opcodeSetAlarm, opcodeSetAlarmExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -147,6 +227,14 @@ namespace MWScript interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); + interpreter.installSegment5 (opcodeSetHello, new OpSetHello); + interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello); + interpreter.installSegment5 (opcodeSetFight, new OpSetFight); + interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetFight); + interpreter.installSegment5 (opcodeSetFlee, new OpSetFlee); + interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetFlee); + interpreter.installSegment5 (opcodeSetAlarm, new OpSetAlarm); + interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAlarm); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 7faba7f41..8a166eff3 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -157,4 +157,12 @@ op 0x2000158: ClearForceSneak op 0x2000159: ClearForceSneak, explicit reference op 0x200015a: ForceSneak op 0x200015b: ForceSneak, explicit reference -opcodes 0x200015b-0x3ffffff unused +op 0x200015c: SetHello +op 0x200015d: SetHello, explicit reference +op 0x200015e: SetFight +op 0x200015f: SetFight, explicit reference +op 0x2000160: SetFlee +op 0x2000161: SetFlee, explicit reference +op 0x2000162: SetAlarm +op 0x2000163: SetAlarm, explicit reference +opcodes 0x2000164-0x3ffffff unused From e2a77037ebf88bd014df905bbf8515291ce59d8e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:38:54 +0200 Subject: [PATCH 267/289] fixed a type in a script instruction --- apps/openmw/mwscript/guiextensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index b267cc6e4..8e5897298 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -104,7 +104,7 @@ namespace MWScript extensions.registerInstruction ("enableclassmenu", "", opcodeEnableClassMenu); extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu); extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu); - extensions.registerInstruction ("enablestatsreviewmenu", "", + extensions.registerInstruction ("enablestatreviewmenu", "", opcodeEnableStatsReviewMenu); extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu); From 3c42a71dae5e766d79a7e7b65b321804ce4db022 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 Jun 2012 16:42:35 +0200 Subject: [PATCH 268/289] removed some cout spam --- apps/openmw/mwgui/messagebox.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 0bb7d3c1c..27e14ba82 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -86,13 +86,12 @@ void MessageBoxManager::createMessageBox (const std::string& message) bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector& buttons) { + /// \todo Don't write this kind of error message to cout. Either discard the old message box + /// silently or throw an exception. if(mInterMessageBoxe != NULL) { std::cout << "there is a MessageBox already" << std::endl; return false; } - std::cout << "interactive MessageBox: " << message << " - "; - std::copy (buttons.begin(), buttons.end(), std::ostream_iterator (std::cout, ", ")); - std::cout << std::endl; mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons); From b831c3313dc3a16796760c42d3c3819c6ab61972 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Jun 2012 00:47:45 +0200 Subject: [PATCH 269/289] render system was not written on launcher exit --- apps/launcher/graphicspage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index e156e4fbc..e6940164e 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -200,6 +200,7 @@ void GraphicsPage::writeConfig() Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); + Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString()); std::string resolution = mResolutionComboBox->currentText().toStdString(); // parse resolution x and y from a string like "800 x 600" From f81e1277013494850cd97a7d24b013101165300d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 17 Jun 2012 06:46:23 +0200 Subject: [PATCH 270/289] Created custom directory dialog which only accepts Data Files dirs --- apps/launcher/CMakeLists.txt | 3 ++ apps/launcher/datafilespage.cpp | 46 ++++++++++++++------------ apps/launcher/filedialog.cpp | 57 +++++++++++++++++++++++++++++++++ apps/launcher/filedialog.hpp | 50 +++++++++++++++++++++++++++++ apps/launcher/lineedit.cpp | 35 ++++++++------------ apps/launcher/lineedit.hpp | 2 +- 6 files changed, 150 insertions(+), 43 deletions(-) create mode 100644 apps/launcher/filedialog.cpp create mode 100644 apps/launcher/filedialog.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index ccefee1ee..ed3559fdc 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -8,6 +8,7 @@ set(LAUNCHER playpage.cpp pluginsmodel.cpp pluginsview.cpp + filedialog.cpp launcher.rc ) @@ -22,6 +23,7 @@ set(LAUNCHER_HEADER playpage.hpp pluginsmodel.hpp pluginsview.hpp + filedialog.hpp ) # Headers that must be pre-processed @@ -34,6 +36,7 @@ set(LAUNCHER_HEADER_MOC playpage.hpp pluginsmodel.hpp pluginsview.hpp + filedialog.hpp ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index c15274e74..a4992bc63 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -5,6 +5,7 @@ #include "datafilespage.hpp" #include "lineedit.hpp" +#include "filedialog.hpp" #include "naturalsort.hpp" #include "pluginsmodel.hpp" #include "pluginsview.hpp" @@ -203,8 +204,7 @@ void DataFilesPage::setupDataFiles() mCfgMgr.readConfiguration(variables, desc); // Put the paths in a boost::filesystem vector to use with Files::Collections - Files::PathContainer dataDirs(variables["data"].as()); - mDataDirs = dataDirs; + mDataDirs = Files::PathContainer(variables["data"].as()); // std::string local = variables["data-local"].as(); // if (!local.empty()) { @@ -212,36 +212,42 @@ void DataFilesPage::setupDataFiles() // dataDirs.push_back(Files::PathContainer::value_type(local)); // } - if (dataDirs.size()>1) - dataDirs.resize (1); + if (mDataDirs.size()>1) + mDataDirs.resize (1); - mCfgMgr.processPaths(dataDirs); - - while (dataDirs.empty()) { - // No valid data files directory found + mCfgMgr.processPaths(mDataDirs); + while (mDataDirs.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("Error detecting Morrowind installation"); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Cancel); msgBox.setText(tr("
Could not find the Data Files location

\ - The directory containing the data files was not found.

\ - Press \"Browse...\" to specify the location manually.
")); + The directory containing the data files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); QAbstractButton *dirSelectButton = - msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); + msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); msgBox.exec(); if (msgBox.clickedButton() == dirSelectButton) { - QString dataDir = QFileDialog::getExistingDirectory( - this, tr("Select Data Files Directory"), - "/home", - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + // Show a custom dir selection dialog which only accepts valid dirs + QString selectedDir = FileDialog::getExistingDirectory( + this, tr("Select Data Files Directory"), + QDir::currentPath(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + // Add the user selected data directory + if (!selectedDir.isEmpty()) { + mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString())); + mCfgMgr.processPaths(mDataDirs); + } else { + // Cancel from within the dir selection dialog + break; + } - dataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); - mDataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); } else { // Cancel break; @@ -249,13 +255,13 @@ void DataFilesPage::setupDataFiles() } // Check if cancel was clicked because we can't exit from while loop - if (dataDirs.empty()) { + if (mDataDirs.empty()) { QApplication::exit(1); return; } - // Create a file collection for the dataDirs - Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as()); + // Create a file collection for the data dirs + Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as()); // First we add all the master files const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); diff --git a/apps/launcher/filedialog.cpp b/apps/launcher/filedialog.cpp new file mode 100644 index 000000000..20ec3e234 --- /dev/null +++ b/apps/launcher/filedialog.cpp @@ -0,0 +1,57 @@ +#include "filedialog.hpp" +#include +#include + +FileDialog::FileDialog(QWidget *parent) + : QFileDialog(parent) +{ + // Remove the default Choose button to prevent it being updated elsewhere + QDialogButtonBox *box = qFindChild(this); + Q_ASSERT(box); + box->removeButton(box->button(QDialogButtonBox::Open)); + + // Add our own button so we can disable/enable it + mChooseButton = new QPushButton(tr("&Choose")); + mChooseButton->setIcon(QIcon::fromTheme("document-open")); + mChooseButton->setEnabled(false); + box->addButton(mChooseButton, QDialogButtonBox::AcceptRole); + + connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&))); + emit directoryEntered(directory().absolutePath()); +} + +QString FileDialog::getExistingDirectory(QWidget *parent, + const QString &caption, + const QString &dir, + Options options) +{ + // create a non-native file dialog + FileDialog dialog; + dialog.setFileMode(DirectoryOnly); + dialog.setOptions(options & DontUseNativeDialog | ShowDirsOnly); + + if (!caption.isEmpty()) + dialog.setWindowTitle(caption); + + if (!dir.isEmpty()) + dialog.setDirectory(dir); + + if (dialog.exec() == QDialog::Accepted) { + return dialog.selectedFiles().value(0); + } + return QString(); +} + +void FileDialog::updateChooseButton(const QString &directory) +{ + QDir currentDir = QDir(directory); + currentDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + currentDir.setNameFilters(QStringList() << "*.esm" << "*.esp"); + + if (!currentDir.entryList().isEmpty()) { + // There are data files in the current dir + mChooseButton->setEnabled(true); + } else { + mChooseButton->setEnabled(false); + } +} diff --git a/apps/launcher/filedialog.hpp b/apps/launcher/filedialog.hpp new file mode 100644 index 000000000..ededcbf39 --- /dev/null +++ b/apps/launcher/filedialog.hpp @@ -0,0 +1,50 @@ +#ifndef FILEDIALOG_HPP +#define FILEDIALOG_HPP + +#include + +class QPushButton; + +struct FileDialogArgs +{ + FileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {} + QWidget *parent; + QString caption; + QString directory; + QString selection; + QString filter; + QFileDialog::FileMode mode; + QFileDialog::Options options; + +}; + +class FileDialog : public QFileDialog +{ + Q_OBJECT + +public: + FileDialog(QWidget *parent = 0); +// FileDialog(QWidget *parent, Qt::WindowFlags f); + + //QString getExistingDirectory(); + static QString getExistingDirectory(QWidget *parent = 0, + const QString &caption = QString(), + const QString &dir = QString(), + Options options = ShowDirsOnly); + //FileDialog mDirectoryDialog; + + bool initialized; +protected: + +private slots: +// void updateOkButton(const QString &text); + void updateChooseButton(const QString &directory); + //void + +private: + QPushButton *mChooseButton; + //QFileDialog *mDirectoryDialog; +}; + + +#endif // FILEDIALOG_HPP diff --git a/apps/launcher/lineedit.cpp b/apps/launcher/lineedit.cpp index 254c09fce..dac196425 100644 --- a/apps/launcher/lineedit.cpp +++ b/apps/launcher/lineedit.cpp @@ -1,12 +1,3 @@ -/**************************************************************************** -** -** Copyright (c) 2007 Trolltech ASA -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - #include "lineedit.hpp" #include #include @@ -14,33 +5,33 @@ LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { - clearButton = new QToolButton(this); + mClearButton = new QToolButton(this); QPixmap pixmap(":images/clear.png"); - clearButton->setIcon(QIcon(pixmap)); - clearButton->setIconSize(pixmap.size()); - clearButton->setCursor(Qt::ArrowCursor); - clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); - clearButton->hide(); - connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); + mClearButton->setIcon(QIcon(pixmap)); + mClearButton->setIconSize(pixmap.size()); + mClearButton->setCursor(Qt::ArrowCursor); + mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + mClearButton->hide(); + connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); + setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); - setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), - qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); + setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2), + qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2)); } void LineEdit::resizeEvent(QResizeEvent *) { - QSize sz = clearButton->sizeHint(); + QSize sz = mClearButton->sizeHint(); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - clearButton->move(rect().right() - frameWidth - sz.width(), + mClearButton->move(rect().right() - frameWidth - sz.width(), (rect().bottom() + 1 - sz.height())/2); } void LineEdit::updateCloseButton(const QString& text) { - clearButton->setVisible(!text.isEmpty()); + mClearButton->setVisible(!text.isEmpty()); } diff --git a/apps/launcher/lineedit.hpp b/apps/launcher/lineedit.hpp index 7a96a523c..2ed76d6eb 100644 --- a/apps/launcher/lineedit.hpp +++ b/apps/launcher/lineedit.hpp @@ -28,7 +28,7 @@ private slots: void updateCloseButton(const QString &text); private: - QToolButton *clearButton; + QToolButton *mClearButton; }; #endif // LIENEDIT_H From de3daf3dc15fef32c45805c6aa81ed2f2b773512 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 18 Jun 2012 00:21:55 +0200 Subject: [PATCH 271/289] allow the 'lock' and 'unlock' script commands to work on containers, like in morrowind --- apps/openmw/mwclass/container.cpp | 13 +++++++++++++ apps/openmw/mwclass/container.hpp | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index e9b8ce31f..99a32fc32 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -192,4 +192,17 @@ namespace MWClass { return getContainerStore (ptr).getWeight(); } + + void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const + { + if (lockLevel<0) + lockLevel = 0; + + ptr.getCellRef().lockLevel = lockLevel; + } + + void Container::unlock (const MWWorld::Ptr& ptr) const + { + ptr.getCellRef().lockLevel = 0; + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 44f0fe927..739c75c77 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -44,6 +44,12 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; + ///< Lock object + + virtual void unlock (const MWWorld::Ptr& ptr) const; + ///< Unlock object + static void registerSelf(); }; } From 50d81e99fbc474a24a9b3621cc5c6cf136ed0ac2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 19 Jun 2012 14:55:22 +0200 Subject: [PATCH 272/289] possible fix for script execution bug --- components/compiler/exprparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 8041a7c8a..52192625b 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -309,7 +309,7 @@ namespace Compiler if (mExplicit.empty() && getContext().isId (name2)) { - mExplicit = name; + mExplicit = name2; return true; } } From 0aa01b93e298261ef6f4fbe8d459c2d6cd6ec4b8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Jun 2012 15:24:52 +0200 Subject: [PATCH 273/289] don't put blue color on actions that are in the topic list, but are not topics (e.g. Barter) --- apps/openmw/mwgui/dialogue.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 79b2d68ba..55bd49beb 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -205,11 +205,14 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c std::string DialogueWindow::parseText(std::string text) { + bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored) for(unsigned int i = 0;igetItemCount();i++) { std::string keyWord = topicsList->getItemNameAt(i); - if (keyWord != "") + if (separatorReached && keyWord != "") addColorInString(text,keyWord,"#686EBA","#B29154"); + else + separatorReached = true; } return text; } From ff278ab4ec2b1600966937f9c7de823afb8e3b77 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Jun 2012 15:25:04 +0200 Subject: [PATCH 274/289] chargen generate class: fix result not being shown in review dialog --- apps/openmw/mwgui/charactercreation.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 3f9a94e2d..c39e305dc 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -708,6 +708,9 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) if (mGenerateClassResultDialog) mWM->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); + const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(mGenerateClass); + mPlayerClass = *klass; + mWM->setPlayerClass(mPlayerClass); if (mCreationStage == CSE_ReviewNext) { From c9e76d3e90d9e09c39721340eb786e148a9c7e0c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Jun 2012 15:57:58 +0200 Subject: [PATCH 275/289] remove extra tokens at the end of the resolution string, if present --- apps/launcher/graphicspage.cpp | 43 ++++++++++++++++++++++++++++++---- apps/launcher/graphicspage.hpp | 1 + 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index e6940164e..345b51a11 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -202,11 +202,11 @@ void GraphicsPage::writeConfig() Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString()); - std::string resolution = mResolutionComboBox->currentText().toStdString(); // parse resolution x and y from a string like "800 x 600" - size_t xPos = resolution.find("x"); - int resX = boost::lexical_cast(resolution.substr(0, xPos-1)); - int resY = boost::lexical_cast(resolution.substr(xPos+2, resolution.size()-(xPos+2))); + QString resolution = mResolutionComboBox->currentText(); + QStringList tokens = resolution.split(" ", QString::SkipEmptyParts); + int resX = boost::lexical_cast(tokens.at(0).toStdString()); + int resY = boost::lexical_cast(tokens.at(2).toStdString()); Settings::Manager::setInt("resolution x", "Video", resX); Settings::Manager::setInt("resolution y", "Video", resY); } @@ -240,6 +240,39 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy return result; } +QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) +{ + QString key ("Video Mode"); + QStringList result; + + uint row = 0; + Ogre::ConfigOptionMap options = renderer->getConfigOptions(); + + for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++) + { + if (key.toStdString() != i->first) + continue; + + Ogre::StringVector::iterator opt_it; + uint idx = 0; + for (opt_it = i->second.possibleValues.begin (); + opt_it != i->second.possibleValues.end (); opt_it++, idx++) + { + QString qval = QString::fromStdString(*opt_it).simplified(); + // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) + QStringList tokens = qval.split(" ", QString::SkipEmptyParts); + assert (tokens.size() >= 3); + QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); + { + result << resolutionStr; + } + } + + } + + return result; +} + void GraphicsPage::rendererChanged(const QString &renderer) { mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); @@ -248,5 +281,5 @@ void GraphicsPage::rendererChanged(const QString &renderer) mResolutionComboBox->clear(); mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 1b0c6f388..c2701f362 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -59,6 +59,7 @@ private: Files::ConfigurationManager &mCfgMgr; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); + QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); void createPages(); void setupConfig(); From 61ec56debc5fa63e26f301caa40870ec5cf469bf Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Jun 2012 16:02:28 +0200 Subject: [PATCH 276/289] don't add duplicate resolutions --- apps/launcher/graphicspage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 345b51a11..22a9ca5be 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -264,7 +264,10 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) assert (tokens.size() >= 3); QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); { - result << resolutionStr; + + // do not add duplicate resolutions + if (!result.contains(resolutionStr)) + result << resolutionStr; } } From 590dfe8d63e6eb6b608e12177a6dd43918244eea Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 19 Jun 2012 16:42:10 +0200 Subject: [PATCH 277/289] fixed the container fill problem on cell load --- apps/openmw/mwworld/cells.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index b6d3e38ce..990a4cc4a 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -142,7 +142,10 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce (int(*)(int)) std::tolower); if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase)) + { cell.load (mStore, mReader); + fillContainers (cell); + } else return Ptr(); } From 15e959868c4d18ce4ab98cc551e7c02adff203c1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Jun 2012 17:07:00 +0200 Subject: [PATCH 278/289] make some of the gui mode changes a bit safer --- apps/openmw/mwdialogue/dialoguemanager.cpp | 2 +- apps/openmw/mwgui/alchemywindow.cpp | 4 ++-- apps/openmw/mwgui/bookwindow.cpp | 4 ++-- apps/openmw/mwgui/container.cpp | 4 ++-- apps/openmw/mwgui/messagebox.cpp | 2 +- apps/openmw/mwgui/scrollwindow.cpp | 4 ++-- apps/openmw/mwgui/settingswindow.cpp | 2 +- apps/openmw/mwgui/tradewindow.cpp | 4 ++-- apps/openmw/mwgui/window_manager.cpp | 5 ++++- apps/openmw/mwworld/actionalchemy.cpp | 1 - 10 files changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index a19356d07..45e2c8cb3 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -843,7 +843,7 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); } void DialogueManager::questionAnswered(std::string answere) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 9c26bfabe..423678eed 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -70,8 +70,8 @@ namespace MWGui void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.popGuiMode(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Alchemy); + mWindowManager.removeGuiMode(GM_Inventory); } void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index f1873b550..a9dcd4555 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -92,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Book); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -102,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mBook); take.execute(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Book); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6775fa643..36ed16b0e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -640,7 +640,7 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } } @@ -671,7 +671,7 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) containerStore.clear(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } } diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 27e14ba82..ca04af830 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,7 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; - mWindowManager->popGuiMode(); + mWindowManager->removeGuiMode(GM_InterMessageBox); } } diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index f4d45fc26..92b18d953 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -56,7 +56,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Scroll); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -66,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Scroll); } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 67ccf9d53..eafbd3462 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -155,7 +155,7 @@ namespace MWGui void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Settings); } void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 47d299fdc..a42da60d1 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -212,7 +212,7 @@ namespace MWGui std::string sound = "Item Gold Up"; MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Barter); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) @@ -222,7 +222,7 @@ namespace MWGui // now gimme back my stuff! mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Barter); } void TradeWindow::updateLabels() diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 5b963d3ae..f62a3fa0f 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -464,7 +464,7 @@ void WindowManager::onDialogueWindowBye() //removeDialog(dialogueWindow); mDialogueWindow->setVisible(false); } - popGuiMode(); + removeGuiMode(GM_Dialogue); } void WindowManager::onFrame (float frameDuration) @@ -677,6 +677,9 @@ void WindowManager::removeGuiMode(GuiMode mode) ++it; } + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + updateVisible(); } diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index a2f3bd1e4..eb91b6946 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -7,7 +7,6 @@ namespace MWWorld { void ActionAlchemy::execute() { - MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy); } } From e21442f6cc67b3830e3465b133c11d4a37d985e4 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Jun 2012 02:28:49 +0200 Subject: [PATCH 279/289] Fix for Bug #306: launcher now creates the config dir and returns proper error codes --- apps/launcher/datafilespage.cpp | 18 +++++++++++++++++- apps/launcher/filedialog.cpp | 2 +- apps/launcher/main.cpp | 6 ++++-- apps/launcher/maindialog.cpp | 12 +++++++----- apps/launcher/maindialog.hpp | 4 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index a4992bc63..3128c7b75 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1063,8 +1063,24 @@ void DataFilesPage::writeConfig(QString profile) return; } + QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); + QDir userPath(pathStr); + + if (!userPath.exists()) { + if (!userPath.mkpath(pathStr)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not create %0

\Please make sure you have the right permissions and try again.
").arg(pathStr)); + msgBox.exec(); + + qApp->exit(1); + return; + } + } // Open the OpenMW config as a QFile - QFile file(QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string())); + QFile file(pathStr.append("openmw.cfg")); if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { // File cannot be opened or created diff --git a/apps/launcher/filedialog.cpp b/apps/launcher/filedialog.cpp index 20ec3e234..ead1cbc55 100644 --- a/apps/launcher/filedialog.cpp +++ b/apps/launcher/filedialog.cpp @@ -17,7 +17,7 @@ FileDialog::FileDialog(QWidget *parent) box->addButton(mChooseButton, QDialogButtonBox::AcceptRole); connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&))); - emit directoryEntered(directory().absolutePath()); + emit directoryEntered(QDir::currentPath()); } QString FileDialog::getExistingDirectory(QWidget *parent, diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index bd29e2bca..cbc1c4da3 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -31,8 +31,10 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - MainDialog dialog; - return dialog.exec(); + MainDialog mainWin; + mainWin.show(); + + return app.exec(); } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index d404fed8e..63ea96b6f 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -29,7 +29,10 @@ MainDialog::MainDialog() mSettings.loadUser(globaldefault); - mIconWidget = new QListWidget; + QWidget *centralWidget = new QWidget(this); + setCentralWidget(centralWidget); + + mIconWidget = new QListWidget(centralWidget); mIconWidget->setObjectName("IconWidget"); mIconWidget->setViewMode(QListView::IconMode); mIconWidget->setWrapping(false); @@ -43,7 +46,7 @@ MainDialog::MainDialog() mIconWidget->setCurrentRow(0); mIconWidget->setFlow(QListView::LeftToRight); - QGroupBox *groupBox = new QGroupBox(this); + QGroupBox *groupBox = new QGroupBox(centralWidget); QVBoxLayout *groupLayout = new QVBoxLayout(groupBox); mPagesWidget = new QStackedWidget(groupBox); @@ -51,16 +54,15 @@ MainDialog::MainDialog() QPushButton *playButton = new QPushButton(tr("Play")); - QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget); buttonBox->setStandardButtons(QDialogButtonBox::Close); buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); - QVBoxLayout *dialogLayout = new QVBoxLayout(this); + QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget); dialogLayout->addWidget(mIconWidget); dialogLayout->addWidget(groupBox); dialogLayout->addWidget(buttonBox); - setWindowTitle(tr("OpenMW Launcher")); setWindowIcon(QIcon(":/images/openmw.png")); // Remove what's this? button diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 0065aa8c4..59c6cbd2d 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -1,7 +1,7 @@ #ifndef MAINDIALOG_H #define MAINDIALOG_H -#include +#include #include #include @@ -17,7 +17,7 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class MainDialog : public QDialog +class MainDialog : public QMainWindow { Q_OBJECT From d162445e6868f5e3d5c6a31d9c51d7143c4747cc Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Jun 2012 13:35:05 +0200 Subject: [PATCH 280/289] Got rid of some unwanted warnings and did some cleanup on the launcher --- apps/launcher/datafilespage.cpp | 7 ++++--- apps/launcher/filedialog.cpp | 2 +- apps/launcher/filedialog.hpp | 22 ---------------------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 3128c7b75..f3c5962ca 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1072,7 +1072,8 @@ void DataFilesPage::writeConfig(QString profile) msgBox.setWindowTitle("Error creating OpenMW configuration directory"); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not create %0

\Please make sure you have the right permissions and try again.
").arg(pathStr)); + msgBox.setText(tr("
Could not create %0

\ + Please make sure you have the right permissions and try again.
").arg(pathStr)); msgBox.exec(); qApp->exit(1); @@ -1089,7 +1090,7 @@ void DataFilesPage::writeConfig(QString profile) msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); + Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); qApp->exit(1); @@ -1120,7 +1121,7 @@ void DataFilesPage::writeConfig(QString profile) msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not write to %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); + Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); qApp->exit(1); diff --git a/apps/launcher/filedialog.cpp b/apps/launcher/filedialog.cpp index ead1cbc55..595501b91 100644 --- a/apps/launcher/filedialog.cpp +++ b/apps/launcher/filedialog.cpp @@ -28,7 +28,7 @@ QString FileDialog::getExistingDirectory(QWidget *parent, // create a non-native file dialog FileDialog dialog; dialog.setFileMode(DirectoryOnly); - dialog.setOptions(options & DontUseNativeDialog | ShowDirsOnly); + dialog.setOptions(options & (DontUseNativeDialog | ShowDirsOnly)); if (!caption.isEmpty()) dialog.setWindowTitle(caption); diff --git a/apps/launcher/filedialog.hpp b/apps/launcher/filedialog.hpp index ededcbf39..7a161ecb9 100644 --- a/apps/launcher/filedialog.hpp +++ b/apps/launcher/filedialog.hpp @@ -5,45 +5,23 @@ class QPushButton; -struct FileDialogArgs -{ - FileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {} - QWidget *parent; - QString caption; - QString directory; - QString selection; - QString filter; - QFileDialog::FileMode mode; - QFileDialog::Options options; - -}; - class FileDialog : public QFileDialog { Q_OBJECT public: FileDialog(QWidget *parent = 0); -// FileDialog(QWidget *parent, Qt::WindowFlags f); - //QString getExistingDirectory(); static QString getExistingDirectory(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), Options options = ShowDirsOnly); - //FileDialog mDirectoryDialog; - - bool initialized; -protected: private slots: -// void updateOkButton(const QString &text); void updateChooseButton(const QString &directory); - //void private: QPushButton *mChooseButton; - //QFileDialog *mDirectoryDialog; }; From 01d1995164c18033d785662ba7d53fbd3275a4a1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 20 Jun 2012 18:22:18 +0200 Subject: [PATCH 281/289] fix compilation against latest bullet svn --- libs/openengine/bullet/physic.cpp | 16 ++++++++-------- libs/openengine/bullet/physic.hpp | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index f7caa54b4..1bc4341a0 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -488,7 +488,7 @@ namespace Physic dynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { - name = static_cast(*resultCallback1.m_collisionObject).mName; + name = static_cast(*resultCallback1.m_collisionObject).mName; d1 = resultCallback1.m_closestHitFraction; d = d1; } @@ -502,7 +502,7 @@ namespace Physic d2 = resultCallback1.m_closestHitFraction; if(d2<=d1) { - name = static_cast(*resultCallback2.m_collisionObject).mName; + name = static_cast(*resultCallback2.m_collisionObject).mName; d = d2; } } @@ -515,25 +515,25 @@ namespace Physic MyRayResultCallback resultCallback1; resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; dynamicsWorld->rayTest(from, to, resultCallback1); - std::vector< std::pair > results = resultCallback1.results; + std::vector< std::pair > results = resultCallback1.results; MyRayResultCallback resultCallback2; resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; dynamicsWorld->rayTest(from, to, resultCallback2); - std::vector< std::pair > actorResults = resultCallback2.results; + std::vector< std::pair > actorResults = resultCallback2.results; std::vector< std::pair > results2; - for (std::vector< std::pair >::iterator it=results.begin(); + for (std::vector< std::pair >::iterator it=results.begin(); it != results.end(); ++it) { - results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); } - for (std::vector< std::pair >::iterator it=actorResults.begin(); + for (std::vector< std::pair >::iterator it=actorResults.begin(); it != actorResults.end(); ++it) { - results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); } std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 811572320..e327f24e1 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -278,7 +278,7 @@ namespace Physic return false; } - std::vector < std::pair > results; + std::vector < std::pair > results; }; }} From 6a2bcddef5de155ea04e95b66dec46cfa9cef964 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Jun 2012 20:43:51 +0200 Subject: [PATCH 282/289] Changed the way the launcher exits and polished the error handling code --- apps/launcher/datafilespage.cpp | 21 +++----- apps/launcher/datafilespage.hpp | 2 +- apps/launcher/filedialog.cpp | 4 +- apps/launcher/graphicspage.cpp | 20 +++---- apps/launcher/graphicspage.hpp | 3 +- apps/launcher/main.cpp | 9 ++-- apps/launcher/maindialog.cpp | 92 +++++++++++++++++++++------------ apps/launcher/maindialog.hpp | 1 + 8 files changed, 84 insertions(+), 68 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index f3c5962ca..8545be835 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -140,7 +140,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) createActions(); setupConfig(); - setupDataFiles(); + //setupDataFiles(); } @@ -189,7 +189,7 @@ void DataFilesPage::setupConfig() } -void DataFilesPage::setupDataFiles() +bool DataFilesPage::setupDataFiles() { // We use the Configuration Manager to retrieve the configuration values boost::program_options::variables_map variables; @@ -245,21 +245,15 @@ void DataFilesPage::setupDataFiles() mCfgMgr.processPaths(mDataDirs); } else { // Cancel from within the dir selection dialog - break; + return false; } } else { // Cancel - break; + return false; } } - // Check if cancel was clicked because we can't exit from while loop - if (mDataDirs.empty()) { - QApplication::exit(1); - return; - } - // Create a file collection for the data dirs Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as()); @@ -362,6 +356,7 @@ void DataFilesPage::setupDataFiles() } readConfig(); + return true; } void DataFilesPage::createActions() @@ -1076,7 +1071,7 @@ void DataFilesPage::writeConfig(QString profile) Please make sure you have the right permissions and try again.
").arg(pathStr)); msgBox.exec(); - qApp->exit(1); + qApp->quit(); return; } } @@ -1093,7 +1088,7 @@ void DataFilesPage::writeConfig(QString profile) Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); - qApp->exit(1); + qApp->quit(); return; } @@ -1124,7 +1119,7 @@ void DataFilesPage::writeConfig(QString profile) Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); - qApp->exit(1); + qApp->quit(); return; } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index ad5e90511..5078f6428 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -34,6 +34,7 @@ public: ComboBox *mProfilesComboBox; void writeConfig(QString profile = QString()); + bool setupDataFiles(); public slots: void masterSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); @@ -92,7 +93,6 @@ private: void removePlugins(const QModelIndex &index); void uncheckPlugins(); void createActions(); - void setupDataFiles(); void setupConfig(); void readConfig(); void scrollToSelection(); diff --git a/apps/launcher/filedialog.cpp b/apps/launcher/filedialog.cpp index 595501b91..16d677533 100644 --- a/apps/launcher/filedialog.cpp +++ b/apps/launcher/filedialog.cpp @@ -28,13 +28,13 @@ QString FileDialog::getExistingDirectory(QWidget *parent, // create a non-native file dialog FileDialog dialog; dialog.setFileMode(DirectoryOnly); - dialog.setOptions(options & (DontUseNativeDialog | ShowDirsOnly)); + dialog.setOptions(options |= QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly); if (!caption.isEmpty()) dialog.setWindowTitle(caption); if (!dir.isEmpty()) - dialog.setDirectory(dir); + dialog.setDirectory(dir); if (dialog.exec() == QDialog::Accepted) { return dialog.selectedFiles().value(0); diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 22a9ca5be..0af127edc 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -45,10 +45,6 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) connect(mRendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&))); createPages(); - setupConfig(); - setupOgre(); - - readConfig(); } void GraphicsPage::createPages() @@ -78,11 +74,7 @@ void GraphicsPage::createPages() mDisplayStackedWidget->addWidget(main); } -void GraphicsPage::setupConfig() -{ -} - -void GraphicsPage::setupOgre() +bool GraphicsPage::setupOgre() { QString pluginCfg = mCfgMgr.getPluginsConfigPath().string().c_str(); QFile file(pluginCfg); @@ -113,9 +105,7 @@ void GraphicsPage::setupOgre() msgBox.exec(); qCritical("Error creating Ogre::Root, the error reported was:\n %s", qPrintable(ogreError)); - - qApp->exit(1); - return; + return false; } #ifdef ENABLE_PLUGIN_GL @@ -165,8 +155,7 @@ void GraphicsPage::setupOgre() Please make sure the plugins.cfg file exists and contains a valid rendering plugin.
")); msgBox.exec(); - qApp->exit(1); - return; + return false; } // Now fill the GUI elements @@ -174,6 +163,9 @@ void GraphicsPage::setupOgre() mResolutionComboBox->clear(); mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); + + readConfig(); + return true; } void GraphicsPage::readConfig() diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index c2701f362..b8166f672 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -30,6 +30,7 @@ class GraphicsPage : public QWidget public: GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0); + bool setupOgre(); void writeConfig(); public slots: @@ -62,8 +63,6 @@ private: QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); void createPages(); - void setupConfig(); - void setupOgre(); void readConfig(); }; diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index cbc1c4da3..4ae09f844 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "maindialog.hpp" @@ -32,9 +31,13 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); MainDialog mainWin; - mainWin.show(); - return app.exec(); + if (mainWin.setup()) { + mainWin.show(); + return app.exec(); + } + + return 0; } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 63ea96b6f..ab6eb0b73 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -7,28 +7,6 @@ MainDialog::MainDialog() { - // Create the settings manager and load default settings file - const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; - const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg"; - - // prefer local - if (boost::filesystem::exists(localdefault)) - mSettings.loadDefault(localdefault); - else if (boost::filesystem::exists(globaldefault)) - mSettings.loadDefault(globaldefault); - else - throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed."); - - // load user settings if they exist, otherwise just load the default settings as user settings - const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; - if (boost::filesystem::exists(settingspath)) - mSettings.loadUser(settingspath); - else if (boost::filesystem::exists(localdefault)) - mSettings.loadUser(localdefault); - else if (boost::filesystem::exists(globaldefault)) - mSettings.loadUser(globaldefault); - - QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); @@ -72,22 +50,22 @@ MainDialog::MainDialog() // Install the stylesheet font QFile file; QFontDatabase fontDatabase; - + const QStringList fonts = fontDatabase.families(); - + // Check if the font is installed if (!fonts.contains("EB Garamond")) { - + QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); file.setFileName(font); - + if (!file.exists()) { - font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); + font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); } - + fontDatabase.addApplicationFont(font); } - + // Load the stylesheet QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string()); file.setFileName(config); @@ -101,7 +79,6 @@ MainDialog::MainDialog() qApp->setStyleSheet(styleSheet); file.close(); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); @@ -172,6 +149,53 @@ void MainDialog::createPages() } + +bool MainDialog::setup() +{ + // Create the settings manager and load default settings file + const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string(); + const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string(); + + // prefer local + if (boost::filesystem::exists(localdefault)) { + mSettings.loadDefault(localdefault); + } else if (boost::filesystem::exists(globaldefault)) { + mSettings.loadDefault(globaldefault); + } else { + QMessageBox msgBox; + msgBox.setWindowTitle("Error reading OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not find %0

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.").arg(QString::fromStdString(globaldefault))); + msgBox.exec(); + return false; + } + + // load user settings if they exist, otherwise just load the default settings as user settings + const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); + + if (boost::filesystem::exists(settingspath)) + mSettings.loadUser(settingspath); + else if (boost::filesystem::exists(localdefault)) + mSettings.loadUser(localdefault); + else if (boost::filesystem::exists(globaldefault)) + mSettings.loadUser(globaldefault); + + // Setup the Graphics page + if (!mGraphicsPage->setupOgre()) { + return false; + } + + // Setup the Data Files page + if (!mDataFilesPage->setupDataFiles()) { + return false; + } + + return true; +} + void MainDialog::profileChanged(int index) { // Just to be sure, should always have a selection @@ -204,7 +228,8 @@ void MainDialog::closeEvent(QCloseEvent *event) mGraphicsPage->writeConfig(); // Save user settings - const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; + const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); + qDebug() << QString::fromStdString(settingspath); mSettings.saveUser(settingspath); event->accept(); @@ -248,7 +273,7 @@ void MainDialog::play() if (!info.isExecutable()) { QMessageBox msgBox; msgBox.setWindowTitle("Error starting OpenMW"); - msgBox.setIcon(QMessageBox::Critical); + msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not start OpenMW

\ The OpenMW application is not executable.
\ @@ -272,6 +297,7 @@ void MainDialog::play() return; } else { - close(); + qApp->quit(); } } + diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 59c6cbd2d..683cd58c2 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -28,6 +28,7 @@ public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); void play(); void profileChanged(int index); + bool setup(); private: void createIcons(); From 89ac0fa232112ee3bf4b61e545b0a823b9ffbfe0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Jun 2012 11:43:18 +0200 Subject: [PATCH 283/289] Issue #312: Implemented ID-search caching to speed up some badly written scripts --- apps/openmw/mwworld/cells.cpp | 42 +++++++++++++++++++++++++++++------ apps/openmw/mwworld/cells.hpp | 4 ++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 990a4cc4a..3d6042e46 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -70,8 +70,26 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) } } +MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellStore& cellStore) +{ + Ptr ptr = getPtr (name, cellStore); + + if (!ptr.isEmpty()) + { + mIdCache[mIdCacheIndex].first = name; + mIdCache[mIdCacheIndex].second = &cellStore; + if (++mIdCacheIndex>=mIdCache.size()) + mIdCacheIndex = 0; + } + + return ptr; +} + MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world) -: mStore (store), mReader (reader), mWorld (world) {} +: mStore (store), mReader (reader), mWorld (world), + mIdCache (20, std::pair ("", 0)), /// \todo make cache size configurable + mIdCacheIndex (0) +{} MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) { @@ -215,19 +233,29 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) { - // First check cells that are already listed + // First check the cache + for (std::vector >::iterator iter (mIdCache.begin()); + iter!=mIdCache.end(); ++iter) + if (iter->first==name && iter->second) + { + Ptr ptr = getPtr (name, *iter->second); + if (!ptr.isEmpty()) + return ptr; + } + + // Then check cells that are already listed for (std::map::iterator iter = mInteriors.begin(); iter!=mInteriors.end(); ++iter) { - Ptr ptr = getPtr (name, iter->second); + Ptr ptr = getPtrAndCache (name, iter->second); if (!ptr.isEmpty()) - return ptr; + return ptr; } for (std::map, Ptr::CellStore>::iterator iter = mExteriors.begin(); iter!=mExteriors.end(); ++iter) { - Ptr ptr = getPtr (name, iter->second); + Ptr ptr = getPtrAndCache (name, iter->second); if (!ptr.isEmpty()) return ptr; } @@ -238,7 +266,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) { Ptr::CellStore *cellStore = getCellStore (iter->second); - Ptr ptr = getPtr (name, *cellStore); + Ptr ptr = getPtrAndCache (name, *cellStore); if (!ptr.isEmpty()) return ptr; @@ -249,7 +277,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) { Ptr::CellStore *cellStore = getCellStore (iter->second); - Ptr ptr = getPtr (name, *cellStore); + Ptr ptr = getPtrAndCache (name, *cellStore); if (!ptr.isEmpty()) return ptr; diff --git a/apps/openmw/mwworld/cells.hpp b/apps/openmw/mwworld/cells.hpp index 42aa1050c..05367138f 100644 --- a/apps/openmw/mwworld/cells.hpp +++ b/apps/openmw/mwworld/cells.hpp @@ -28,6 +28,8 @@ namespace MWWorld std::map mInteriors; std::map, Ptr::CellStore> mExteriors; MWWorld::World& mWorld; + std::vector > mIdCache; + std::size_t mIdCacheIndex; Cells (const Cells&); Cells& operator= (const Cells&); @@ -36,6 +38,8 @@ namespace MWWorld void fillContainers (Ptr::CellStore& cellStore); + Ptr getPtrAndCache (const std::string& name, Ptr::CellStore& cellStore); + public: Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world); From ad251065f469d9e0fdf4574116f9b700758eb3f3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Jun 2012 12:00:56 +0200 Subject: [PATCH 284/289] removed more cout spam --- apps/openmw/mwgui/messagebox.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index ca04af830..007f966aa 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -265,11 +265,8 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan if(buttonsWidth < fixedWidth) { // on one line - std::cout << "on one line" << std::endl; - if(textSize.width + 2*textPadding < buttonsWidth) { - std::cout << "width = buttonsWidth" << std::endl; mainWidgetSize.width = buttonsWidth; } else @@ -282,13 +279,9 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2; absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2; - std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl; - std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl; - mMainWidget->setCoord(absCoord); mMainWidget->setSize(mainWidgetSize); - MyGUI::IntCoord messageWidgetCoord; messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2; messageWidgetCoord.top = textPadding; @@ -318,7 +311,6 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan else { // among each other - if(biggestButtonWidth > textSize.width) { mainWidgetSize.width = biggestButtonWidth + buttonTopPadding; } @@ -327,8 +319,6 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan } mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding; - std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl; - std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl; mMainWidget->setSize(mainWidgetSize); MyGUI::IntCoord absCoord; @@ -383,7 +373,6 @@ void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed) } index++; } - std::cout << "Cant be possible :/" << std::endl; } int InteractiveMessageBox::readPressedButton () From 68459441f2bbc4e8c9f670b1b25bd554b4eee11e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Jun 2012 12:40:44 +0200 Subject: [PATCH 285/289] adjusting version number --- CMakeLists.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b83935bdc..84cef306e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 15) +set (OPENMW_VERSION_MINOR 16) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") diff --git a/readme.txt b/readme.txt index 4cc31343b..02737f63e 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.15.0 +Version: 0.16.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org From 89dfa54b79b9acd0660423e019cd14e895968a3b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Jun 2012 13:06:34 +0200 Subject: [PATCH 286/289] updated changelog --- readme.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/readme.txt b/readme.txt index 02737f63e..aa981dba3 100644 --- a/readme.txt +++ b/readme.txt @@ -133,6 +133,33 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil CHANGELOG +0.16.0 + +Bug #250: OpenMW launcher erratic behaviour +Bug #270: Crash because of underwater effect on OS X +Bug #277: Auto-equipping in some cells not working +Bug #294: Container GUI ignores disabled inventory menu +Bug #297: Stats review dialog shows all skills and attribute values as 0 +Bug #298: MechanicsManager::buildPlayer does not remove previous bonuses +Bug #299: Crash in World::disable +Bug #306: Non-existent ~/.config/openmw "crash" the launcher. +Bug #307: False "Data Files" location make the launcher "crash" +Feature #81: Spell Window +Feature #85: Alchemy Window +Feature #181: Support for x.y script syntax +Feature #242: Weapon and Spell icons +Feature #254: Ingame settings window +Feature #293: Allow "stacking" game modes +Feature #295: Class creation dialog tooltips +Feature #296: Clicking on the HUD elements should show/hide the respective window +Feature #301: Direction after using a Teleport Door +Feature #303: Allow object selection in the console +Feature #305: Allow the use of = as a synonym for == +Feature #312: Compensation for slow object access in poorly written Morrowind.esm scripts +Task #176: Restructure enabling/disabling of MW-references +Task #283: Integrate ogre.cfg file in settings file +Task #290: Auto-Close MW-reference related GUI windows + 0.15.0 Bug #5: Physics reimplementation (fixes various issues) From 63ce143a04db357322895ca49de995d648103e83 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Jun 2012 12:56:04 +0200 Subject: [PATCH 287/289] fix triangle / batch counts with compositors --- apps/openmw/engine.cpp | 6 ++-- apps/openmw/mwgui/hud.cpp | 4 +-- apps/openmw/mwgui/hud.hpp | 4 +-- apps/openmw/mwgui/window_manager.hpp | 6 ++-- apps/openmw/mwrender/compositors.cpp | 37 +++++++++++++++++++++++ apps/openmw/mwrender/compositors.hpp | 4 +++ apps/openmw/mwrender/renderingmanager.cpp | 13 ++++++++ apps/openmw/mwrender/renderingmanager.hpp | 6 ++-- apps/openmw/mwworld/world.cpp | 5 +++ apps/openmw/mwworld/world.hpp | 2 ++ 10 files changed, 75 insertions(+), 12 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e192b1f88..5c5a586af 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -126,9 +126,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // update GUI Ogre::RenderWindow* window = mOgre->getWindow(); - MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), - window->getTriangleCount(), - window->getBatchCount()); + unsigned int tri, batch; + MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); + MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame); } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 95d66eb81..4ad9845f0 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -143,12 +143,12 @@ void HUD::setFPS(float fps) fpscounter->setCaption(boost::lexical_cast((int)fps)); } -void HUD::setTriangleCount(size_t count) +void HUD::setTriangleCount(unsigned int count) { trianglecounter->setCaption(boost::lexical_cast(count)); } -void HUD::setBatchCount(size_t count) +void HUD::setBatchCount(unsigned int count) { batchcounter->setCaption(boost::lexical_cast(count)); } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 0bfe5c20f..c6bcdd4e9 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -16,8 +16,8 @@ namespace MWGui void setEffect(const char *img); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); void setFPS(float fps); - void setTriangleCount(size_t count); - void setBatchCount(size_t count); + void setTriangleCount(unsigned int count); + void setBatchCount(unsigned int count); void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 37f30c59a..fd1e61021 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -159,7 +159,7 @@ namespace MWGui MyGUI::Gui* getGui() const { return gui; } - void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount) + void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) { mFPS = fps; mTriangleCount = triangleCount; @@ -295,8 +295,8 @@ namespace MWGui int showFPSLevel; float mFPS; - size_t mTriangleCount; - size_t mBatchCount; + unsigned int mTriangleCount; + unsigned int mBatchCount; void onDialogueWindowBye(); diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index 6f97269ab..b1c98a306 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include using namespace MWRender; @@ -69,3 +71,38 @@ void Compositors::removeAll() mCompositors.clear(); } + +bool Compositors::anyCompositorEnabled() +{ + for (CompositorMap::iterator it=mCompositors.begin(); + it != mCompositors.end(); ++it) + { + if (it->second.first && mEnabled) + return true; + } + return false; +} + +void Compositors::countTrianglesBatches(unsigned int &triangles, unsigned int &batches) +{ + triangles = 0; + batches = 0; + + Ogre::CompositorInstance* c = NULL; + Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain (mViewport); + // accumulate tris & batches from all compositors with all their render targets + for (unsigned int i=0; i < chain->getNumCompositors(); ++i) + { + if (chain->getCompositor(i)->getEnabled()) + { + c = chain->getCompositor(i); + for (unsigned int j = 0; j < c->getTechnique()->getNumTargetPasses(); ++j) + { + std::string textureName = c->getTechnique()->getTargetPass(j)->getOutputName(); + Ogre::RenderTarget* rt = c->getRenderTarget(textureName); + triangles += rt->getTriangleCount(); + batches += rt->getBatchCount(); + } + } + } +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index bbd838b8e..e5dd7503c 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -44,6 +44,10 @@ namespace MWRender */ void addCompositor (const std::string& name, const int priority); + bool anyCompositorEnabled(); + + void countTrianglesBatches(unsigned int &triangles, unsigned int &batches); + void removeAll (); protected: diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 266362f9b..1029b5b60 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -677,4 +677,17 @@ void RenderingManager::applyCompositors() mWater->assignTextures(); } +void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) +{ + if (mCompositors->anyCompositorEnabled()) + { + mCompositors->countTrianglesBatches(triangles, batches); + } + else + { + triangles = mRendering.getWindow()->getTriangleCount(); + batches = mRendering.getWindow()->getBatchCount(); + } +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 642c42930..20f22fcca 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -118,14 +118,16 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void disableLights(); void enableLights(); - bool occlusionQuerySupported() { return mOcclusionQuery->supported(); }; - OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; }; + bool occlusionQuerySupported() { return mOcclusionQuery->supported(); } + OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; } Shadows* getShadows(); void switchToInterior(); void switchToExterior(); + void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches); + void setGlare(bool glare); void skyEnable (); void skyDisable (); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index e8d555689..79fd03e36 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -1039,4 +1039,9 @@ namespace MWWorld { mRendering->processChangedSettings(settings); } + + void World::getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) + { + mRendering->getTriangleBatchCount(triangles, batches); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index e8391773b..34990574e 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -133,6 +133,8 @@ namespace MWWorld void adjustSky(); + void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches); + void setFallbackValues(std::map fallbackMap); std::string getFallback(std::string key); From 797c2c538d9d6e02002391c0ad2dce8c489335b8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Jun 2012 12:25:28 +0200 Subject: [PATCH 288/289] fix some settings bugs --- apps/openmw/mwgui/settingswindow.cpp | 37 +++++++++++++++++----------- components/settings/settings.cpp | 2 ++ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index eafbd3462..8dcea6d89 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -5,6 +5,7 @@ #include #include +#include #include @@ -39,6 +40,17 @@ namespace else return "Trilinear"; } + + void parseResolution (int &x, int &y, const std::string& str) + { + std::vector split; + boost::algorithm::split (split, str, boost::is_any_of("x")); + assert (split.size() >= 2); + boost::trim(split[0]); + boost::trim(split[1]); + x = boost::lexical_cast (split[0]); + y = boost::lexical_cast (split[1]); + } } namespace MWGui @@ -103,7 +115,12 @@ namespace MWGui for (Ogre::StringVector::const_iterator it=videoModes.begin(); it!=videoModes.end(); ++it) { - mResolutionList->addItem(*it); + int resX, resY; + parseResolution (resX, resY, *it); + std::string str = boost::lexical_cast(resX) + " x " + boost::lexical_cast(resY); + + if (mResolutionList->findItemIndexWith(str) == MyGUI::ITEM_NONE) + mResolutionList->addItem(str); } // read settings @@ -174,13 +191,8 @@ namespace MWGui void SettingsWindow::onResolutionAccept() { std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); - size_t xPos = resStr.find("x"); - std::string resXStr = resStr.substr(0, xPos-1); - Ogre::StringUtil::trim(resXStr); - std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); - Ogre::StringUtil::trim(resYStr); - int resX = boost::lexical_cast(resXStr); - int resY = boost::lexical_cast(resYStr); + int resX, resY; + parseResolution (resX, resY, resStr); Settings::Manager::setInt("resolution x", "Video", resX); Settings::Manager::setInt("resolution y", "Video", resY); @@ -217,13 +229,8 @@ namespace MWGui for (unsigned int i=0; igetItemCount(); ++i) { std::string resStr = mResolutionList->getItemNameAt(i); - size_t xPos = resStr.find("x"); - std::string resXStr = resStr.substr(0, xPos-1); - Ogre::StringUtil::trim(resXStr); - std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); - Ogre::StringUtil::trim(resYStr); - int resX = boost::lexical_cast(resXStr); - int resY = boost::lexical_cast(resYStr); + int resX, resY; + parseResolution (resX, resY, resStr); if (resX == Settings::Manager::getInt("resolution x", "Video") && resY == Settings::Manager::getInt("resolution y", "Video")) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 9b941e253..dd89dde65 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -66,6 +66,8 @@ void Manager::saveUser(const std::string& file) } fout << it->first.second << " = " << it->second << '\n'; } + + fout.close(); } const std::string Manager::getString (const std::string& setting, const std::string& category) From 232fe0be8c411f2e793429b062c4188d9e16fef1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 26 Jun 2012 18:03:52 +0200 Subject: [PATCH 289/289] fix for the directx crash --- apps/openmw/mwgui/settingswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 8dcea6d89..1d1836e9f 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -44,7 +44,7 @@ namespace void parseResolution (int &x, int &y, const std::string& str) { std::vector split; - boost::algorithm::split (split, str, boost::is_any_of("x")); + boost::algorithm::split (split, str, boost::is_any_of("x@")); assert (split.size() >= 2); boost::trim(split[0]); boost::trim(split[1]);