diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e17a2cb25..b3bd51e20 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -36,6 +36,7 @@ add_openmw_dir (mwscript locals scriptmanager compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions + animationextensions ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 06339cdd4..2a198b5f4 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -225,6 +225,15 @@ void RenderingManager::toggleLight() setAmbientMode(); } +void RenderingManager::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, + int mode, int number) +{ +std::cout<<"play animation " << groupName << ", " << mode << ", " << number << std::endl; +} +void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr) +{ +std::cout<<"skip animation"< &mCell); + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number = 1); + ///< Run animation for a MW-reference. Calls to this function for references that are currently not + /// in the rendered scene should be ignored. + /// + /// \param mode: 0 normal, 1 immediate start, 2 immediate loop + /// \param number How offen the animation should be run + + void skipAnimation (const MWWorld::Ptr& ptr); + ///< Skip the animation for the given MW-reference for one frame. Calls to this function for + /// references that are currently not in the rendered scene should be ignored. + private: void setAmbientMode(); diff --git a/apps/openmw/mwscript/animationextensions.cpp b/apps/openmw/mwscript/animationextensions.cpp new file mode 100644 index 000000000..184be83db --- /dev/null +++ b/apps/openmw/mwscript/animationextensions.cpp @@ -0,0 +1,127 @@ + +#include "animationextensions.hpp" + +#include + +#include + +#include +#include +#include + +#include "../mwworld/world.hpp" + +#include "interpretercontext.hpp" +#include "ref.hpp" + +namespace MWScript +{ + namespace Animation + { + template + class OpSkipAnim : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + context.getWorld().skipAnimation (ptr); + } + }; + + template + class OpPlayAnim : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + std::string group = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer mode = 0; + + if (arg0==1) + { + mode = runtime[0].mInteger; + runtime.pop(); + + if (mode<0 || mode>2) + throw std::runtime_error ("animation mode out of range"); + } + + context.getWorld().playAnimationGroup (ptr, group, mode, 1); + } + }; + + template + class OpLoopAnim : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + std::string group = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer loops = runtime[0].mInteger; + runtime.pop(); + + if (loops<0) + throw std::runtime_error ("number of animation loops must be non-negative"); + + Interpreter::Type_Integer mode = 0; + + if (arg0==1) + { + mode = runtime[0].mInteger; + runtime.pop(); + + if (mode<0 || mode>2) + throw std::runtime_error ("animation mode out of range"); + } + + context.getWorld().playAnimationGroup (ptr, group, mode, loops); + } + }; + + const int opcodeSkipAnim = 0x2000138; + const int opcodeSkipAnimExplicit = 0x2000139; + const int opcodePlayAnim = 0x20006; + const int opcodePlayAnimExplicit = 0x20007; + const int opcodeLoopAnim = 0x20008; + const int opcodeLoopAnimExplicit = 0x20009; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("skipanim", "", opcodeSkipAnim, opcodeSkipAnimExplicit); + extensions.registerInstruction ("playgroup", "c/l", opcodePlayAnim, opcodePlayAnimExplicit); + extensions.registerInstruction ("loopgroup", "cl/l", opcodeLoopAnim, opcodeLoopAnimExplicit); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeSkipAnim, new OpSkipAnim); + interpreter.installSegment5 (opcodeSkipAnimExplicit, new OpSkipAnim); + interpreter.installSegment3 (opcodePlayAnim, new OpPlayAnim); + interpreter.installSegment3 (opcodePlayAnimExplicit, new OpPlayAnim); + interpreter.installSegment3 (opcodeLoopAnim, new OpLoopAnim); + interpreter.installSegment3 (opcodeLoopAnimExplicit, new OpLoopAnim); + } + } +} diff --git a/apps/openmw/mwscript/animationextensions.hpp b/apps/openmw/mwscript/animationextensions.hpp new file mode 100644 index 000000000..ff619ab73 --- /dev/null +++ b/apps/openmw/mwscript/animationextensions.hpp @@ -0,0 +1,24 @@ +#ifndef GAME_SCRIPT_ANIMATIONEXTENSIONS_H +#define GAME_SCRIPT_ANIMATIONEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + namespace Animation + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 33ce38cdd..183605328 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -19,7 +19,11 @@ op 0x20002: AiEscort op 0x20003: AiEscort, explicit reference op 0x20004: Lock op 0x20005: Lock, explicit reference -opcodes 0x20006-0x3ffff unused +op 0x20006: PlayAnim +op 0x20007: PlayAnim, explicit reference +op 0x20008: LoopAnim +op 0x20009: LoopAnim, explicit reference +opcodes 0x2000a-0x3ffff unused Segment 4: (not implemented yet) @@ -109,4 +113,6 @@ op 0x2000134: SetJournalIndex op 0x2000135: GetJournalIndex op 0x2000136: GetPCCell op 0x2000137: GetButtonPressed -opcodes 0x2000138-0x3ffffff unused +op 0x2000138: SkipAnim +op 0x2000139: SkipAnim, expplicit reference +opcodes 0x200013a-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index 86161d2b1..197494146 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -14,6 +14,7 @@ #include "aiextensions.hpp" #include "controlextensions.hpp" #include "dialogueextensions.hpp" +#include "animationextensions.hpp" namespace MWScript { @@ -29,6 +30,7 @@ namespace MWScript Ai::registerExtensions (extensions); Control::registerExtensions (extensions); Dialogue::registerExtensions (extensions); + Animation::registerExtensions (extensions); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -44,5 +46,6 @@ namespace MWScript Ai::installOpcodes (interpreter); Control::installOpcodes (interpreter); Dialogue::installOpcodes (interpreter); + Animation::installOpcodes (interpreter); } } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 45f333d9b..126bdaf38 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -673,4 +673,15 @@ namespace MWWorld return cell; } } + + void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number) + { + mRendering.playAnimationGroup (ptr, groupName, mode, number); + } + + void World::skipAnimation (const MWWorld::Ptr& ptr) + { + mRendering.skipAnimation (ptr); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index ea775453a..2c7b43280 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -66,7 +66,7 @@ namespace MWWorld private: MWRender::RenderingManager mRendering; - + MWWorld::Scene *mWorldScene; MWWorld::Player *mPlayer; ESM::ESMReader mEsm; @@ -132,10 +132,10 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle. - + /// \todo enable reference in the OGRE scene void enable (Ptr reference); - + /// \todo 5disable reference in the OGRE scene void disable (Ptr reference); @@ -206,6 +206,18 @@ namespace MWWorld const ESM::Cell *createRecord (const ESM::Cell& record); ///< Create a new recrod (of type cell) in the ESM store. /// \return ID, pointer to created record + + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number = 1); + ///< Run animation for a MW-reference. Calls to this function for references that are + /// currently not in the rendered scene should be ignored. + /// + /// \param mode: 0 normal, 1 immediate start, 2 immediate loop + /// \param number How offen the animation should be run + + void skipAnimation (const MWWorld::Ptr& ptr); + ///< Skip the animation for the given MW-reference for one frame. Calls to this function for + /// references that are currently not in the rendered scene should be ignored. }; }