From eb6590f7d88ef0027bb3ab59c44cd2507168c457 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 10 Feb 2013 17:21:25 +0100 Subject: [PATCH 01/11] added delegate factory --- apps/opencs/view/doc/viewmanager.cpp | 6 +++- apps/opencs/view/doc/viewmanager.hpp | 6 ++++ apps/opencs/view/world/table.cpp | 7 +++- apps/opencs/view/world/util.cpp | 53 ++++++++++++++++++++++++++++ apps/opencs/view/world/util.hpp | 48 +++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b01b9ce342..2a6309da1c 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -6,6 +6,8 @@ #include "../../model/doc/documentmanager.hpp" #include "../../model/doc/document.hpp" +#include "../world/util.hpp" + #include "view.hpp" void CSVDoc::ViewManager::updateIndices() @@ -29,11 +31,13 @@ void CSVDoc::ViewManager::updateIndices() CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager) { - + mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; } CSVDoc::ViewManager::~ViewManager() { + delete mDelegateFactories; + for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; } diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 91a80d4962..72e7a3e1a1 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -11,6 +11,11 @@ namespace CSMDoc class DocumentManager; } +namespace CSVWorld +{ + class CommandDelegateFactoryCollection; +} + namespace CSVDoc { class View; @@ -21,6 +26,7 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; + CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; // not implemented ViewManager (const ViewManager&); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 0721ead2c0..f9167d2591 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -102,7 +102,12 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q if (flags & CSMWorld::ColumnBase::Flag_Table) { - CommandDelegate *delegate = new CommandDelegate (undoStack, this); + CSMWorld::ColumnBase::Display display = static_cast ( + mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); + + CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate (display, + undoStack, this); + mDelegates.push_back (delegate); setItemDelegateForColumn (i, delegate); } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 7181dd4d17..85fda2dad1 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -1,6 +1,8 @@ #include "util.hpp" +#include + #include #include "../../model/world/commands.hpp" @@ -35,6 +37,57 @@ QVariant CSVWorld::NastyTableModelHack::getData() const return mData; } + +CSVWorld::CommandDelegateFactory::~CommandDelegateFactory() {} + + +CSVWorld::CommandDelegateFactoryCollection *CSVWorld::CommandDelegateFactoryCollection::sThis = 0; + +CSVWorld::CommandDelegateFactoryCollection::CommandDelegateFactoryCollection() +{ + if (sThis) + throw std::logic_error ("multiple instances of CSVWorld::CommandDelegateFactoryCollection"); + + sThis = this; +} + +CSVWorld::CommandDelegateFactoryCollection::~CommandDelegateFactoryCollection() +{ + sThis = 0; + + for (std::map::iterator iter ( + mFactories.begin()); + iter!=mFactories.end(); ++iter) + delete iter->second; +} + +void CSVWorld::CommandDelegateFactoryCollection::add (CSMWorld::ColumnBase::Display display, + CommandDelegateFactory *factory) +{ + mFactories.insert (std::make_pair (display, factory)); +} + +CSVWorld::CommandDelegate *CSVWorld::CommandDelegateFactoryCollection::makeDelegate ( + CSMWorld::ColumnBase::Display display, QUndoStack& undoStack, QObject *parent) const +{ + std::map::const_iterator iter = + mFactories.find (display); + + if (iter!=mFactories.end()) + return iter->second->makeDelegate (undoStack, parent); + + return new CommandDelegate (undoStack, parent); +} + +const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFactoryCollection::get() +{ + if (!sThis) + throw std::logic_error ("no instance of CSVWorld::CommandDelegateFactoryCollection"); + + return *sThis; +} + + CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) : QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) {} diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 1365831186..79f30da2c2 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -1,9 +1,13 @@ #ifndef CSV_WORLD_UTIL_H #define CSV_WORLD_UTIL_H +#include + #include #include +#include "../../model/world/columnbase.hpp" + class QUndoStack; namespace CSVWorld @@ -31,6 +35,50 @@ namespace CSVWorld QVariant getData() const; }; + class CommandDelegate; + + class CommandDelegateFactory + { + public: + + virtual ~CommandDelegateFactory(); + + virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const = 0; + ///< The ownership of the returned CommandDelegate is transferred to the caller. + }; + + class CommandDelegateFactoryCollection + { + static CommandDelegateFactoryCollection *sThis; + std::map mFactories; + + private: + + // not implemented + CommandDelegateFactoryCollection (const CommandDelegateFactoryCollection&); + CommandDelegateFactoryCollection& operator= (const CommandDelegateFactoryCollection&); + + public: + + CommandDelegateFactoryCollection(); + + ~CommandDelegateFactoryCollection(); + + void add (CSMWorld::ColumnBase::Display display, CommandDelegateFactory *factory); + ///< The ownership of \æ factory is transferred to *this. + /// + /// This function must not be called more than once per value of \æ display. + + CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, QUndoStack& undoStack, + QObject *parent) const; + ///< The ownership of the returned CommandDelegate is transferred to the caller. + /// + /// If no factory is registered for \a display, a CommandDelegate will be returned. + + static const CommandDelegateFactoryCollection& get(); + + }; + ///< \brief Use commands instead of manipulating the model directly class CommandDelegate : public QStyledItemDelegate { From ceefae81e8ea34fdafc2682b2f6a777d65b02587 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sun, 17 Feb 2013 07:46:50 -0600 Subject: [PATCH 02/11] fix for the opencs icon --- apps/opencs/CMakeLists.txt | 6 +++--- apps/opencs/main.cpp | 6 +++++- files/opencs/opencs.png | Bin 0 -> 65168 bytes files/opencs/resources.qrc | 5 +++++ 4 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 files/opencs/opencs.png create mode 100644 files/opencs/resources.qrc diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d1cfbea524..af8fb59817 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -40,7 +40,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc - viewmanager view operations operation subview + viewmanager view operations operation subview startup ) opencs_units_noqt (view/doc @@ -73,7 +73,7 @@ opencs_units_noqt (view/tools set (OPENCS_US ) -set (OPENCS_RES +set (OPENCS_RES ../../files/opencs/resources.qrc ) source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) @@ -102,4 +102,4 @@ target_link_libraries(opencs ${Boost_LIBRARIES} ${QT_LIBRARIES} components -) \ No newline at end of file +) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 4b1a688c26..aa315804b2 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -5,6 +5,7 @@ #include #include +#include class Application : public QApplication { @@ -31,9 +32,12 @@ class Application : public QApplication int main(int argc, char *argv[]) { + Q_INIT_RESOURCE (resources); Application mApplication (argc, argv); + mApplication.setWindowIcon (QIcon (":./opencs.png")); + CS::Editor editor; return editor.run(); -} \ No newline at end of file +} diff --git a/files/opencs/opencs.png b/files/opencs/opencs.png new file mode 100644 index 0000000000000000000000000000000000000000..dddf220a3cbd0df1f4437ce4e00a95aef4b0e4a9 GIT binary patch literal 65168 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 + + opencs.png + + From 00db13be32d0ec107541e3427934117e900fb152 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 15:56:22 +0100 Subject: [PATCH 03/11] Reverted previous commits, and handle disallowed inventory in MWWorld::Class. Wanted to avoid this, but the previous solution broke teleport door sounds. Also fixed book/scroll window take button showing when inventory was not allowed. --- apps/openmw/mwclass/apparatus.cpp | 4 ++++ apps/openmw/mwclass/armor.cpp | 4 ++++ apps/openmw/mwclass/clothing.cpp | 4 ++++ apps/openmw/mwclass/container.cpp | 4 ++++ apps/openmw/mwclass/ingredient.cpp | 4 ++++ apps/openmw/mwclass/light.cpp | 3 +++ apps/openmw/mwclass/lockpick.cpp | 4 ++++ apps/openmw/mwclass/misc.cpp | 4 ++++ apps/openmw/mwclass/potion.cpp | 4 ++++ apps/openmw/mwclass/probe.cpp | 4 ++++ apps/openmw/mwclass/repair.cpp | 4 ++++ apps/openmw/mwclass/weapon.cpp | 4 ++++ apps/openmw/mwgui/bookwindow.cpp | 15 ++++++++++++--- apps/openmw/mwgui/bookwindow.hpp | 5 +++++ apps/openmw/mwgui/scrollwindow.cpp | 15 ++++++++++++--- apps/openmw/mwgui/scrollwindow.hpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.cpp | 15 ++++++++++++++- apps/openmw/mwworld/action.cpp | 4 +++- apps/openmw/mwworld/action.hpp | 3 +-- apps/openmw/mwworld/actionalchemy.cpp | 3 +-- apps/openmw/mwworld/actionalchemy.hpp | 2 +- apps/openmw/mwworld/actionapply.cpp | 6 ++---- apps/openmw/mwworld/actionapply.hpp | 4 ++-- apps/openmw/mwworld/actioneat.cpp | 4 +--- apps/openmw/mwworld/actioneat.hpp | 2 +- apps/openmw/mwworld/actionequip.cpp | 4 +--- apps/openmw/mwworld/actionequip.hpp | 2 +- apps/openmw/mwworld/actionopen.cpp | 5 ++--- apps/openmw/mwworld/actionopen.hpp | 2 +- apps/openmw/mwworld/actionread.cpp | 3 +-- apps/openmw/mwworld/actionread.hpp | 2 +- apps/openmw/mwworld/actiontake.cpp | 7 +------ apps/openmw/mwworld/actiontake.hpp | 2 +- apps/openmw/mwworld/actiontalk.cpp | 4 +--- apps/openmw/mwworld/actiontalk.hpp | 2 +- apps/openmw/mwworld/actionteleport.cpp | 3 +-- apps/openmw/mwworld/actionteleport.hpp | 2 +- apps/openmw/mwworld/failedaction.cpp | 9 ++++----- apps/openmw/mwworld/failedaction.hpp | 4 ++-- apps/openmw/mwworld/nullaction.hpp | 2 +- 40 files changed, 127 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 06467bb21a..2c561eb858 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -12,6 +12,7 @@ #include "../mwworld/actionalchemy.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -61,6 +62,9 @@ namespace MWClass boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action( new MWWorld::ActionTake (ptr)); diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 704173b1c4..654cb87fd6 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -15,6 +15,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -64,6 +65,9 @@ namespace MWClass boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index c411bb1930..892ac091ce 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -13,6 +13,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -62,6 +63,9 @@ namespace MWClass boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index bbe005955c..a2d75131eb 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/failedaction.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/customdata.hpp" #include "../mwworld/cellstore.hpp" @@ -85,6 +86,9 @@ namespace MWClass boost::shared_ptr Container::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + const std::string lockedSound = "LockedChest"; const std::string trapActivationSound = "Disarm Trap Fail"; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 7ad8f1b47c..bbba45df58 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -13,6 +13,7 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/actioneat.hpp" #include "../mwworld/player.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwmechanics/npcstats.hpp" @@ -72,6 +73,9 @@ namespace MWClass boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index b94b0d395b..235e57d375 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -88,6 +88,9 @@ namespace MWClass boost::shared_ptr Light::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index a667fefb2a..7e909437cf 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -13,6 +13,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -62,6 +63,9 @@ namespace MWClass boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index a21cc2aef6..d43a44359f 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/manualref.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -65,6 +66,9 @@ namespace MWClass boost::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 09d152de77..c3a6df2112 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -13,6 +13,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/player.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -62,6 +63,9 @@ namespace MWClass boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action( new MWWorld::ActionTake (ptr)); diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 0d8653aa87..a28be17e7e 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -13,6 +13,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -61,6 +62,9 @@ namespace MWClass boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index edb28d16c2..39a7f65e07 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -11,6 +11,7 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -60,6 +61,9 @@ namespace MWClass boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index c8fe0d2768..d8c11558cc 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -13,6 +13,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwgui/tooltips.hpp" @@ -62,6 +63,9 @@ namespace MWClass boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return boost::shared_ptr (new MWWorld::NullAction ()); + boost::shared_ptr action(new MWWorld::ActionTake (ptr)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 659795e188..777751069b 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -14,8 +14,10 @@ using namespace MWGui; -BookWindow::BookWindow (MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_book.layout", parWindowManager) +BookWindow::BookWindow (MWBase::WindowManager& parWindowManager) + : WindowBase("openmw_book.layout", parWindowManager) + , mTakeButtonShow(true) + , mTakeButtonAllowed(true) { getWidget(mCloseButton, "CloseButton"); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked); @@ -85,7 +87,14 @@ void BookWindow::open (MWWorld::Ptr book) void BookWindow::setTakeButtonShow(bool show) { - mTakeButton->setVisible(show); + mTakeButtonShow = show; + mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); +} + +void BookWindow::setInventoryAllowed(bool allowed) +{ + mTakeButtonAllowed = allowed; + mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); } void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index 5887975ea4..a509f131fe 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -17,6 +17,8 @@ namespace MWGui void open(MWWorld::Ptr book); void setTakeButtonShow(bool show); + void setInventoryAllowed(bool allowed); + protected: void onNextPageButtonClicked (MyGUI::Widget* sender); void onPrevPageButtonClicked (MyGUI::Widget* sender); @@ -40,6 +42,9 @@ namespace MWGui std::vector mPages; MWWorld::Ptr mBook; + + bool mTakeButtonShow; + bool mTakeButtonAllowed; }; } diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 8317025e0b..3bd3a47439 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -12,8 +12,10 @@ using namespace MWGui; -ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_scroll.layout", parWindowManager) +ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager) + : WindowBase("openmw_scroll.layout", parWindowManager) + , mTakeButtonShow(true) + , mTakeButtonAllowed(true) { getWidget(mTextView, "TextView"); @@ -50,7 +52,14 @@ void ScrollWindow::open (MWWorld::Ptr scroll) void ScrollWindow::setTakeButtonShow(bool show) { - mTakeButton->setVisible(show); + mTakeButtonShow = show; + mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); +} + +void ScrollWindow::setInventoryAllowed(bool allowed) +{ + mTakeButtonAllowed = allowed; + mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); } void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 7932a215b8..42b6395a9a 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -15,6 +15,7 @@ namespace MWGui void open (MWWorld::Ptr scroll); void setTakeButtonShow(bool show); + void setInventoryAllowed(bool allowed); protected: void onCloseButtonClicked (MyGUI::Widget* _sender); @@ -26,6 +27,10 @@ namespace MWGui MyGUI::ScrollView* mTextView; MWWorld::Ptr mScroll; + + bool mTakeButtonShow; + bool mTakeButtonAllowed; + }; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e360aad19b..e03b91216d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -109,7 +109,6 @@ WindowManager::WindowManager( , mHudEnabled(true) , mTranslationDataStorage (translationDataStorage) { - // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath); mGui = mGuiManager->getGui(); @@ -196,6 +195,9 @@ WindowManager::WindowManager( unsetSelectedSpell(); unsetSelectedWeapon(); + if (newGame) + disallowAll (); + // Set up visibility updateVisible(); } @@ -943,12 +945,23 @@ bool WindowManager::isAllowed (GuiWindow wnd) const void WindowManager::allow (GuiWindow wnd) { mAllowed = (GuiWindow)(mAllowed | wnd); + + if (wnd & GW_Inventory) + { + mBookWindow->setInventoryAllowed (true); + mScrollWindow->setInventoryAllowed (true); + } + updateVisible(); } void WindowManager::disallowAll() { mAllowed = GW_None; + + mBookWindow->setInventoryAllowed (false); + mScrollWindow->setInventoryAllowed (false); + updateVisible(); } diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index 0d50d8deda..a5199fb3ea 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -18,7 +18,7 @@ MWWorld::Action::~Action() {} void MWWorld::Action::execute (const Ptr& actor) { - if (!mSoundId.empty() & executeImp (actor)) + if (!mSoundId.empty()) { if (mKeepSound && actor.getRefData().getHandle()=="player") { @@ -35,6 +35,8 @@ void MWWorld::Action::execute (const Ptr& actor) mKeepSound ? MWBase::SoundManager::Play_NoTrack : MWBase::SoundManager::Play_Normal); } } + + executeImp (actor); } void MWWorld::Action::setSound (const std::string& id) diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index 42c2ad0844..d8e5d93bb2 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -18,8 +18,7 @@ namespace MWWorld Action (const Action& action); Action& operator= (const Action& action); - /// @return true if the sound should be played, false if not (e.g. if the action is not allowed) - virtual bool executeImp (const Ptr& actor) = 0; + virtual void executeImp (const Ptr& actor) = 0; protected: diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index 20093279e0..bba75bc499 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -5,9 +5,8 @@ namespace MWWorld { - bool ActionAlchemy::executeImp (const Ptr& actor) + void ActionAlchemy::executeImp (const Ptr& actor) { MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy); - return true; } } diff --git a/apps/openmw/mwworld/actionalchemy.hpp b/apps/openmw/mwworld/actionalchemy.hpp index 814f347c88..e6d1a7976c 100644 --- a/apps/openmw/mwworld/actionalchemy.hpp +++ b/apps/openmw/mwworld/actionalchemy.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionAlchemy : public Action { - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); }; } diff --git a/apps/openmw/mwworld/actionapply.cpp b/apps/openmw/mwworld/actionapply.cpp index 2a41b5613f..f78b8f7988 100644 --- a/apps/openmw/mwworld/actionapply.cpp +++ b/apps/openmw/mwworld/actionapply.cpp @@ -9,10 +9,9 @@ namespace MWWorld : Action (false, target), mId (id) {} - bool ActionApply::executeImp (const Ptr& actor) + void ActionApply::executeImp (const Ptr& actor) { MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor); - return true; } @@ -21,10 +20,9 @@ namespace MWWorld : Action (false, target), mId (id), mSkillIndex (skillIndex), mUsageType (usageType) {} - bool ActionApplyWithSkill::executeImp (const Ptr& actor) + void ActionApplyWithSkill::executeImp (const Ptr& actor) { if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1) MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType); - return true; } } diff --git a/apps/openmw/mwworld/actionapply.hpp b/apps/openmw/mwworld/actionapply.hpp index 53b2de1d08..3353ae0eed 100644 --- a/apps/openmw/mwworld/actionapply.hpp +++ b/apps/openmw/mwworld/actionapply.hpp @@ -13,7 +13,7 @@ namespace MWWorld { std::string mId; - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: @@ -26,7 +26,7 @@ namespace MWWorld int mSkillIndex; int mUsageType; - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: diff --git a/apps/openmw/mwworld/actioneat.cpp b/apps/openmw/mwworld/actioneat.cpp index 81c45f051e..63efff738e 100644 --- a/apps/openmw/mwworld/actioneat.cpp +++ b/apps/openmw/mwworld/actioneat.cpp @@ -16,7 +16,7 @@ namespace MWWorld { - bool ActionEat::executeImp (const Ptr& actor) + void ActionEat::executeImp (const Ptr& actor) { // remove used item getTarget().getRefData().setCount (getTarget().getRefData().getCount()-1); @@ -42,8 +42,6 @@ namespace MWWorld // increase skill Class::get (actor).skillUsageSucceeded (actor, ESM::Skill::Alchemy, 1); } - - return true; } ActionEat::ActionEat (const MWWorld::Ptr& object) : Action (false, object) {} diff --git a/apps/openmw/mwworld/actioneat.hpp b/apps/openmw/mwworld/actioneat.hpp index 265f5aa68a..ce5330db77 100644 --- a/apps/openmw/mwworld/actioneat.hpp +++ b/apps/openmw/mwworld/actioneat.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionEat : public Action { - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 902e0fdb69..2d257aa614 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -16,7 +16,7 @@ namespace MWWorld { } - bool ActionEquip::executeImp (const Ptr& actor) + void ActionEquip::executeImp (const Ptr& actor) { MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); @@ -113,7 +113,5 @@ namespace MWWorld /* Set OnPCEquip Variable on item's script, if the player is equipping it, and it has a script with that variable declared */ if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && script != "") (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 1); - - return true; } } diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp index fb3a1ac10e..3b56c74027 100644 --- a/apps/openmw/mwworld/actionequip.hpp +++ b/apps/openmw/mwworld/actionequip.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionEquip : public Action { - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: /// @param item to equip diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index da570dff02..040a3856e8 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -14,13 +14,12 @@ namespace MWWorld { } - bool ActionOpen::executeImp (const MWWorld::Ptr& actor) + void ActionOpen::executeImp (const MWWorld::Ptr& actor) { if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) - return false; + return; MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget()); - return true; } } diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp index 42ad4aecbe..c49ebefa51 100644 --- a/apps/openmw/mwworld/actionopen.hpp +++ b/apps/openmw/mwworld/actionopen.hpp @@ -10,7 +10,7 @@ namespace MWWorld { class ActionOpen : public Action { - virtual bool executeImp (const MWWorld::Ptr& actor); + virtual void executeImp (const MWWorld::Ptr& actor); public: ActionOpen (const Ptr& container); diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 157b051d6f..6d5d9d8fde 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -19,7 +19,7 @@ namespace MWWorld { } - bool ActionRead::executeImp (const MWWorld::Ptr& actor) + void ActionRead::executeImp (const MWWorld::Ptr& actor) { LiveCellRef *ref = getTarget().get(); @@ -53,6 +53,5 @@ namespace MWWorld npcStats.flagAsUsed (ref->mBase->mId); } - return true; } } diff --git a/apps/openmw/mwworld/actionread.hpp b/apps/openmw/mwworld/actionread.hpp index dfb536c64a..00a4756dda 100644 --- a/apps/openmw/mwworld/actionread.hpp +++ b/apps/openmw/mwworld/actionread.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionRead : public Action { - virtual bool executeImp (const MWWorld::Ptr& actor); + virtual void executeImp (const MWWorld::Ptr& actor); public: /// @param book or scroll to read diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index fef8a7e73a..cdd19b46e4 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -12,18 +12,13 @@ namespace MWWorld { ActionTake::ActionTake (const MWWorld::Ptr& object) : Action (true, object) {} - bool ActionTake::executeImp (const Ptr& actor) + void ActionTake::executeImp (const Ptr& actor) { - if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) - return false; - // insert into player's inventory MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true); MWWorld::Class::get (player).getContainerStore (player).add (getTarget()); MWBase::Environment::get().getWorld()->deleteObject (getTarget()); - - return true; } } diff --git a/apps/openmw/mwworld/actiontake.hpp b/apps/openmw/mwworld/actiontake.hpp index 2a87156d0a..b0a9b82478 100644 --- a/apps/openmw/mwworld/actiontake.hpp +++ b/apps/openmw/mwworld/actiontake.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionTake : public Action { - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 6bee9eb26e..905497f85b 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -3,15 +3,13 @@ #include "../mwbase/environment.hpp" #include "../mwbase/dialoguemanager.hpp" -#include "../mwbase/inputmanager.hpp" namespace MWWorld { ActionTalk::ActionTalk (const Ptr& actor) : Action (false, actor) {} - bool ActionTalk::executeImp (const Ptr& actor) + void ActionTalk::executeImp (const Ptr& actor) { MWBase::Environment::get().getDialogueManager()->startDialogue (getTarget()); - return true; } } diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index 91c71dc79b..b88b168d8c 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionTalk : public Action { - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 9b21cc8763..ae5ffc3b90 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -12,12 +12,11 @@ namespace MWWorld { } - bool ActionTeleport::executeImp (const Ptr& actor) + void ActionTeleport::executeImp (const Ptr& actor) { if (mCellName.empty()) MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition); else MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, mPosition); - return true; } } diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index 4f771cac99..a13cb61b21 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -14,7 +14,7 @@ namespace MWWorld std::string mCellName; ESM::Position mPosition; - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: diff --git a/apps/openmw/mwworld/failedaction.cpp b/apps/openmw/mwworld/failedaction.cpp index e2ca78b2c7..ec763dba01 100644 --- a/apps/openmw/mwworld/failedaction.cpp +++ b/apps/openmw/mwworld/failedaction.cpp @@ -11,12 +11,11 @@ namespace MWWorld { } - bool FailedAction::executeImp (const Ptr& actor) + void FailedAction::executeImp (const Ptr& actor) { if ( actor.getRefData().getHandle()=="player" && !(message.empty())) - { - MWBase::Environment::get().getWindowManager() ->messageBox(message, std::vector()); - } - return true; + { + MWBase::Environment::get().getWindowManager() ->messageBox(message, std::vector()); + } } } diff --git a/apps/openmw/mwworld/failedaction.hpp b/apps/openmw/mwworld/failedaction.hpp index 7d64afe74b..e736bfb63b 100644 --- a/apps/openmw/mwworld/failedaction.hpp +++ b/apps/openmw/mwworld/failedaction.hpp @@ -10,11 +10,11 @@ namespace MWWorld { std::string message; - virtual bool executeImp (const Ptr& actor); + virtual void executeImp (const Ptr& actor); public: FailedAction (const std::string& message = std::string()); }; } -#endif +#endif \ No newline at end of file diff --git a/apps/openmw/mwworld/nullaction.hpp b/apps/openmw/mwworld/nullaction.hpp index f5544e4c10..7ef8b4a065 100644 --- a/apps/openmw/mwworld/nullaction.hpp +++ b/apps/openmw/mwworld/nullaction.hpp @@ -8,7 +8,7 @@ namespace MWWorld /// \brief Action: do nothing class NullAction : public Action { - virtual bool executeImp (const Ptr& actor) {return false;} + virtual void executeImp (const Ptr& actor) {} }; } From d899f334444665ef073ac3d6f77623000f7831d9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 16:00:31 +0100 Subject: [PATCH 04/11] Race/Class/Birth dialogs: immediately enable OK buttons since they have a preselected entry now. --- apps/openmw/mwgui/birth.cpp | 3 --- apps/openmw/mwgui/class.cpp | 3 --- apps/openmw/mwgui/race.cpp | 3 --- 3 files changed, 9 deletions(-) diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 99d6605d33..c53a68cf44 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -48,7 +48,6 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) getWidget(okButton, "OKButton"); okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); - okButton->setEnabled(false); updateBirths(); updateSpells(); @@ -85,7 +84,6 @@ void BirthDialog::setBirthId(const std::string &birthId) mBirthList->setIndexSelected(i); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); break; } } @@ -114,7 +112,6 @@ void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); const std::string *birthId = mBirthList->getItemDataAt(_index); if (boost::iequals(mCurrentBirthId, *birthId)) diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 475efaab31..2eed21a528 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -104,7 +104,6 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked); - okButton->setEnabled(false); updateClasses(); updateStats(); @@ -140,7 +139,6 @@ void PickClassDialog::setClassId(const std::string &classId) mClassList->setIndexSelected(i); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); break; } } @@ -169,7 +167,6 @@ void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); const std::string *classId = mClassList->getItemDataAt(_index); if (boost::iequals(mCurrentClassId, *classId)) diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index df6c993401..054cce7b85 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -81,7 +81,6 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) getWidget(okButton, "OKButton"); okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); - okButton->setEnabled(false); updateRaces(); updateSkills(); @@ -135,7 +134,6 @@ void RaceDialog::setRaceId(const std::string &raceId) mRaceList->setIndexSelected(i); MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); break; } } @@ -258,7 +256,6 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) MyGUI::ButtonPtr okButton; getWidget(okButton, "OKButton"); - okButton->setEnabled(true); const std::string *raceId = mRaceList->getItemDataAt(_index); if (boost::iequals(mCurrentRaceId, *raceId)) return; From 5a11ddc485db96390d2bce1e07460ac3def4ff68 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 16:01:36 +0100 Subject: [PATCH 05/11] Pressing F1 again hides the quick keys menu. --- apps/openmw/mwinput/inputmanagerimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 02a699eced..b065b7f7fd 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -638,6 +638,8 @@ namespace MWInput { if (!mWindows.isGuiMode ()) mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu); + else if (mWindows.getMode () == MWGui::GM_QuickKeysMenu) + mWindows.removeGuiMode (MWGui::GM_QuickKeysMenu); } void InputManager::activate() From 50d61a5b6e057c194f4fddb4d12ee910e1295cda Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 Feb 2013 17:27:25 +0100 Subject: [PATCH 06/11] proper implementation of gmst type column --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/columnbase.hpp | 3 +- apps/opencs/model/world/columns.hpp | 5 +- apps/opencs/view/doc/viewmanager.cpp | 5 + apps/opencs/view/world/enumdelegate.cpp | 101 ++++++++++++++++++++ apps/opencs/view/world/enumdelegate.hpp | 57 ++++++++++++ apps/opencs/view/world/util.cpp | 25 ++++- apps/opencs/view/world/util.hpp | 12 ++- apps/opencs/view/world/vartypedelegate.cpp | 103 +++++++++++++++++++++ apps/opencs/view/world/vartypedelegate.hpp | 38 ++++++++ 10 files changed, 342 insertions(+), 9 deletions(-) create mode 100644 apps/opencs/view/world/enumdelegate.cpp create mode 100644 apps/opencs/view/world/enumdelegate.hpp create mode 100644 apps/opencs/view/world/vartypedelegate.cpp create mode 100644 apps/opencs/view/world/vartypedelegate.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8cee3f0f4e..083aa96304 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -59,7 +59,7 @@ opencs_units (view/world ) opencs_units_noqt (view/world - dialoguesubview util subviews + dialoguesubview util subviews enumdelegate vartypedelegate ) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index f1871a6a94..40581972e9 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -29,7 +29,8 @@ namespace CSMWorld Display_String, Display_Integer, Display_Float, - Display_Var + Display_Var, + Display_VarType }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index cfbd804a5a..2d81a24e90 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -79,7 +79,7 @@ namespace CSMWorld int mType; FixedRecordTypeColumn (int type) - : Column ("Type", ColumnBase::Display_Integer, 0), mType (type) {} + : Column ("Record Type", ColumnBase::Display_Integer, 0), mType (type) {} virtual QVariant get (const Record& record) const { @@ -92,10 +92,11 @@ namespace CSMWorld } }; + /// \attention A var type column must be immediately followed by a suitable value column. template struct VarTypeColumn : public Column { - VarTypeColumn() : Column ("Type", ColumnBase::Display_Integer) {} + VarTypeColumn() : Column ("Type", ColumnBase::Display_VarType) {} virtual QVariant get (const Record& record) const { diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 2a6309da1c..473049999c 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -7,6 +7,8 @@ #include "../../model/doc/document.hpp" #include "../world/util.hpp" +#include "../world/enumdelegate.hpp" +#include "../world/vartypedelegate.hpp" #include "view.hpp" @@ -32,6 +34,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager) { mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; + + mDelegateFactories->add (CSMWorld::ColumnBase::Display_VarType, + new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float)); } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp new file mode 100644 index 0000000000..7a8b45373d --- /dev/null +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -0,0 +1,101 @@ + +#include "enumdelegate.hpp" + +#include + +#include +#include +#include + +#include "../../model/world/commands.hpp" + +void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + if (QComboBox *comboBox = dynamic_cast (editor)) + { + QString value = comboBox->currentText(); + + for (std::vector >::const_iterator iter (mValues.begin()); + iter!=mValues.end(); ++iter) + if (iter->second==value) + { + addCommands (model, index, iter->first); + break; + } + } +} + +void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model, + const QModelIndex& index, int type) const +{ + getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type)); +} + + +CSVWorld::EnumDelegate::EnumDelegate (const std::vector >& values, + QUndoStack& undoStack, QObject *parent) +: CommandDelegate (undoStack, parent), mValues (values) +{ + +} + +QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + QComboBox *comboBox = new QComboBox (parent); + + for (std::vector >::const_iterator iter (mValues.begin()); + iter!=mValues.end(); ++iter) + comboBox->addItem (iter->second); + + return comboBox; +} + +void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const +{ + if (QComboBox *comboBox = dynamic_cast (editor)) + { + int value = index.data (Qt::EditRole).toInt(); + + std::size_t size = mValues.size(); + + for (std::size_t i=0; isetCurrentIndex (i); + break; + } + } +} + +void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + QStyleOptionViewItemV4 option2 (option); + + int value = index.data().toInt(); + + for (std::vector >::const_iterator iter (mValues.begin()); + iter!=mValues.end(); ++iter) + if (iter->first==value) + { + option2.text = iter->second; + + QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter); + + break; + } +} + + +CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack, + QObject *parent) const +{ + return new EnumDelegate (mValues, undoStack, parent); +} + +void CSVWorld::EnumDelegateFactory::add (int value, const QString& name) +{ + mValues.push_back (std::make_pair (value, name)); +} diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp new file mode 100644 index 0000000000..f11252371e --- /dev/null +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -0,0 +1,57 @@ +#ifndef CSV_WORLD_ENUMDELEGATE_H +#define CSV_WORLD_ENUMDELEGATE_H + +#include + +#include + +#include + +#include "util.hpp" + +namespace CSVWorld +{ + /// \brief Integer value that represents an enum and is interacted with via a combobox + class EnumDelegate : public CommandDelegate + { + std::vector > mValues; + + private: + + virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const; + + virtual void addCommands (QAbstractItemModel *model, + const QModelIndex& index, int type) const; + + public: + + EnumDelegate (const std::vector >& values, + QUndoStack& undoStack, QObject *parent); + + virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, + const QModelIndex& index) const; + + virtual void setEditorData (QWidget *editor, const QModelIndex& index) const; + + virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const; + + }; + + class EnumDelegateFactory : public CommandDelegateFactory + { + std::vector > mValues; + + public: + + virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; + ///< The ownership of the returned CommandDelegate is transferred to the caller. + + void add (int value, const QString& name); + }; + + +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 85fda2dad1..5ada1d84f3 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -88,6 +88,19 @@ const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFacto } +QUndoStack& CSVWorld::CommandDelegate::getUndoStack() const +{ + return mUndoStack; +} + +void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); +} + CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) : QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) {} @@ -97,14 +110,18 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode { if (!mEditLock) { - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + setModelDataImp (editor, model, index); } + ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. } -void CSVWorld::CommandDelegate::setEditLock (bool locked) +void CSVWorld::CommandDelegate::setEditLock (bool locked) { mEditLock = locked; +} + +bool CSVWorld::CommandDelegate::isEditLocked() const +{ + return mEditLock; } \ No newline at end of file diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 79f30da2c2..5334abf9c8 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -85,13 +85,23 @@ namespace CSVWorld QUndoStack& mUndoStack; bool mEditLock; + protected: + + QUndoStack& getUndoStack() const; + + virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const; + public: CommandDelegate (QUndoStack& undoStack, QObject *parent); - void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + virtual void setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const; void setEditLock (bool locked); + + bool isEditLocked() const; }; } diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp new file mode 100644 index 0000000000..3ee759ef2b --- /dev/null +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -0,0 +1,103 @@ + +#include "vartypedelegate.hpp" + +#include + +#include "../../model/world/commands.hpp" + +void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type) + const +{ + QModelIndex next = model->index (index.row(), index.column()+1); + + QVariant old = model->data (next); + + QVariant value; + + switch (type) + { + case ESM::VT_Short: + case ESM::VT_Int: + case ESM::VT_Long: + + value = old.toInt(); + break; + + case ESM::VT_Float: + + value = old.toFloat(); + break; + + case ESM::VT_String: + + value = old.toString(); + break; + + default: break; // ignore the rest + } + + getUndoStack().beginMacro ( + "Modify " + model->headerData (index.column(), Qt::Horizontal, Qt::DisplayRole).toString()); + + getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type)); + getUndoStack().push (new CSMWorld::ModifyCommand (*model, next, value)); + + getUndoStack().endMacro(); +} + +CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector >& values, + QUndoStack& undoStack, QObject *parent) +: EnumDelegate (values, undoStack, parent) +{} + + +CSVWorld::VarTypeDelegateFactory::VarTypeDelegateFactory (ESM::VarType type0, + ESM::VarType type1, ESM::VarType type2, ESM::VarType type3) +{ + if (type0!=ESM::VT_Unknown) + add (type0); + + if (type1!=ESM::VT_Unknown) + add (type1); + + if (type2!=ESM::VT_Unknown) + add (type2); + + if (type3!=ESM::VT_Unknown) + add (type3); +} + +CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndoStack& undoStack, + QObject *parent) const +{ + return new VarTypeDelegate (mValues, undoStack, parent); +} + +void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) +{ + struct Name + { + ESM::VarType mType; + const char *mName; + }; + + static const Name sNames[] = + { + { ESM::VT_None, "empty" }, + { ESM::VT_Short, "short" }, + { ESM::VT_Int, "long" }, + { ESM::VT_Long, "long" }, + { ESM::VT_Float, "float" }, + { ESM::VT_String, "string" }, + { ESM::VT_Unknown, 0 } // end marker + }; + + for (int i=0; sNames[i].mName; ++i) + if (sNames[i].mType==type) + { + mValues.push_back (std::make_pair (type, sNames[i].mName)); + return; + } + + throw std::logic_error ("Unsupported variable type"); +} diff --git a/apps/opencs/view/world/vartypedelegate.hpp b/apps/opencs/view/world/vartypedelegate.hpp new file mode 100644 index 0000000000..621dd316b3 --- /dev/null +++ b/apps/opencs/view/world/vartypedelegate.hpp @@ -0,0 +1,38 @@ +#ifndef CSV_WORLD_VARTYPEDELEGATE_H +#define CSV_WORLD_VARTYPEDELEGATE_H + +#include "enumdelegate.hpp" + +namespace CSVWorld +{ + class VarTypeDelegate : public EnumDelegate + { + private: + + virtual void addCommands (QAbstractItemModel *model, + const QModelIndex& index, int type) const; + + public: + + VarTypeDelegate (const std::vector >& values, + QUndoStack& undoStack, QObject *parent); + }; + + class VarTypeDelegateFactory : public CommandDelegateFactory + { + std::vector > mValues; + + public: + + VarTypeDelegateFactory (ESM::VarType type0 = ESM::VT_Unknown, + ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown, + ESM::VarType type3 = ESM::VT_Unknown); + + virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; + ///< The ownership of the returned CommandDelegate is transferred to the caller. + + void add (ESM::VarType type); + }; +} + +#endif From 170a9762ac0127579c9df4cab14bc8d1732bb2f4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 18:30:21 +0100 Subject: [PATCH 07/11] Fix travel services not actually costing gold. --- apps/openmw/mwgui/travelwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 9615e95f73..465f588b8a 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -132,6 +132,8 @@ namespace MWGui if (mWindowManager.getInventoryWindow()->getPlayerGold()addOrRemoveGold (-price); + MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); ESM::Position pos = *_sender->getUserData(); From e1ca0a15aec61c1bcc3eba325b12476e0600b41a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 18:58:54 +0100 Subject: [PATCH 08/11] Add message box when item is added to player's inventory --- apps/openmw/mwscript/containerextensions.cpp | 23 +++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 4cce19b862..68ae1b516f 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -60,6 +60,27 @@ namespace MWScript } MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr()); + + // The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory + std::string msgBox; + std::string itemName = MWWorld::Class::get(ref.getPtr()).getName(ref.getPtr()); + if (count == 1) + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}"); + std::stringstream temp; + temp << boost::format(msgBox) % itemName; + msgBox = temp.str(); + } + else + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}"); + std::stringstream temp; + temp << boost::format(msgBox) % (count) % itemName; + msgBox = temp.str(); + } + + if(count > 0) + MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); } }; @@ -130,7 +151,7 @@ namespace MWScript } } - /* The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory */ + // The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory std::string msgBox; if(originalCount - count > 1) { From abd307d70e946b9efe259ce6c4ed54d8f2af6b53 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 Feb 2013 19:26:01 +0100 Subject: [PATCH 09/11] Issue #567: workaround for crash with non-English ESX files --- apps/opencs/model/world/data.cpp | 6 +++++- apps/opencs/view/doc/opendialog.cpp | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f120c75f10..92bd2bdb04 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -72,7 +72,11 @@ void CSMWorld::Data::merge() void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) { ESM::ESMReader reader; - /// \todo set encoder + + /// \todo set encoding properly, once config implementation has been fixed. + ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); + reader.setEncoder (&encoder); + reader.open (path.string()); // Note: We do not need to send update signals here, because at this point the model is not connected diff --git a/apps/opencs/view/doc/opendialog.cpp b/apps/opencs/view/doc/opendialog.cpp index 9a5feb23a7..7b62aafa31 100644 --- a/apps/opencs/view/doc/opendialog.cpp +++ b/apps/opencs/view/doc/opendialog.cpp @@ -10,48 +10,48 @@ OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent) QVBoxLayout *layout = new QVBoxLayout(this); mFileSelector = new DataFilesList(mCfgMgr, this); layout->addWidget(mFileSelector); - - //FIXME - same as DataFilesPage::setupDataFiles + + /// \todo move config to Editor class and add command line options. // We use the Configuration Manager to retrieve the configuration values boost::program_options::variables_map variables; boost::program_options::options_description desc; - + desc.add_options() ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) ("data-local", boost::program_options::value()->default_value("")) ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) ("encoding", boost::program_options::value()->default_value("win1252")); - + boost::program_options::notify(variables); - + mCfgMgr.readConfiguration(variables, desc); - + Files::PathContainer mDataDirs, mDataLocal; if (!variables["data"].empty()) { mDataDirs = Files::PathContainer(variables["data"].as()); } - + std::string local = variables["data-local"].as(); if (!local.empty()) { mDataLocal.push_back(Files::PathContainer::value_type(local)); } - + mCfgMgr.processPaths(mDataDirs); mCfgMgr.processPaths(mDataLocal); - + // Set the charset for reading the esm/esp files QString encoding = QString::fromStdString(variables["encoding"].as()); - + Files::PathContainer dataDirs; dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); mFileSelector->setupDataFiles(dataDirs, encoding); - + buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); layout->addWidget(buttonBox); - + setLayout(layout); setWindowTitle(tr("Open")); } From 52d0f0b750ecca5b72892a6e815a1332299594fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 19:44:00 +0100 Subject: [PATCH 10/11] Fixed OpAddItem, OpRemoveItem --- apps/openmw/mwscript/containerextensions.cpp | 84 +++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 68ae1b516f..81639b5be9 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -21,6 +21,7 @@ #include "../mwworld/containerstore.hpp" #include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/player.hpp" #include "interpretercontext.hpp" #include "ref.hpp" @@ -47,6 +48,10 @@ namespace MWScript if (count<0) throw std::runtime_error ("second argument for AddItem must be non-negative"); + // no-op + if (count == 0) + return; + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item); ref.getPtr().getRefData().setCount (count); @@ -61,26 +66,25 @@ namespace MWScript MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr()); - // The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory - std::string msgBox; - std::string itemName = MWWorld::Class::get(ref.getPtr()).getName(ref.getPtr()); - if (count == 1) + // Spawn a messagebox (only for items added to player's inventory) + if (ptr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer()) { - msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}"); - std::stringstream temp; - temp << boost::format(msgBox) % itemName; - msgBox = temp.str(); - } - else - { - msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}"); - std::stringstream temp; - temp << boost::format(msgBox) % (count) % itemName; - msgBox = temp.str(); - } + // The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory + std::string msgBox; + std::string itemName = MWWorld::Class::get(ref.getPtr()).getName(ref.getPtr()); + if (count == 1) + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}"); + msgBox = boost::str(boost::format(msgBox) % itemName); + } + else + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}"); + msgBox = boost::str(boost::format(msgBox) % count % itemName); + } - if(count > 0) MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); + } } }; @@ -122,13 +126,19 @@ namespace MWScript Interpreter::Type_Integer count = runtime[0].mInteger; runtime.pop(); - + if (count<0) throw std::runtime_error ("second argument for RemoveItem must be non-negative"); + // no-op + if (count == 0) + return; + MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); std::string itemName = ""; + + // originalCount holds the total number of items to remove, count holds the remaining number of items to remove Interpreter::Type_Integer originalCount = count; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; @@ -151,28 +161,26 @@ namespace MWScript } } - // The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory - std::string msgBox; - if(originalCount - count > 1) + // Spawn a messagebox (only for items added to player's inventory) + if (ptr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer()) { - msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}"); - std::stringstream temp; - temp << boost::format(msgBox) % (originalCount - count) % itemName; - msgBox = temp.str(); - } - else - { - msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); - std::stringstream temp; - temp << boost::format(msgBox) % itemName; - msgBox = temp.str(); - } - - if(originalCount - count > 0) - MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); + // The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory + std::string msgBox; + int numRemoved = (originalCount - count); + if(numRemoved > 1) + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}"); + msgBox = boost::str (boost::format(msgBox) % numRemoved % itemName); + } + else + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); + msgBox = boost::str (boost::format(msgBox) % itemName); + } - // To be fully compatible with original Morrowind, we would need to check if - // count is >= 0 here and throw an exception. But let's be tollerant instead. + if (numRemoved > 0) + MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); + } } }; From b52df83d8461978478df3899fd537590e65baabd Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 20:23:22 +0100 Subject: [PATCH 11/11] Pressing Enter should skip _one_ message box, not skip all message boxes until the key is released again --- apps/openmw/mwinput/inputmanagerimp.cpp | 17 +++++++---------- apps/openmw/mwinput/inputmanagerimp.hpp | 2 -- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index dc4c020d6c..f1f88b9aec 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -51,7 +51,6 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) - , mEnterPressed(false) { Ogre::RenderWindow* window = ogre.getWindow (); size_t windowHnd; @@ -240,10 +239,6 @@ namespace MWInput void InputManager::update(float dt, bool loading) { - // Pressing enter when a messagebox is prompting for "ok" will activate the ok button - if(mEnterPressed && MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox) - MWBase::Environment::get().getWindowManager()->enterPressed(); - // Tell OIS to handle all input events mKeyboard->capture(); mMouse->capture(); @@ -431,8 +426,13 @@ namespace MWInput bool InputManager::keyPressed( const OIS::KeyEvent &arg ) { - if(arg.key == OIS::KC_RETURN && MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console) - mEnterPressed = true; + if(arg.key == OIS::KC_RETURN + && MWBase::Environment::get().getWindowManager()->isGuiMode() + && MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox ) + { + // Pressing enter when a messagebox is prompting for "ok" will activate the ok button + MWBase::Environment::get().getWindowManager()->enterPressed(); + } mInputCtrl->keyPressed (arg); unsigned int text = arg.text; @@ -450,9 +450,6 @@ namespace MWInput bool InputManager::keyReleased( const OIS::KeyEvent &arg ) { - if(arg.key == OIS::KC_RETURN) - mEnterPressed = false; - mInputCtrl->keyReleased (arg); MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(arg.key)); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index c7ba7b7565..9deed1f285 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -151,8 +151,6 @@ namespace MWInput std::map mControlSwitch; - bool mEnterPressed; - private: void adjustMouseRegion(int width, int height);