diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index f777f838f..eb43acec7 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -36,6 +36,12 @@ namespace MWBase public: + class ResponseCallback + { + public: + virtual void addResponse(const std::string& title, const std::string& text) = 0; + }; + DialogueManager() {} virtual void clear() = 0; @@ -44,8 +50,7 @@ namespace MWBase virtual bool isInChoice() const = 0; - typedef std::pair Response; // title, text - virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response) = 0; + virtual bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback) = 0; virtual void addTopic (const std::string& topic) = 0; @@ -69,15 +74,15 @@ namespace MWBase virtual void say(const MWWorld::Ptr &actor, const std::string &topic) = 0; - virtual Response keywordSelected (const std::string& keyword) = 0; + virtual void keywordSelected (const std::string& keyword, ResponseCallback* callback) = 0; virtual void goodbyeSelected() = 0; - virtual Response questionAnswered (int answer) = 0; + virtual void questionAnswered (int answer, ResponseCallback* callback) = 0; virtual std::list getAvailableTopics() = 0; - virtual bool checkServiceRefused (Response& response) = 0; + virtual bool checkServiceRefused (ResponseCallback* callback) = 0; - virtual Response persuade (int type) = 0; + virtual void persuade (int type, ResponseCallback* callback) = 0; virtual int getTemporaryDispositionChange () const = 0; /// @note This change is temporary and gets discarded when dialogue ends. diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 3f89a1121..31326a23b 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -139,7 +139,7 @@ namespace MWDialogue } } - bool DialogueManager::startDialogue (const MWWorld::Ptr& actor, Response& response) + bool DialogueManager::startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback) { updateGlobals(); @@ -189,7 +189,7 @@ namespace MWDialogue parseText (info->mResponse); MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); - response = Response ("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); + callback->addResponse("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript, mActor); mLastTopic = it->mId; @@ -278,9 +278,8 @@ namespace MWDialogue } } - DialogueManager::Response DialogueManager::executeTopic (const std::string& topic) + void DialogueManager::executeTopic (const std::string& topic, ResponseCallback* callback) { - DialogueManager::Response response; Filter filter (mActor, mChoice, mTalkedTo); const MWWorld::Store &dialogues = @@ -312,7 +311,7 @@ namespace MWDialogue title = topic; MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); - response = Response(title, Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); + callback->addResponse(title, Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); if (dialogue.mType == ESM::Dialogue::Topic) { @@ -333,7 +332,6 @@ namespace MWDialogue mLastTopic = topic; } - return response; } const ESM::Dialogue *DialogueManager::searchDialogue(const std::string& id) @@ -388,18 +386,16 @@ namespace MWDialogue return keywordList; } - DialogueManager::Response DialogueManager::keywordSelected (const std::string& keyword) + void DialogueManager::keywordSelected (const std::string& keyword, ResponseCallback* callback) { - Response response; if(!mIsInChoice) { const ESM::Dialogue* dialogue = searchDialogue(keyword); if (dialogue && dialogue->mType == ESM::Dialogue::Topic) { - response = executeTopic (keyword); + executeTopic (keyword, callback); } } - return response; } bool DialogueManager::isInChoice() const @@ -424,10 +420,9 @@ namespace MWDialogue mTemporaryDispositionChange = 0; } - DialogueManager::Response DialogueManager::questionAnswered (int answer) + void DialogueManager::questionAnswered (int answer, ResponseCallback* callback) { mChoice = answer; - DialogueManager::Response response; const ESM::Dialogue* dialogue = searchDialogue(mLastTopic); if (dialogue) @@ -446,7 +441,7 @@ namespace MWDialogue mChoices.clear(); MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); - response = Response("", Interpreter::fixDefinesDialog(text, interpreterContext)); + callback->addResponse("", Interpreter::fixDefinesDialog(text, interpreterContext)); // Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group, // in which case it should not be added to the journal. @@ -472,7 +467,6 @@ namespace MWDialogue } updateActorKnownTopics(); - return response; } void DialogueManager::addChoice (const std::string& text, int choice) @@ -498,7 +492,7 @@ namespace MWDialogue mGoodbye = true; } - DialogueManager::Response DialogueManager::persuade(int type) + void DialogueManager::persuade(int type, ResponseCallback* callback) { bool success; float temp, perm; @@ -547,7 +541,7 @@ namespace MWDialogue text = "Bribe"; } - return executeTopic (text + (success ? " Success" : " Fail")); + executeTopic (text + (success ? " Success" : " Fail"), callback); } int DialogueManager::getTemporaryDispositionChange() const @@ -560,7 +554,7 @@ namespace MWDialogue mTemporaryDispositionChange += delta; } - bool DialogueManager::checkServiceRefused(Response& response) + bool DialogueManager::checkServiceRefused(ResponseCallback* callback) { Filter filter (mActor, mChoice, mTalkedTo); @@ -581,7 +575,7 @@ namespace MWDialogue MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); - response = Response(gmsts.find ("sServiceRefusal")->getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); + callback->addResponse(gmsts.find ("sServiceRefusal")->getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript, mActor); return true; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index e754ac118..5d7e9f9a2 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -57,7 +57,7 @@ namespace MWDialogue bool compile (const std::string& cmd, std::vector& code, const MWWorld::Ptr& actor); void executeScript (const std::string& script, const MWWorld::Ptr& actor); - Response executeTopic (const std::string& topic); + void executeTopic (const std::string& topic, ResponseCallback* callback); const ESM::Dialogue* searchDialogue(const std::string& id); @@ -69,7 +69,7 @@ namespace MWDialogue virtual bool isInChoice() const; - virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response); + virtual bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback); std::list getAvailableTopics(); @@ -93,16 +93,16 @@ namespace MWDialogue virtual void goodbye(); - virtual bool checkServiceRefused (Response& response); + virtual bool checkServiceRefused (ResponseCallback* callback); virtual void say(const MWWorld::Ptr &actor, const std::string &topic); //calbacks for the GUI - virtual Response keywordSelected (const std::string& keyword); + virtual void keywordSelected (const std::string& keyword, ResponseCallback* callback); virtual void goodbyeSelected(); - virtual Response questionAnswered (int answer); + virtual void questionAnswered (int answer, ResponseCallback* callback); - virtual Response persuade (int type); + virtual void persuade (int type, ResponseCallback* callback); virtual int getTemporaryDispositionChange () const; /// @note This change is temporary and gets discarded when dialogue ends. diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 39c73a23d..8a7ae85ea 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -30,8 +30,29 @@ namespace MWGui { - PersuasionDialog::PersuasionDialog() + class ResponseCallback : public MWBase::DialogueManager::ResponseCallback + { + public: + ResponseCallback(DialogueWindow* win, bool needMargin=true) + : mWindow(win) + , mNeedMargin(needMargin) + { + + } + + void addResponse(const std::string& title, const std::string& text) + { + mWindow->addResponse(title, text, mNeedMargin); + } + + private: + DialogueWindow* mWindow; + bool mNeedMargin; + }; + + PersuasionDialog::PersuasionDialog(ResponseCallback* callback) : WindowModal("openmw_persuasion_dialog.layout") + , mCallback(callback) { getWidget(mCancelButton, "CancelButton"); getWidget(mAdmireButton, "AdmireButton"); @@ -69,9 +90,7 @@ namespace MWGui else /*if (sender == mBribe1000Button)*/ type = MWBase::MechanicsManager::PT_Bribe1000; - MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->persuade(type); - - eventPersuadeMsg(response.first, response.second); + MWBase::Environment::get().getDialogueManager()->persuade(type, mCallback.get()); setVisible(false); } @@ -244,13 +263,14 @@ namespace MWGui : WindowBase("openmw_dialogue_window.layout") , mIsCompanion(false) , mGoodbye(false) - , mPersuasionDialog() + , mPersuasionDialog(new ResponseCallback(this)) + , mCallback(new ResponseCallback(this)) + , mGreetingCallback(new ResponseCallback(this, false)) { // Centre dialog center(); mPersuasionDialog.setVisible(false); - mPersuasionDialog.eventPersuadeMsg += MyGUI::newDelegate(this, &DialogueWindow::onPersuadeResult); //History view getWidget(mHistory, "History"); @@ -277,8 +297,6 @@ namespace MWGui DialogueWindow::~DialogueWindow() { - mPersuasionDialog.eventPersuadeMsg.clear(); - deleteLater(); for (Link* link : mLinks) delete link; @@ -356,12 +374,11 @@ namespace MWGui const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - MWBase::DialogueManager::Response response; if (topic == gmst.find("sPersuasion")->getString()) mPersuasionDialog.setVisible(true); else if (topic == gmst.find("sCompanionShare")->getString()) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr); - else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(response)) + else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(mCallback.get())) { if (topic == gmst.find("sBarter")->getString()) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr); @@ -378,19 +395,34 @@ namespace MWGui else if (topic == gmst.find("sRepair")->getString()) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr); } - else - addResponse(response.first, response.second); } } void DialogueWindow::setPtr(const MWWorld::Ptr& actor) { - MWBase::DialogueManager::Response response; - if (!MWBase::Environment::get().getDialogueManager()->startDialogue(actor, response)) + bool sameActor = (mPtr == actor); + if (!sameActor) + { + for (std::vector::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) + delete (*it); + mHistoryContents.clear(); + mKeywords.clear(); + mTopicsList->clear(); + for (std::vector::iterator it = mLinks.begin(); it != mLinks.end(); ++it) + mDeleteLater.push_back(*it); // Links are not deleted right away to prevent issues with event handlers + mLinks.clear(); + } + + mPtr = actor; + mGoodbye = false; + mTopicsList->setEnabled(true); + + if (!MWBase::Environment::get().getDialogueManager()->startDialogue(actor, mGreetingCallback.get())) { // No greetings found. The dialogue window should not be shown. // If this is a companion, we must show the companion window directly (used by BM_bear_be_unique). MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); + mPtr = MWWorld::Ptr(); if (isCompanion(actor)) MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion, actor); return; @@ -398,32 +430,11 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); - mGoodbye = false; - bool sameActor = (mPtr == actor); - mPtr = actor; - mTopicsList->setEnabled(true); setTitle(mPtr.getClass().getName(mPtr)); - mTopicsList->clear(); - - if (!sameActor) - { - for (std::vector::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) - delete (*it); - mHistoryContents.clear(); - - mKeywords.clear(); - updateTopicsPane(); - } - - for (std::vector::iterator it = mLinks.begin(); it != mLinks.end(); ++it) - mDeleteLater.push_back(*it); // Links are not deleted right away to prevent issues with event handlers - mLinks.clear(); - + updateTopicsPane(); updateDisposition(); restock(); - - addResponse(response.first, response.second, false); } void DialogueWindow::restock() @@ -608,14 +619,12 @@ namespace MWGui void DialogueWindow::onTopicActivated(const std::string &topicId) { - MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId); - addResponse(response.first, response.second); + MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId, mCallback.get()); } void DialogueWindow::onChoiceActivated(int id) { - MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->questionAnswered(id); - addResponse(response.first, response.second); + MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get()); } void DialogueWindow::onGoodbyeActivated() @@ -707,8 +716,4 @@ namespace MWGui && actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"); } - void DialogueWindow::onPersuadeResult(const std::string &title, const std::string &text) - { - addResponse(title, text); - } } diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 472996a6c..277032513 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -22,19 +22,20 @@ namespace MWGui namespace MWGui { + class ResponseCallback; + class PersuasionDialog : public WindowModal { public: - PersuasionDialog(); - - typedef MyGUI::delegates::CMultiDelegate2 EventHandle_Result; - EventHandle_Result eventPersuadeMsg; + PersuasionDialog(ResponseCallback* callback); virtual void onOpen(); virtual MyGUI::Widget* getDefaultKeyFocus(); private: + std::unique_ptr mCallback; + MyGUI::Button* mCancelButton; MyGUI::Button* mAdmireButton; MyGUI::Button* mIntimidateButton; @@ -136,7 +137,6 @@ namespace MWGui bool isCompanion(const MWWorld::Ptr& actor); bool isCompanion(); - void onPersuadeResult(const std::string& title, const std::string& text); void onSelectListItem(const std::string& topic, int id); void onByeClicked(MyGUI::Widget* _sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); @@ -180,6 +180,9 @@ namespace MWGui PersuasionDialog mPersuasionDialog; MyGUI::IntSize mCurrentWindowSize; + + std::unique_ptr mCallback; + std::unique_ptr mGreetingCallback; }; } #endif diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 376a28aa7..7c89c4979 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -126,6 +126,7 @@ namespace MWGui if (mInterMessageBoxe != NULL) { std::cerr << "Warning: replacing an interactive message box that was not answered yet" << std::endl; + mInterMessageBoxe->setVisible(false); delete mInterMessageBoxe; mInterMessageBoxe = NULL; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6c4cc802b..4fbcdc4d5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -252,6 +252,7 @@ namespace MWRender sceneRoot->setName("Scene Root"); mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); + mSky->setCamera(mViewer->getCamera()); mSky->setRainIntensityUniform(mWater->getRainIntensityUniform()); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 52b659984..c4dffb7a4 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -416,9 +416,9 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem setHeight(mTop); - updateWaterMaterial(); - mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); + + updateWaterMaterial(); } osg::Uniform *Water::getRainIntensityUniform() @@ -517,6 +517,7 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R osg::ref_ptr fragmentShader (shaderMgr.getShader("water_fragment.glsl", defineMap, osg::Shader::FRAGMENT)); osg::ref_ptr normalMap (new osg::Texture2D(readPngImage(mResourcePath + "/shaders/water_nm.png"))); + if (normalMap->getImage()) normalMap->getImage()->flipVertical(); normalMap->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); @@ -531,6 +532,7 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R shaderStateset->setTextureAttributeAndModes(0, normalMap, osg::StateAttribute::ON); shaderStateset->setTextureAttributeAndModes(1, reflection->getReflectionTexture(), osg::StateAttribute::ON); + if (refraction) { shaderStateset->setTextureAttributeAndModes(2, refraction->getRefractionTexture(), osg::StateAttribute::ON); @@ -552,13 +554,13 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R shaderStateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + shaderStateset->addUniform(mRainIntensityUniform.get()); + osg::ref_ptr program (new osg::Program); program->addShader(vertexShader); program->addShader(fragmentShader); shaderStateset->setAttributeAndModes(program, osg::StateAttribute::ON); - shaderStateset->addUniform(mRainIntensityUniform); - node->setStateSet(shaderStateset); node->setUpdateCallback(NULL); } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 851a6a29c..e999097db 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -453,5 +453,6 @@ op 0x2000302: Fixme op 0x2000303: Fixme, explicit op 0x2000304: Show op 0x2000305: Show, explicit +op 0x2000306: OnActivate, explicit -opcodes 0x2000304-0x3ffffff unused +opcodes 0x2000307-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 6622fb4cf..148c39b19 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -157,16 +157,14 @@ namespace MWScript } }; + template class OpOnActivate : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - - MWWorld::Ptr ptr = context.getReference(); + MWWorld::Ptr ptr = R()(runtime); runtime.push (ptr.getRefData().onActivate()); } @@ -1350,7 +1348,8 @@ namespace MWScript void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox); - interpreter.installSegment5 (Compiler::Misc::opcodeOnActivate, new OpOnActivate); + interpreter.installSegment5 (Compiler::Misc::opcodeOnActivate, new OpOnActivate); + interpreter.installSegment5 (Compiler::Misc::opcodeOnActivateExplicit, new OpOnActivate); interpreter.installSegment5 (Compiler::Misc::opcodeActivate, new OpActivate); interpreter.installSegment5 (Compiler::Misc::opcodeActivateExplicit, new OpActivate); interpreter.installSegment3 (Compiler::Misc::opcodeLock, new OpLock); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index eb3e1e4ee..cd5bf7ef7 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -240,7 +240,7 @@ namespace Compiler void registerExtensions (Extensions& extensions) { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); - extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate); + extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate, opcodeOnActivateExplicit); extensions.registerInstruction ("activate", "x", opcodeActivate, opcodeActivateExplicit); extensions.registerInstruction ("lock", "/l", opcodeLock, opcodeLockExplicit); extensions.registerInstruction ("unlock", "", opcodeUnlock, opcodeUnlockExplicit); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index b2333032b..6a6552467 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -200,6 +200,7 @@ namespace Compiler { const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; + const int opcodeOnActivateExplicit = 0x2000306; const int opcodeActivate = 0x2000075; const int opcodeActivateExplicit = 0x2000244; const int opcodeLock = 0x20004;