From 592fa84e2d2f008de75019a19dabacd6042a6e7c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 16:07:03 +0200 Subject: [PATCH 1/5] 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 From 5a1dd4feddd4227c88f11d9fdee67ad136141317 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 18:21:16 +0200 Subject: [PATCH 2/5] fixed fileparser bug (empty line before the initial begin statement were not handled correctly --- components/compiler/fileparser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 6e3e1de69..6e26f48d6 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -75,6 +75,12 @@ namespace Compiler { if (code==Scanner::S_newline) { + if (mState==BeginState) + { + // ignore empty lines + return true; + } + if (mState==BeginCompleteState) { // parse the script body From ce74ee86189e1fac90fcc7e6675e2e37c1b27f5e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 18:27:31 +0200 Subject: [PATCH 3/5] removed an outdated log message --- components/esm_store/cell_store.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index 444c3e1af..941dba6fe 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -175,8 +175,6 @@ namespace ESMS std::cout << "WARNING: Ignoring reference '" << ref.refID << "' of unhandled type\n"; } } - - std::cout << "Statics in cell: " << statics.list.size() << std::endl; } }; From d4ac3b506e4eef1a95921e3ad5f3410954ee73e2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 19:32:17 +0200 Subject: [PATCH 4/5] implemented enable, disable and getdisabled with explicit references --- apps/mwinterpreter/context.cpp | 6 +- apps/mwinterpreter/context.hpp | 6 +- apps/openmw/mwscript/interpretercontext.cpp | 62 ++++++++++++++------- apps/openmw/mwscript/interpretercontext.hpp | 19 ++++--- components/compiler/exprparser.cpp | 52 ++++++++++++++++- components/compiler/exprparser.hpp | 2 + components/compiler/generator.cpp | 53 ++++++++++++++++-- components/compiler/generator.hpp | 6 +- components/compiler/lineparser.cpp | 44 +++++++++++---- components/compiler/lineparser.hpp | 4 +- components/interpreter/context.hpp | 6 +- components/interpreter/docs/vmformat.txt | 5 +- components/interpreter/installopcodes.cpp | 5 +- components/interpreter/miscopcodes.hpp | 42 ++++++++++++++ 14 files changed, 250 insertions(+), 62 deletions(-) diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index e09626198..cbe379f0f 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -120,14 +120,14 @@ namespace SAInterpreter return 0; } - bool Context::isDisabled() const + bool Context::isDisabled (const std::string& id) const { return false; } - void Context::enable() {} + void Context::enable (const std::string& id) {} - void Context::disable() {} + void Context::disable (const std::string& id) {} void Context::report() { diff --git a/apps/mwinterpreter/context.hpp b/apps/mwinterpreter/context.hpp index d3e61df78..1ee3129f7 100644 --- a/apps/mwinterpreter/context.hpp +++ b/apps/mwinterpreter/context.hpp @@ -62,11 +62,11 @@ namespace SAInterpreter virtual float getSecondsPassed() const; - virtual bool isDisabled() const; + virtual bool isDisabled (const std::string& id = "") const; - virtual void enable(); + virtual void enable (const std::string& id = ""); - virtual void disable(); + virtual void disable (const std::string& id = ""); void report(); ///< Write state to std::cout diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 7e57e5aea..064ac583d 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -16,6 +16,42 @@ namespace MWScript { + InterpreterContext::PtrWithCell InterpreterContext::getReference ( + const std::string& id, bool activeOnly) + { + PtrWithCell ref; + + if (!id.empty()) + { + return mEnvironment.mWorld->getPtr (id, activeOnly); + } + else + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + return PtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + } + } + + InterpreterContext::CPtrWithCell InterpreterContext::getReference ( + const std::string& id, bool activeOnly) const + { + CPtrWithCell ref; + + if (!id.empty()) + { + return mEnvironment.mWorld->getPtr (id, activeOnly); + } + else + { + if (mReference.isEmpty()) + throw std::runtime_error ("no implicit reference"); + + return CPtrWithCell (mReference, mEnvironment.mWorld->find (mReference)); + } + } + InterpreterContext::InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference) : mEnvironment (environment), mLocals (locals), mReference (reference) @@ -166,33 +202,21 @@ namespace MWScript return mEnvironment.mFrameDuration; } - bool InterpreterContext::isDisabled() const + bool InterpreterContext::isDisabled (const std::string& id) const { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - return !mReference.getRefData().isEnabled(); + CPtrWithCell ref = getReference (id, false); + return !ref.first.getRefData().isEnabled(); } - void InterpreterContext::enable() + void InterpreterContext::enable (const std::string& id) { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - std::pair ref - (mReference, mEnvironment.mWorld->find (mReference)); - + PtrWithCell ref = getReference (id, false); mEnvironment.mWorld->enable (ref); } - void InterpreterContext::disable() + void InterpreterContext::disable (const std::string& id) { - if (mReference.isEmpty()) - throw std::runtime_error ("no implicit reference"); - - std::pair ref - (mReference, mEnvironment.mWorld->find (mReference)); - + PtrWithCell ref = getReference (id, false); mEnvironment.mWorld->disable (ref); } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 9d426aafc..bdc871a01 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -5,11 +5,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/environment.hpp" - -namespace MWWorld -{ - class World; -} +#include "../mwworld/world.hpp" namespace MWSound { @@ -26,6 +22,13 @@ namespace MWScript Locals *mLocals; MWWorld::Ptr mReference; + typedef std::pair PtrWithCell; + typedef std::pair CPtrWithCell; + + PtrWithCell getReference (const std::string& id, bool activeOnly); + + CPtrWithCell getReference (const std::string& id, bool activeOnly) const; + public: InterpreterContext (MWWorld::Environment& environment, @@ -73,11 +76,11 @@ namespace MWScript virtual float getSecondsPassed() const; - virtual bool isDisabled() const; + virtual bool isDisabled (const std::string& id = "") const; - virtual void enable(); + virtual void enable (const std::string& id = ""); - virtual void disable(); + virtual void disable (const std::string& id = ""); MWWorld::World& getWorld(); diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 8fae00adf..9ebd0c89a 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -203,6 +203,9 @@ namespace Compiler bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseInt (value, loc, scanner); + mFirst = false; if (mNextOperand) @@ -221,6 +224,9 @@ namespace Compiler bool ExprParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseFloat (value, loc, scanner); + mFirst = false; if (mNextOperand) @@ -240,6 +246,9 @@ namespace Compiler bool ExprParser::parseName (const std::string& name, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + return Parser::parseName (name, loc, scanner); + mFirst = false; if (mNextOperand) @@ -255,7 +264,6 @@ namespace Compiler mOperands.push_back (type=='f' ? 'f' : 'l'); return true; } - type = getContext().getGlobalType (name2); @@ -266,6 +274,12 @@ namespace Compiler mOperands.push_back (type=='f' ? 'f' : 'l'); return true; } + + if (mOperands.empty() && mOperators.empty() && mExplicit.empty()) + { + mExplicit = name; + return true; + } } else { @@ -280,7 +294,28 @@ namespace Compiler bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) { mFirst = false; + + if (!mExplicit.empty()) + { + if (mRefOp && mNextOperand) + { + if (keyword==Scanner::K_getdisabled) + { + mTokenLoc = loc; + Generator::getDisabled (mCode, mLiterals, mExplicit); + mOperands.push_back ('l'); + mExplicit.clear(); + mRefOp = false; + + mNextOperand = false; + return true; + } + } + + return Parser::parseKeyword (keyword, loc, scanner); + } + if (mNextOperand) { if (keyword==Scanner::K_getsquareroot) @@ -351,7 +386,7 @@ namespace Compiler { mTokenLoc = loc; - Generator::getDisabled (mCode); + Generator::getDisabled (mCode, mLiterals, ""); mOperands.push_back ('l'); mNextOperand = false; @@ -391,6 +426,17 @@ namespace Compiler bool ExprParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) { + if (!mExplicit.empty()) + { + if (!mRefOp && code==Scanner::S_ref) + { + mRefOp = true; + return true; + } + + return Parser::parseSpecial (code, loc, scanner); + } + if (code==Scanner::S_comma) { mTokenLoc = loc; @@ -498,6 +544,8 @@ namespace Compiler mNextOperand = true; mCode.clear(); mFirst = true; + mExplicit.clear(); + mRefOp = false; } char ExprParser::append (std::vector& code) diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index b8f295b5c..0dd8c871a 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -24,6 +24,8 @@ namespace Compiler std::vector mCode; bool mFirst; bool mArgument; + std::string mExplicit; + bool mRefOp; int getPriority (char op) const; diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 4b6014e55..ece1bebaf 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -300,6 +300,20 @@ namespace code.push_back (Compiler::Generator::segment5 (53)); } + void opEnableExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (54)); + } + + void opDisableExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (55)); + } + + void opGetDisabledExplicit (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (56)); + } } namespace Compiler @@ -702,19 +716,46 @@ namespace Compiler opGetSecondsPassed (code); } - void getDisabled (CodeContainer& code) + void getDisabled (CodeContainer& code, Literals& literals, const std::string id) { - opGetDisabled (code); + if (id.empty()) + { + opGetDisabled (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opGetDisabledExplicit (code); + } } - void enable (CodeContainer& code) + void enable (CodeContainer& code, Literals& literals, const std::string id) { - opEnable (code); + if (id.empty()) + { + opEnable (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opEnableExplicit (code); + } } - void disable (CodeContainer& code) + void disable (CodeContainer& code, Literals& literals, const std::string id) { - opDisable (code); + if (id.empty()) + { + opDisable (code); + } + else + { + int index = literals.addString (id); + opPushInt (code, index); + opDisableExplicit (code); + } } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 4a043ecdb..9623b7226 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -111,11 +111,11 @@ namespace Compiler void getSecondsPassed (CodeContainer& code); - void getDisabled (CodeContainer& code); + void getDisabled (CodeContainer& code, Literals& literals, const std::string id); - void enable (CodeContainer& code); + void enable (CodeContainer& code, Literals& literals, const std::string id); - void disable (CodeContainer& code); + void disable (CodeContainer& code, Literals& literals, const std::string id); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index b1acbec45..0b5f563d0 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -129,11 +129,36 @@ namespace Compiler return false; } + if (mState==BeginState) + { + mState = PotentialExplicitState; + mExplicit = toLower (name); + return true; + } + return Parser::parseName (name, loc, scanner); } bool LineParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) { + if (mState==BeginState || mState==ExplicitState) + { + switch (keyword) + { + case Scanner::K_enable: + + Generator::enable (mCode, mLiterals, mExplicit); + mState = EndState; + return true; + + case Scanner::K_disable: + + Generator::disable (mCode, mLiterals, mExplicit); + mState = EndState; + return true; + } + } + if (mState==BeginState) { switch (keyword) @@ -163,18 +188,6 @@ namespace Compiler Generator::stopScript (mCode); mState = EndState; 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 @@ -233,6 +246,12 @@ namespace Compiler mState = MessageCommaState; return true; } + + if (code==Scanner::S_ref && mState==PotentialExplicitState) + { + mState = ExplicitState; + return true; + } return Parser::parseSpecial (code, loc, scanner); } @@ -241,6 +260,7 @@ namespace Compiler { mState = BeginState; mName.clear(); + mExplicit.clear(); } } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 63efb60a4..717d73451 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -23,7 +23,8 @@ namespace Compiler ShortState, LongState, FloatState, SetState, SetLocalVarState, SetGlobalVarState, MessageState, MessageCommaState, - EndState + EndState, + PotentialExplicitState, ExplicitState }; Locals& mLocals; @@ -31,6 +32,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + std::string mExplicit; char mType; ExprParser mExprParser; diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 30eb56167..aae0051bd 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -57,11 +57,11 @@ namespace Interpreter virtual float getSecondsPassed() const = 0; - virtual bool isDisabled() const = 0; + virtual bool isDisabled (const std::string& id = "") const = 0; - virtual void enable() = 0; + virtual void enable (const std::string& id = "") = 0; - virtual void disable() = 0; + virtual void disable (const std::string& id = "") = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 2be1fcf0a..dcf204473 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -112,6 +112,9 @@ op 50: push frame duration (float) 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 +op 54: explicit reference = stack[0]; pop; enable explicit reference +op 55: explicit reference = stack[0]; pop; disable explicit reference +op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else +opcodes 57-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index e991bf937..522f77b95 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -92,7 +92,10 @@ namespace Interpreter interpreter.installSegment5 (51, new OpEnable); interpreter.installSegment5 (52, new OpDisable); interpreter.installSegment5 (53, new OpGetDisabled); - + interpreter.installSegment5 (54, new OpEnableExplicit); + interpreter.installSegment5 (55, new OpDisableExplicit); + interpreter.installSegment5 (56, new OpGetDisabledExplicit); + // script control interpreter.installSegment5 (46, new OpScriptRunning); interpreter.installSegment5 (47, new OpStartScript); diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index ba090a488..852d2d154 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -161,6 +161,48 @@ namespace Interpreter } }; + class OpEnableExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.getContext().enable (id); + } + }; + + class OpDisableExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.getContext().disable (id); + } + }; + + class OpGetDisabledExplicit : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + int index = runtime[0]; + runtime.pop(); + std::string id = runtime.getStringLiteral (index); + + runtime.push (runtime.getContext().isDisabled (id)); + } + }; + } #endif From c37b007be076c4c2f86a60a1c4f7bf080374f7ed Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jul 2010 20:35:34 +0200 Subject: [PATCH 5/5] added verification for explicit references (check if the given ID exists) --- apps/mwcompiler/context.cpp | 5 +++++ apps/mwcompiler/context.hpp | 5 ++++- apps/openmw/mwscript/compilercontext.cpp | 25 ++++++++++++++++++++++++ apps/openmw/mwscript/compilercontext.hpp | 3 +++ components/compiler/context.hpp | 5 ++++- components/compiler/exprparser.cpp | 2 +- components/compiler/lineparser.cpp | 2 +- 7 files changed, 43 insertions(+), 4 deletions(-) diff --git a/apps/mwcompiler/context.cpp b/apps/mwcompiler/context.cpp index 895e2c62a..ff84494af 100644 --- a/apps/mwcompiler/context.cpp +++ b/apps/mwcompiler/context.cpp @@ -12,5 +12,10 @@ namespace SACompiler { return ' '; } + + bool Context::isId (const std::string& name) const + { + return false; + } } diff --git a/apps/mwcompiler/context.hpp b/apps/mwcompiler/context.hpp index be06bbca8..ebf84166c 100644 --- a/apps/mwcompiler/context.hpp +++ b/apps/mwcompiler/context.hpp @@ -13,7 +13,10 @@ namespace SACompiler ///< Is the compiler allowed to declare local variables? virtual char getGlobalType (const std::string& name) const; - ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual bool isId (const std::string& name) const; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 1e5cdaf4a..5e4882f25 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -31,5 +31,30 @@ namespace MWScript return ' '; } + + bool CompilerContext::isId (const std::string& name) const + { + return + mEnvironment.mWorld->getStore().activators.find (name) || + mEnvironment.mWorld->getStore().potions.find (name) || + mEnvironment.mWorld->getStore().appas.find (name) || + mEnvironment.mWorld->getStore().armors.find (name) || + mEnvironment.mWorld->getStore().books.find (name) || + mEnvironment.mWorld->getStore().clothes.find (name) || + mEnvironment.mWorld->getStore().containers.find (name) || + mEnvironment.mWorld->getStore().creatures.find (name) || + mEnvironment.mWorld->getStore().doors.find (name) || + mEnvironment.mWorld->getStore().ingreds.find (name) || + mEnvironment.mWorld->getStore().creatureLists.find (name) || + mEnvironment.mWorld->getStore().itemLists.find (name) || + mEnvironment.mWorld->getStore().lights.find (name) || + mEnvironment.mWorld->getStore().lockpicks.find (name) || + mEnvironment.mWorld->getStore().miscItems.find (name) || + mEnvironment.mWorld->getStore().npcs.find (name) || + mEnvironment.mWorld->getStore().probes.find (name) || + mEnvironment.mWorld->getStore().repairs.find (name) || + mEnvironment.mWorld->getStore().statics.find (name) || + mEnvironment.mWorld->getStore().weapons.find (name); + } } diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 41d5f314e..7a3411bba 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -35,6 +35,9 @@ namespace MWScript /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; + + virtual bool isId (const std::string& name) const; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index b34297cce..929119cf4 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -31,7 +31,10 @@ namespace Compiler } virtual char getGlobalType (const std::string& name) const = 0; - ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual bool isId (const std::string& name) const = 0; + ///< Does \a name match an ID, that can be referenced? }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 9ebd0c89a..e11dde521 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -275,7 +275,7 @@ namespace Compiler return true; } - if (mOperands.empty() && mOperators.empty() && mExplicit.empty()) + if (mExplicit.empty() && getContext().isId (name)) { mExplicit = name; return true; diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 0b5f563d0..d46d5f093 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -129,7 +129,7 @@ namespace Compiler return false; } - if (mState==BeginState) + if (mState==BeginState && getContext().isId (name)) { mState = PotentialExplicitState; mExplicit = toLower (name);