From 592fa84e2d2f008de75019a19dabacd6042a6e7c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 16:07:03 +0200 Subject: [PATCH] added Enable, Disable, GetDisabled --- apps/mwinterpreter/context.cpp | 9 +++ apps/mwinterpreter/context.hpp | 6 ++ apps/openmw/mwrender/cell.hpp | 8 ++ apps/openmw/mwrender/cellimp.cpp | 4 +- apps/openmw/mwrender/cellimp.hpp | 2 +- apps/openmw/mwrender/interior.cpp | 17 +++- apps/openmw/mwrender/interior.hpp | 10 ++- apps/openmw/mwscript/interpretercontext.cpp | 30 +++++++ apps/openmw/mwscript/interpretercontext.hpp | 6 ++ apps/openmw/mwworld/refdata.hpp | 18 ++++- apps/openmw/mwworld/world.cpp | 89 +++++++++++++++++++++ apps/openmw/mwworld/world.hpp | 9 +++ components/compiler/exprparser.cpp | 12 ++- components/compiler/generator.cpp | 31 +++++++ components/compiler/generator.hpp | 6 ++ components/compiler/lineparser.cpp | 14 +++- components/compiler/scanner.cpp | 1 + components/compiler/scanner.hpp | 3 +- components/interpreter/context.hpp | 8 +- components/interpreter/docs/vmformat.txt | 5 +- components/interpreter/installopcodes.cpp | 3 + components/interpreter/miscopcodes.hpp | 31 +++++++ 22 files changed, 310 insertions(+), 12 deletions(-) diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index ecf4bd829..e09626198 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -120,6 +120,15 @@ namespace SAInterpreter return 0; } + bool Context::isDisabled() const + { + return false; + } + + void Context::enable() {} + + void Context::disable() {} + void Context::report() { std::size_t i = 0; diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index 48ba40ca3..d3e61df78 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -62,6 +62,12 @@ namespace SAInterpreter virtual float getSecondsPassed() const; + virtual bool isDisabled() const; + + virtual void enable(); + + virtual void disable(); + void report(); ///< Write state to std::cout }; diff --git a/apps/openmw/mwrender/cell.hpp b/apps/openmw/mwrender/cell.hpp index 756ec1cda..9e214209a 100644 --- a/apps/openmw/mwrender/cell.hpp +++ b/apps/openmw/mwrender/cell.hpp @@ -1,6 +1,8 @@ #ifndef GAME_RENDER_CELL_H #define GAME_RENDER_CELL_H +#include + namespace MWRender { class CellRender @@ -15,6 +17,12 @@ namespace MWRender /// Remove the cell from rendering, but don't remove it from /// memory. virtual void hide() = 0; + + /// Make the reference with the given handle visible. + virtual void enable (const std::string& handle) = 0; + + /// Make the reference with the given handle invisible. + virtual void disable (const std::string& handle) = 0; }; } diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 7a8de957e..86bddb3a9 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -13,7 +13,7 @@ void insertObj(CellRenderImp& cellRender, T& liveRef) { cellRender.insertBegin (liveRef.ref); cellRender.insertMesh ("meshes\\" + model); - liveRef.mData.setHandle (cellRender.insertEnd()); + liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); } } @@ -36,7 +36,7 @@ void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRefdata.radius); cellRender.insertLight(r, g, b, radius); - liveRef.mData.setHandle (cellRender.insertEnd()); + liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); } } diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp index 88406bb4f..f93bbbbf3 100644 --- a/apps/openmw/mwrender/cellimp.hpp +++ b/apps/openmw/mwrender/cellimp.hpp @@ -33,7 +33,7 @@ namespace MWRender virtual void insertLight(float r, float g, float b, float radius) = 0; /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd() = 0; + virtual std::string insertEnd (bool Enable) = 0; void insertCell(ESMS::CellStore &cell); diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index 5cf38a5a1..a2f55880b 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -103,12 +103,15 @@ void InteriorCellRender::insertLight(float r, float g, float b, float radius) // finish inserting a new reference and return a handle to it. -std::string InteriorCellRender::insertEnd() +std::string InteriorCellRender::insertEnd (bool enable) { assert (insert); std::string handle = insert->getName(); + if (!enable) + insert->setVisible (false); + insert = 0; return handle; @@ -219,6 +222,18 @@ void InteriorCellRender::toggleLight() setAmbientMode(); } +void InteriorCellRender::enable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (true); +} + +void InteriorCellRender::disable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (false); +} + // Magic function from the internets. Might need this later. /* void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode ) diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 5eda4eccd..cd6834999 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -66,7 +66,7 @@ namespace MWRender virtual void insertLight(float r, float g, float b, float radius); /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd(); + virtual std::string insertEnd (bool Enable); /// configure lighting according to cell void configureAmbient(); @@ -88,13 +88,19 @@ namespace MWRender /// Remove the cell from rendering, but don't remove it from /// memory. - void hide(); + virtual void hide(); /// Destroy all rendering objects connected with this cell. void destroy(); // comment by Zini: shouldn't this go into the destructor? /// Switch through lighting modes. void toggleLight(); + + /// Make the reference with the given handle visible. + virtual void enable (const std::string& handle); + + /// Make the reference with the given handle invisible. + virtual void disable (const std::string& handle); }; } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 0b1610f4f..7e57e5aea 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -166,6 +166,36 @@ namespace MWScript return mEnvironment.mFrameDuration; } + bool InterpreterContext::isDisabled() const + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + return !mReference.getRefData().isEnabled(); + } + + void InterpreterContext::enable() + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + std::pair ref + (mReference, mEnvironment.mWorld->find (mReference)); + + mEnvironment.mWorld->enable (ref); + } + + void InterpreterContext::disable() + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + std::pair ref + (mReference, mEnvironment.mWorld->find (mReference)); + + mEnvironment.mWorld->disable (ref); + } + MWGui::GuiManager& InterpreterContext::getGuiManager() { return *mEnvironment.mGuiManager; diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 947756262..9d426aafc 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -73,6 +73,12 @@ namespace MWScript virtual float getSecondsPassed() const; + virtual bool isDisabled() const; + + virtual void enable(); + + virtual void disable(); + MWWorld::World& getWorld(); MWSound::SoundManager& getSoundManager(); diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index a7e137b9d..58c169c0e 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -20,10 +20,11 @@ namespace MWWorld // object in the refdata of refs without a script, // we can make this a pointer later. bool mHasLocals; + bool mEnabled; public: - RefData() : mHasLocals (false) {} + RefData() : mHasLocals (false), mEnabled (true) {} std::string getHandle() { @@ -48,6 +49,21 @@ namespace MWWorld { return mLocals; } + + bool isEnabled() const + { + return mEnabled; + } + + void enable() + { + mEnabled = true; + } + + void disable() + { + mEnabled = true; + } }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 01f03b641..8fb635ef3 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -9,6 +9,8 @@ #include "apps/openmw/mwrender/sky.hpp" #include "apps/openmw/mwrender/interior.hpp" +#include "ptr.hpp" + namespace { template @@ -31,6 +33,20 @@ namespace } } } + + template + bool hasReference (ESMS::CellRefList& cellRefList, const MWWorld::Ptr& ptr) + { + for (typename ESMS::CellRefList::List::iterator iter ( + cellRefList.list.begin()); + iter!=cellRefList.list.end(); ++iter) + { + if (&iter->mData==&ptr.getRefData()) + return true; + } + + return false; + } } namespace MWWorld @@ -121,6 +137,24 @@ namespace MWWorld return Ptr(); } + MWRender::CellRender *World::searchRender (CellStore *store) + { + CellRenderCollection::iterator iter = mActiveCells.find (store); + + if (iter!=mActiveCells.end()) + { + return iter->second; + } + else + { + iter = mBufferedCells.find (store); + if (iter!=mBufferedCells.end()) + return iter->second; + } + + return 0; + } + World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, const std::string& startCell, bool newGame) : mSkyManager (0), mScene (renderer), mPlayerPos (0) @@ -245,4 +279,59 @@ namespace MWWorld throw std::runtime_error ("unknown ID: " + name); } + + void World::enable (std::pair& reference) + { + if (!reference.first.getRefData().isEnabled()) + { + reference.first.getRefData().enable(); + + if (MWRender::CellRender *render = searchRender (reference.second)) + { + render->enable (reference.first.getRefData().getHandle()); + } + } + } + + void World::disable (std::pair& reference) + { + if (!reference.first.getRefData().isEnabled()) + { + reference.first.getRefData().enable(); + + if (MWRender::CellRender *render = searchRender (reference.second)) + { + render->disable (reference.first.getRefData().getHandle()); + } + } + } + + World::CellStore *World::find (const Ptr& ptr) + { + for (CellRenderCollection::iterator iter (mActiveCells.begin()); iter!=mActiveCells.end(); + ++iter) + { + if ( + hasReference (iter->first->activators, ptr) || + hasReference (iter->first->potions, ptr) || + hasReference (iter->first->appas, ptr) || + hasReference (iter->first->armors, ptr) || + hasReference (iter->first->books, ptr) || + hasReference (iter->first->clothes, ptr) || + hasReference (iter->first->containers, ptr) || + hasReference (iter->first->creatures, ptr) || + hasReference (iter->first->doors, ptr) || + hasReference (iter->first->ingreds, ptr) || + hasReference (iter->first->lights, ptr) || + hasReference (iter->first->lockpicks, ptr) || + hasReference (iter->first->miscItems, ptr) || + hasReference (iter->first->npcs, ptr) || + hasReference (iter->first->probes, ptr) || + hasReference (iter->first->repairs, ptr) || + hasReference (iter->first->weapons, ptr)) + return iter->first; + } + + throw std::runtime_error ("failed to locate reference in active cell"); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 74a1ee159..0c299b9f9 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -61,6 +61,8 @@ namespace MWWorld Ptr getPtr (const std::string& name, CellStore& cellStore); + MWRender::CellRender *searchRender (CellStore *store); + public: World (Render::OgreRenderer& renderer, const boost::filesystem::path& master, @@ -83,6 +85,13 @@ namespace MWWorld std::pair getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name. /// \param activeOnly do non search inactive cells. + + void enable (std::pair& reference); + + void disable (std::pair& reference); + + CellStore *find (const Ptr& ptr); + ///< Only active cells are searched. }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index fdf8feedf..8fae00adf 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -346,7 +346,17 @@ namespace Compiler mNextOperand = false; return true; - } + } + else if (keyword==Scanner::K_getdisabled) + { + mTokenLoc = loc; + + Generator::getDisabled (mCode); + mOperands.push_back ('l'); + + mNextOperand = false; + return true; + } else { // check for custom extensions diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 27448e37d..4b6014e55 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -284,6 +284,22 @@ namespace { code.push_back (Compiler::Generator::segment5 (50)); } + + void opEnable (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (51)); + } + + void opDisable (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (52)); + } + + void opGetDisabled (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (53)); + } + } namespace Compiler @@ -685,6 +701,21 @@ namespace Compiler { opGetSecondsPassed (code); } + + void getDisabled (CodeContainer& code) + { + opGetDisabled (code); + } + + void enable (CodeContainer& code) + { + opEnable (code); + } + + void disable (CodeContainer& code) + { + opDisable (code); + } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 3df789f61..4a043ecdb 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -110,6 +110,12 @@ namespace Compiler void getDistance (CodeContainer& code); void getSecondsPassed (CodeContainer& code); + + void getDisabled (CodeContainer& code); + + void enable (CodeContainer& code); + + void disable (CodeContainer& code); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 5a254a804..b1acbec45 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -162,7 +162,19 @@ namespace Compiler mExprParser.parseArguments ("c", scanner, mCode, true); Generator::stopScript (mCode); mState = EndState; - return true; + return true; + + case Scanner::K_enable: + + Generator::enable (mCode); + mState = EndState; + return true; + + case Scanner::K_disable: + + Generator::disable (mCode); + mState = EndState; + return true; } // check for custom extensions diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 8899d561c..6f43f9fde 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -247,6 +247,7 @@ namespace Compiler "startscript", "stopscript", "scriptrunning", "getdistance", "getsecondspassed", + "enable", "disable", "getdisabled", 0 }; diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 9e6e6a7d1..99fca5229 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -53,7 +53,8 @@ namespace Compiler K_random, K_startscript, K_stopscript, K_scriptrunning, K_getdistance, - K_getsecondspassed + K_getsecondspassed, + K_enable, K_disable, K_getdisabled }; enum special diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 34b78d580..30eb56167 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -55,7 +55,13 @@ namespace Interpreter virtual float getDistance (const std::string& name) const = 0; - virtual float getSecondsPassed() const = 0; + virtual float getSecondsPassed() const = 0; + + virtual bool isDisabled() const = 0; + + virtual void enable() = 0; + + virtual void disable() = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 12225e865..2be1fcf0a 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -109,6 +109,9 @@ op 47: start script stack[0] and pop op 48: stop script stack[0] and pop op 49: replace stack[0] with distance between implicit reference and a reference of ID stack[0] op 50: push frame duration (float) -opcodes 51-33554431 unused +op 51: enable implicit reference +op 52: disable implicit reference +op 53: push 1, if implicit reference is disabled, 0 else +opcodes 54-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 302812ad6..e991bf937 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -89,6 +89,9 @@ namespace Interpreter interpreter.installSegment5 (38, new OpMenuMode); interpreter.installSegment5 (45, new OpRandom); interpreter.installSegment5 (50, new OpGetSecondsPassed); + interpreter.installSegment5 (51, new OpEnable); + interpreter.installSegment5 (52, new OpDisable); + interpreter.installSegment5 (53, new OpGetDisabled); // script control interpreter.installSegment5 (46, new OpScriptRunning); diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 17acb72db..ba090a488 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -130,6 +130,37 @@ namespace Interpreter runtime.push (*reinterpret_cast (&duration)); } }; + + class OpEnable : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.getContext().enable(); + } + }; + + class OpDisable : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.getContext().disable(); + } + }; + + class OpGetDisabled : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.push (runtime.getContext().isDisabled()); + } + }; + } #endif