diff --git a/CMakeLists.txt b/CMakeLists.txt index 47c7d6b49c..daf17ba3db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,7 +494,7 @@ if(DPKG_PROGRAM) SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libogremain-1.7.3 (>= 1.7.3), libbullet0 (>= 2.77), libboost-filesystem1.42.0 (>= 1.42.0), libboost-program-options1.42.0 (>= 1.42.0), libboost-system1.42.0 (>= 1.42.0), libboost-thread1.42.0 (>= 1.42.0), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.2.0 (>= 1.2.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libogre-1.7.3 (>= 1.7.3), libbullet0 (>= 2.77), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 21f3e18a2a..54abb948a4 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -149,6 +149,7 @@ set(GAMEWORLD mwworld/containerutil.cpp mwworld/player.cpp mwworld/cells.cpp + mwworld/localscripts.cpp ) set(GAMEWORLD_HEADER mwworld/refdata.hpp @@ -170,6 +171,7 @@ set(GAMEWORLD_HEADER mwworld/player.hpp mwworld/cellfunctors.hpp mwworld/cells.hpp + mwworld/localscripts.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e9ceea2f34..4e58e8a4ca 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -6,22 +6,24 @@ #include #include -#include -#include +#include -#include "components/esm/records.hpp" +#include + +#include +#include + +#include #include -#include #include -#include #include #include - -#include -#include "mwgui/window_manager.hpp" +#include #include "mwinput/inputmanager.hpp" +#include "mwgui/window_manager.hpp" + #include "mwscript/scriptmanager.hpp" #include "mwscript/compilercontext.hpp" #include "mwscript/interpretercontext.hpp" @@ -43,116 +45,76 @@ #include "mwmechanics/mechanicsmanager.hpp" -#include - -#include -#include "mwgui/class.hpp" - -#include "components/nifbullet/bullet_nif_loader.hpp" - -//using namespace ESM; - void OMW::Engine::executeLocalScripts() { - for (MWWorld::World::ScriptList::const_iterator iter ( - mEnvironment.mWorld->getLocalScripts().begin()); - iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter) - { - if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second) - { - MWScript::InterpreterContext interpreterContext (mEnvironment, - &iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second)); - mScriptManager->run (iter->first, interpreterContext); + MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts(); - if (mEnvironment.mWorld->hasCellChanged()) - break; - } + localScripts.startIteration(); + + while (!localScripts.isFinished()) + { + std::pair script = localScripts.getNext(); + + MWScript::InterpreterContext interpreterContext (mEnvironment, + &script.second.getRefData().getLocals(), script.second); + mScriptManager->run (script.first, interpreterContext); + + if (mEnvironment.mWorld->hasCellChanged()) + break; } - mIgnoreLocalPtr = MWWorld::Ptr(); + localScripts.setIgnore (MWWorld::Ptr()); } +void OMW::Engine::updateFocusReport (float duration) +{ + if ((mFocusTDiff += duration)>0.25) + { + mFocusTDiff = 0; + + std::string name; + + std::string handle = mEnvironment.mWorld->getFacedHandle(); + + if (!handle.empty()) + { + MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + + if (!ptr.isEmpty()) + name = MWWorld::Class::get (ptr).getName (ptr); + } + + if (name!=mFocusName) + { + mFocusName = name; + + if (mFocusName.empty()) + std::cout << "Unfocus" << std::endl; + else + std::cout << "Focus: " << name << std::endl; + } + } +} bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) { - if(mShowFPS) - { - mEnvironment.mWindowManager->wmSetFPS(mOgre.getFPS()); - } - - if(mUseSound && !(mEnvironment.mSoundManager->isMusicPlaying())) - { - // Play some good 'ol tunes - mEnvironment.mSoundManager->startRandomTitle(); - } - - std::string effect; - - MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); - - - //If the region has changed - if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ - timer.restart(); - if (test.name != current->cell->region) - { - total = 0; - test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); - } - - if(test.soundList.size() > 0) - { - std::vector::iterator soundIter = test.soundList.begin(); - //mEnvironment.mSoundManager - if(total == 0){ - while (!(soundIter == test.soundList.end())) - { - ESM::NAME32 go = soundIter->sound; - int chance = (int) soundIter->chance; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - soundIter++; - total += chance; - } - } - - srand ( time(NULL) ); - int r = rand() % total; //old random code - int pos = 0; - soundIter = test.soundList.begin(); - while (!(soundIter == test.soundList.end())) - { - const ESM::NAME32 go = soundIter->sound; - int chance = (int) soundIter->chance; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - soundIter++; - if( r - pos < chance) - { - effect = go.name; - //play sound - std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - mEnvironment.mSoundManager->playSound(effect, 20.0, 1.0); - - break; - - } - pos += chance; - } - } - - //mEnvironment.mSoundManager->playSound(effect, 1.0, 1.0); - //printf("REGION: %s\n", test.name); - - } - else if(current->cell->data.flags & current->cell->Interior) - { - test.name = ""; - } - try { mEnvironment.mFrameDuration = evt.timeSinceLastFrame; - // + // sound + if (mUseSound) + { + if (!mEnvironment.mSoundManager->isMusicPlaying()) + mEnvironment.mSoundManager->startRandomTitle(); + + mEnvironment.mSoundManager->update (evt.timeSinceLastFrame); + } + + // update GUI + if(mShowFPS) + mEnvironment.mWindowManager->wmSetFPS(mOgre->getFPS()); + mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration); // global scripts @@ -177,52 +139,39 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) std::vector > movement; mEnvironment.mMechanicsManager->update (movement); - if (focusFrameCounter++ == focusUpdateFrame) - { - std::string handle = mEnvironment.mWorld->getFacedHandle(); - - std::string name; - - if (!handle.empty()) - { - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - - if (!ptr.isEmpty()) - name = MWWorld::Class::get (ptr).getName (ptr); - } - - if (!name.empty()) - std::cout << "Object: " << name << std::endl; - - focusFrameCounter = 0; - } - if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game) mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration); + + // report focus object (for debugging) + if (mReportFocus) + updateFocusReport (mEnvironment.mFrameDuration); } catch (const std::exception& e) { std::cerr << "Error in framelistener: " << e.what() << std::endl; } - //std::cout << "TESTING2"; return true; } OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager) - : mPhysicEngine (0) + : mOgre (0) + , mPhysicEngine (0) , mShowFPS (false) , mDebug (false) , mVerboseScripts (false) , mNewGame (false) , mUseSound (true) , mCompileAll (false) + , mReportFocus (false) + , mFocusTDiff (0) , mScriptManager (0) , mScriptContext (0) , mGuiManager (0) , mFSStrict (false) , mCfgMgr(configurationManager) { + std::srand ( std::time(NULL) ); MWClass::registerClasses(); } @@ -238,6 +187,7 @@ OMW::Engine::~Engine() delete mScriptManager; delete mScriptContext; delete mPhysicEngine; + delete mOgre; } // Load all BSA files in data directory. @@ -261,7 +211,7 @@ void OMW::Engine::loadBSA() void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path) { - mOgre.getRoot()->addResourceLocation (path.string(), "FileSystem", + mOgre->getRoot()->addResourceLocation (path.string(), "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); } @@ -325,6 +275,11 @@ void OMW::Engine::setNewGame(bool newGame) mNewGame = newGame; } +void OMW::Engine::setReportFocus (bool report) +{ + mReportFocus = report; +} + // Initialise and enter main loop. void OMW::Engine::go() @@ -332,11 +287,11 @@ void OMW::Engine::go() assert (!mEnvironment.mWorld); assert (!mCellName.empty()); assert (!mMaster.empty()); + assert (!mOgre); - test.name = ""; - total = 0; + mOgre = new OEngine::Render::OgreRenderer; - mOgre.configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), + mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), mCfgMgr.getOgreConfigPath().string(), mCfgMgr.getLogPath().string() + std::string("/"), mCfgMgr.getPluginsConfigPath().string(), false); @@ -346,28 +301,24 @@ void OMW::Engine::go() addResourcesDirectory(mResDir / "mygui"); // Create the window - mOgre.createWindow("OpenMW"); + mOgre->createWindow("OpenMW"); loadBSA(); + /// \todo move this into the physics manager // Create physics. shapeLoader is deleted by the physic engine NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader); // Create the world - mEnvironment.mWorld = new MWWorld::World (mOgre, mPhysicEngine, mFileCollections, mMaster, + mEnvironment.mWorld = new MWWorld::World (*mOgre, mPhysicEngine, mFileCollections, mMaster, mResDir, mNewGame, mEnvironment, mEncoding); + /// \todo move this into the GUI manager (a.k.a WindowManager) // Set up the GUI system - mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), mOgre.getScene(), false, + mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, mCfgMgr.getLogPath().string() + std::string("/")); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); @@ -375,11 +326,11 @@ void OMW::Engine::go() mExtensions, mShowFPS, mNewGame); // Create sound system - mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), - mOgre.getCamera(), + mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(), + mOgre->getCamera(), mEnvironment.mWorld->getStore(), (mDataDir), - mUseSound, mFSStrict); + mUseSound, mFSStrict, mEnvironment); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, @@ -417,44 +368,32 @@ void OMW::Engine::go() } // Sets up the input system - MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayer(), + MWInput::MWInputManager input(*mOgre, mEnvironment.mWorld->getPlayer(), *mEnvironment.mWindowManager, mDebug, *this); mEnvironment.mInputManager = &input; - focusFrameCounter = 0; - std::cout << "\nPress Q/ESC or close window to exit.\n"; - mOgre.getRoot()->addFrameListener (this); + mOgre->getRoot()->addFrameListener (this); // Play some good 'ol tunes - mEnvironment.mSoundManager->startRandomTitle(); + mEnvironment.mSoundManager->startRandomTitle(); // scripts if (mCompileAll) { - typedef ESMS::ScriptListT::MapType Container; + std::pair result = mScriptManager->compileAll(); - Container scripts = mEnvironment.mWorld->getStore().scripts.list; - - int count = 0; - int success = 0; - - for (Container::const_iterator iter (scripts.begin()); iter!=scripts.end(); ++iter, ++count) - if (mScriptManager->compile (iter->first)) - ++success; - - if (count) + if (result.first) std::cout - << "compiled " << success << " of " << count << " scripts (" - << 100*static_cast (success)/count + << "compiled " << result.second << " of " << result.first << " scripts (" + << 100*static_cast (result.second)/result.first << "%)" << std::endl; - } // Start the main rendering loop - mOgre.start(); + mOgre->start(); std::cout << "Quitting peacefully.\n"; } @@ -488,7 +427,7 @@ void OMW::Engine::activate() if (!script.empty()) { - mIgnoreLocalPtr = ptr; + mEnvironment.mWorld->getLocalScripts().setIgnore (ptr); mScriptManager->run (script, interpreterContext); } diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 3df0d0b3af..443f790a47 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -7,15 +7,14 @@ #include -#include #include + #include #include +#include #include "mwworld/environment.hpp" #include "mwworld/ptr.hpp" -#include -#include namespace Compiler { @@ -48,6 +47,11 @@ namespace OEngine { class MyGUIManager; } + + namespace Render + { + class OgreRenderer; + } } namespace OMW @@ -58,7 +62,7 @@ namespace OMW std::string mEncoding; boost::filesystem::path mDataDir; boost::filesystem::path mResDir; - OEngine::Render::OgreRenderer mOgre; + OEngine::Render::OgreRenderer *mOgre; OEngine::Physic::PhysicEngine* mPhysicEngine; std::string mCellName; std::string mMaster; @@ -68,20 +72,15 @@ namespace OMW bool mNewGame; bool mUseSound; bool mCompileAll; - int total; + bool mReportFocus; + float mFocusTDiff; + std::string mFocusName; MWWorld::Environment mEnvironment; MWScript::ScriptManager *mScriptManager; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; OEngine::GUI::MyGUIManager *mGuiManager; - ESM::Region test; - boost::timer timer; - - int focusFrameCounter; - static const int focusUpdateFrame = 10; - - MWWorld::Ptr mIgnoreLocalPtr; Files::Collections mFileCollections; bool mFSStrict; @@ -100,9 +99,9 @@ namespace OMW void executeLocalScripts(); - virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); + void updateFocusReport (float duration); - /// Process pending commands + virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); public: Engine(Cfg::ConfigurationManager& configurationManager); @@ -144,6 +143,9 @@ namespace OMW /// Start as a new game. void setNewGame(bool newGame); + /// Write name of focussed object to cout + void setReportFocus (bool report); + /// Initialise and enter main loop. void go(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index aa8b13b80d..933d1c48aa 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -102,6 +102,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n" "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" "\n\twin1252 - Western European (Latin) alphabet, used by default") + + ("report-focus", boost::program_options::value()->implicit_value(true) + ->default_value(false), "write name of focussed object to cout") ; bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv) @@ -202,6 +205,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio engine.setSoundUsage(!variables["nosound"].as()); engine.setScriptsVerbosity(variables["script-verbose"].as()); engine.setCompileAll(variables["script-all"].as()); + engine.setReportFocus(variables["report-focus"].as()); return true; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 84e45859fb..095d347e7c 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -77,6 +77,12 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat())); } + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + // Set up visibility updateVisible(); } @@ -329,7 +335,7 @@ void WindowManager::updateVisible() dialogueWindow->open(); return; } - + if(mode == GM_InterMessageBox) { if(!mMessageBoxManager->isInteractiveMessageBox()) { diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 07fa934547..5fcfcc6050 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -116,4 +116,20 @@ namespace MWScript iter->second.clear(); // don't execute again. } } + + std::pair ScriptManager::compileAll() + { + typedef ESMS::ScriptListT::MapType Container; + + const Container& scripts = mStore.scripts.list; + + int count = 0; + int success = 0; + + for (Container::const_iterator iter (scripts.begin()); iter!=scripts.end(); ++iter, ++count) + if (compile (iter->first)) + ++success; + + return std::make_pair (count, success); + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index eab9bdcc08..74511f456e 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -52,6 +52,10 @@ namespace MWScript bool compile (const std::string& name); ///< Compile script with the given namen /// \return Success? + + std::pair compileAll(); + ///< Compile all scripts + /// \return count, success }; }; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 970118a13b..7390e4c5ca 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -1,18 +1,23 @@ #include "soundmanager.hpp" #include +#include +#include + using namespace std; +#include + #include #include #include #include #include -#include -#include -#include +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" /* Set up the sound manager to use Audiere, FFMPEG or MPG123/libsndfile for input. The OPENMW_USE_x macros are set in @@ -378,12 +383,18 @@ namespace MWSound SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &store, boost::filesystem::path dataDir, - bool useSound, bool fsstrict) - : mData(NULL), fsStrict (fsstrict) + bool useSound, bool fsstrict, MWWorld::Environment& environment) + : mData(NULL), fsStrict (fsstrict), mEnvironment (environment) { MP3Lookup(dataDir / "Music/Explore/"); if(useSound) mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string(), (dataDir / "Music").string(), fsstrict); + + + test.name = ""; + total = 0; + + } SoundManager::~SoundManager() @@ -533,4 +544,64 @@ namespace MWSound if(!mData) return; mData->updatePositions(ptr); } + + void SoundManager::update (float duration) + { + std::string effect; + + MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); + + //If the region has changed + if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ + timer.restart(); + if (test.name != current->cell->region) + { + total = 0; + test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); + } + + if(test.soundList.size() > 0) + { + std::vector::iterator soundIter = test.soundList.begin(); + //mEnvironment.mSoundManager + if(total == 0){ + while (!(soundIter == test.soundList.end())) + { + ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + total += chance; + } + } + + int r = rand() % total; //old random code + int pos = 0; + soundIter = test.soundList.begin(); + while (!(soundIter == test.soundList.end())) + { + const ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + if( r - pos < chance) + { + effect = go.name; + //play sound + std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + mEnvironment.mSoundManager->playSound(effect, 20.0, 1.0); + + break; + + } + pos += chance; + } + } + } + else if(current->cell->data.flags & current->cell->Interior) + { + test.name = ""; + } + + } } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index ab9559176e..7dff16c761 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -8,6 +8,9 @@ #include "../mwworld/ptr.hpp" #include + +#include + namespace Ogre { class Root; @@ -19,6 +22,11 @@ namespace ESMS struct ESMStore; } +namespace MWWorld +{ + struct Environment; +} + namespace MWSound { //SoundPtr *music; @@ -31,6 +39,11 @@ namespace MWSound SoundImpl *mData; std::vector files; bool fsStrict; + MWWorld::Environment& mEnvironment; + + int total; + ESM::Region test; + boost::timer timer; void streamMusicFull (const std::string& filename); ///< Play a soundifle @@ -38,8 +51,9 @@ namespace MWSound public: - SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - boost::filesystem::path dataDir, bool useSound, bool fsstrict); + SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, + boost::filesystem::path dataDir, bool useSound, bool fsstrict, + MWWorld::Environment& environment); ~SoundManager(); void streamMusic(const std::string& filename); @@ -60,8 +74,6 @@ namespace MWSound bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? - - void playSound (const std::string& soundId, float volume, float pitch); ///< Play a sound, independently of 3D-position @@ -81,6 +93,8 @@ namespace MWSound void updateObject(MWWorld::Ptr reference); ///< Update the position of all sounds connected to the given object. + + void update (float duration); }; } diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp new file mode 100644 index 0000000000..2d90d90e01 --- /dev/null +++ b/apps/openmw/mwworld/localscripts.cpp @@ -0,0 +1,126 @@ + +#include "localscripts.hpp" + +namespace +{ + template + void listCellScripts (MWWorld::LocalScripts& localScripts, + ESMS::CellRefList& cellRefList, MWWorld::Ptr::CellStore *cell) + { + for (typename ESMS::CellRefList::List::iterator iter ( + cellRefList.list.begin()); + iter!=cellRefList.list.end(); ++iter) + { + if (!iter->base->script.empty() && iter->mData.getCount()) + { + localScripts.add (iter->base->script, MWWorld::Ptr (&*iter, cell)); + } + } + } +} + +MWWorld::LocalScripts::LocalScripts (const ESMS::ESMStore& store) : mStore (store) {} + +void MWWorld::LocalScripts::setIgnore (const Ptr& ptr) +{ + mIgnore = ptr; +} + +void MWWorld::LocalScripts::startIteration() +{ + mIter = mScripts.begin(); +} + +bool MWWorld::LocalScripts::isFinished() const +{ + if (mIter==mScripts.end()) + return true; + + if (!mIgnore.isEmpty() && mIter->second==mIgnore) + { + std::list >::iterator iter = mIter; + return ++iter==mScripts.end(); + } + + return false; +} + +std::pair MWWorld::LocalScripts::getNext() +{ + assert (!isFinished()); + + std::list >::iterator iter = mIter++; + + if (mIgnore.isEmpty() || iter->second!=mIgnore) + return *iter; + + return getNext(); +} + +void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) +{ + if (const ESM::Script *script = mStore.scripts.find (scriptName)) + { + ptr.getRefData().setLocals (*script); + + mScripts.push_back (std::make_pair (scriptName, ptr)); + } +} + +void MWWorld::LocalScripts::addCell (Ptr::CellStore *cell) +{ + listCellScripts (*this, cell->activators, cell); + listCellScripts (*this, cell->potions, cell); + listCellScripts (*this, cell->appas, cell); + listCellScripts (*this, cell->armors, cell); + listCellScripts (*this, cell->books, cell); + listCellScripts (*this, cell->clothes, cell); + listCellScripts (*this, cell->containers, cell); + listCellScripts (*this, cell->creatures, cell); + listCellScripts (*this, cell->doors, cell); + listCellScripts (*this, cell->ingreds, cell); + listCellScripts (*this, cell->lights, cell); + listCellScripts (*this, cell->lockpicks, cell); + listCellScripts (*this, cell->miscItems, cell); + listCellScripts (*this, cell->npcs, cell); + listCellScripts (*this, cell->probes, cell); + listCellScripts (*this, cell->repairs, cell); + listCellScripts (*this, cell->weapons, cell); +} + +void MWWorld::LocalScripts::clear() +{ + mScripts.clear(); +} + +void MWWorld::LocalScripts::clearCell (Ptr::CellStore *cell) +{ + std::list >::iterator iter = mScripts.begin(); + + while (iter!=mScripts.end()) + { + if (iter->second.getCell()==cell) + { + if (iter==mIter) + ++mIter; + + mScripts.erase (iter++); + } + else + ++iter; + } +} + +void MWWorld::LocalScripts::remove (const Ptr& ptr) +{ + for (std::list >::iterator iter = mScripts.begin(); + iter!=mScripts.end(); ++iter) + if (iter->second==ptr) + { + if (iter==mIter) + ++mIter; + + mScripts.erase (iter); + break; + } +} diff --git a/apps/openmw/mwworld/localscripts.hpp b/apps/openmw/mwworld/localscripts.hpp new file mode 100644 index 0000000000..1ea2cf4d5a --- /dev/null +++ b/apps/openmw/mwworld/localscripts.hpp @@ -0,0 +1,58 @@ +#ifndef GAME_MWWORLD_LOCALSCRIPTS_H +#define GAME_MWWORLD_LOCALSCRIPTS_H + +#include +#include + +#include "ptr.hpp" + +namespace ESMS +{ + struct ESMStore; +} + +namespace MWWorld +{ + /// \brief List of active local scripts + class LocalScripts + { + std::list > mScripts; + std::list >::iterator mIter; + MWWorld::Ptr mIgnore; + const ESMS::ESMStore& mStore; + + public: + + LocalScripts (const ESMS::ESMStore& store); + + void setIgnore (const Ptr& ptr); + ///< Mark a single reference for ignoring during iteration over local scripts (will revoke + /// previous ignores). + + void startIteration(); + ///< Set the iterator to the begin of the script list. + + bool isFinished() const; + ///< Is iteration finished? + + std::pair getNext(); + ///< Get next local script (must not be called if isFinished()) + + void add (const std::string& scriptName, const Ptr& ptr); + ///< Add script to collection of active local scripts. + + void addCell (Ptr::CellStore *cell); + ///< Add all local scripts in a cell. + + void clear(); + ///< Clear active local scripts collection. + + void clearCell (Ptr::CellStore *cell); + ///< Remove all scripts belonging to \a cell. + + void remove (const Ptr& ptr); + ///< Remove script for given reference (ignored if reference does not have a scirpt listed). + }; +} + +#endif diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 11bdad35f6..da9bff6b2e 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -57,7 +57,7 @@ namespace MWWorld mPhysics->removeObject (*iter); } - mWorld->removeScripts (iter->first); + mWorld->getLocalScripts().clearCell (iter->first); mEnvironment.mMechanicsManager->dropActors (iter->first); mEnvironment.mSoundManager->stopSound (iter->first); @@ -68,7 +68,7 @@ namespace MWWorld void Scene::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render) { // register local scripts - mWorld->insertInteriorScripts (*cell); + mWorld->getLocalScripts().addCell (cell); // This connects the cell data with the rendering scene. std::pair result = diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index f2e846ef44..78827f150a 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -27,7 +27,7 @@ namespace { template void listCellScripts (const ESMS::ESMStore& store, - ESMS::CellRefList& cellRefList, MWWorld::World::ScriptList& scriptList, + ESMS::CellRefList& cellRefList, MWWorld::LocalScripts& localScripts, MWWorld::Ptr::CellStore *cell) { for (typename ESMS::CellRefList::List::iterator iter ( @@ -40,8 +40,7 @@ namespace { iter->mData.setLocals (*script); - scriptList.push_back ( - std::make_pair (iter->base->script, MWWorld::Ptr (&*iter, cell))); + localScripts.add (iter->base->script, MWWorld::Ptr (&*iter, cell)); } } } @@ -67,28 +66,6 @@ namespace namespace MWWorld { - - void World::insertInteriorScripts (ESMS::CellStore& cell) - { - listCellScripts (mStore, cell.activators, mLocalScripts, &cell); - listCellScripts (mStore, cell.potions, mLocalScripts, &cell); - listCellScripts (mStore, cell.appas, mLocalScripts, &cell); - listCellScripts (mStore, cell.armors, mLocalScripts, &cell); - listCellScripts (mStore, cell.books, mLocalScripts, &cell); - listCellScripts (mStore, cell.clothes, mLocalScripts, &cell); - listCellScripts (mStore, cell.containers, mLocalScripts, &cell); - listCellScripts (mStore, cell.creatures, mLocalScripts, &cell); - listCellScripts (mStore, cell.doors, mLocalScripts, &cell); - listCellScripts (mStore, cell.ingreds, mLocalScripts, &cell); - listCellScripts (mStore, cell.lights, mLocalScripts, &cell); - listCellScripts (mStore, cell.lockpicks, mLocalScripts, &cell); - listCellScripts (mStore, cell.miscItems, mLocalScripts, &cell); - listCellScripts (mStore, cell.npcs, mLocalScripts, &cell); - listCellScripts (mStore, cell.probes, mLocalScripts, &cell); - listCellScripts (mStore, cell.repairs, mLocalScripts, &cell); - listCellScripts (mStore, cell.weapons, mLocalScripts, &cell); - } - Ptr World::getPtrViaHandle (const std::string& handle, Ptr::CellStore& cell) { if (ESMS::LiveCellRef *ref = @@ -185,20 +162,6 @@ namespace MWWorld throw std::runtime_error ("month out of range"); } - void World::removeScripts (Ptr::CellStore *cell) - { - ScriptList::iterator iter = mLocalScripts.begin(); - - while (iter!=mLocalScripts.end()) - { - if (iter->second.getCell()==cell) - mLocalScripts.erase (iter++); - else - ++iter; - } - } - - void World::adjustSky() { if (mSky) @@ -213,7 +176,7 @@ namespace MWWorld const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment, const std::string& encoding) - : mScene (renderer,physEng), mPlayer (0), mGlobalVariables (0), + : mScene (renderer,physEng), mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (false), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this) { mPhysEngine = physEng; @@ -306,7 +269,7 @@ namespace MWWorld return mEsm; } - const World::ScriptList& World::getLocalScripts() const + LocalScripts& World::getLocalScripts() { return mLocalScripts; } @@ -575,13 +538,7 @@ namespace MWWorld mPhysics->removeObject (ptr.getRefData().getHandle()); - for (ScriptList::iterator iter = mLocalScripts.begin(); iter!=mLocalScripts.end(); - ++iter) - if (ptr==iter->second) - { - mLocalScripts.erase (iter); - break; - } + mLocalScripts.remove (ptr); } render->deleteObject (ptr.getRefData().getHandle()); diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 89c6057fa8..978f14c8ea 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -17,6 +17,7 @@ #include "scene.hpp" #include "physicssystem.hpp" #include "cells.hpp" +#include "localscripts.hpp" #include @@ -55,9 +56,7 @@ namespace MWWorld class World { - public: - typedef std::list > ScriptList; enum RenderMode { @@ -71,7 +70,7 @@ namespace MWWorld MWWorld::Player *mPlayer; ESM::ESMReader mEsm; ESMS::ESMStore mStore; - ScriptList mLocalScripts; + LocalScripts mLocalScripts; MWWorld::Globals *mGlobalVariables; MWWorld::PhysicsSystem *mPhysics; bool mSky; @@ -108,10 +107,6 @@ namespace MWWorld Ptr::CellStore *getInterior (const std::string& name); - void removeScripts (Ptr::CellStore *cell); - - void insertInteriorScripts (ESMS::CellStore& cell); - void adjustSky(); MWWorld::Player& getPlayer(); @@ -120,8 +115,7 @@ namespace MWWorld ESM::ESMReader& getEsmReader(); - const ScriptList& getLocalScripts() const; - ///< Names and local variable state of all local scripts in active cells. + LocalScripts& getLocalScripts(); bool hasCellChanged() const; ///< Has the player moved to a different cell, since the last frame?