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) }; }