diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index bbc68b8e2..31c947054 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -200,12 +200,12 @@ void OMW::Engine::loadBSA() for (Files::MultiDirCollection::TIter iter (bsa.begin()); iter!=bsa.end(); ++iter) { - std::cout << "Adding " << iter->second.string() << std::endl; - Bsa::addBSA (iter->second.string()); + std::cout << "Adding " << iter->second.string() << std::endl; + Bsa::addBSA (iter->second.string()); } - std::cout << "Data dir " << mDataDir.string() << std::endl; - Bsa::addDir(mDataDir.string(), mFSStrict); + //std::cout << "Data dir " << mDataDir.string() << std::endl; + //Bsa::addDir(mDataDir.string(), mFSStrict); } // add resources directory @@ -228,7 +228,7 @@ void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs) { /// \todo remove mDataDir, once resources system can handle multiple directories assert (!dataDirs.empty()); - mDataDir = dataDirs.back(); + mDataDirs = dataDirs; mFileCollections = Files::Collections (dataDirs, !mFSStrict); } @@ -339,7 +339,7 @@ void OMW::Engine::go() mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(), mOgre->getCamera(), mEnvironment.mWorld->getStore(), - (mDataDir), + mDataDirs, mUseSound, mFSStrict, mEnvironment); // Create script system diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 97079f5a5..40bf73c6d 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -64,7 +64,7 @@ namespace OMW class Engine : private Ogre::FrameListener { std::string mEncoding; - boost::filesystem::path mDataDir; + Files::PathContainer mDataDirs; boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; OEngine::Physic::PhysicEngine* mPhysicEngine; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 7390e4c5c..76ef23bc2 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -4,8 +4,6 @@ #include #include -using namespace std; - #include #include @@ -15,6 +13,7 @@ using namespace std; #include #include + #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -90,24 +89,28 @@ namespace MWSound // relative to the sound dir, and translates them into full paths // of existing files in the filesystem, if they exist. bool FSstrict; - FileFinder::FileFinder files; - FileFinder::FileFinderStrict strict; - FileFinder::FileFinder musicpath; - FileFinder::FileFinderStrict musicpathStrict; - - SoundImpl(Ogre::Root *root, Ogre::Camera *camera, - const ESMS::ESMStore &str, - const std::string &soundDir, const std::string &musicDir, bool fsstrict) + FileFinder::LessTreeFileFinder files; + FileFinder::StrictTreeFileFinder strict; + FileFinder::LessTreeFileFinder musicpath; + FileFinder::StrictTreeFileFinder musicpathStrict; + + SoundImpl(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &str, + const Files::PathContainer& soundDir, + const Files::PathContainer& musicDir, + bool fsstrict) : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) , updater(mgr) , cameraTracker(mgr) , store(str) - , files(soundDir), strict(soundDir) - ,musicpath(musicDir), musicpathStrict(musicDir) + , FSstrict(fsstrict) + , files(soundDir) + , strict(soundDir) + , musicpath(musicDir) + , musicpathStrict(musicDir) { - FSstrict = fsstrict; - cout << "Sound output: " << SOUND_OUT << endl; - cout << "Sound decoder: " << SOUND_IN << endl; + + std::cout << "Sound output: " << SOUND_OUT << std::endl; + std::cout << "Sound decoder: " << SOUND_IN << std::endl; // Attach the camera to the camera tracker cameraTracker.followCamera(camera); @@ -136,36 +139,49 @@ namespace MWSound bool hasFile(const std::string &str, bool music = false) { - if(FSstrict == false) + bool found = false; + if(!FSstrict) { if(music) { - if(musicpath.has(str)) return true; - + found = musicpath.has(str); // Not found? Try with .mp3 - return musicpath.has(toMp3(str)); + if (!found) + { + found = musicpath.has(toMp3(str)); + } } else { - if(files.has(str)) return true; - return files.has(toMp3(str)); + found = files.has(str); + if (!found) + { + found = files.has(toMp3(str)); + } } } else { if(music) { - if(musicpathStrict.has(str)) return true; - + found = musicpathStrict.has(str); // Not found? Try with .mp3 - return musicpathStrict.has(toMp3(str)); + if (!found) + { + found = musicpathStrict.has(toMp3(str)); + } } else { - if(strict.has(str)) return true; - return strict.has(toMp3(str)); + found = strict.has(str); + if (!found) + { + found = strict.has(toMp3(str)); + } } } + + return found; } // Convert a Morrowind sound path (eg. Fx\funny.wav) to full path @@ -258,13 +274,13 @@ namespace MWSound } catch(...) { - cout << "Error loading " << file << ", skipping.\n"; + std::cout << "Error loading " << file << ", skipping.\n"; } } // Clears all the sub-elements of a given iterator, and then // removes it from 'sounds'. - void clearAll(PtrMap::iterator it) + void clearAll(PtrMap::iterator& it) { IDMap::iterator sit = it->second.begin(); @@ -362,9 +378,9 @@ namespace MWSound } } } - }; + }; /* SoundImpl */ - void SoundManager::streamMusicFull (const std::string& filename) + void SoundManager::streamMusicFull(const std::string& filename) { if(!mData) return; @@ -381,20 +397,24 @@ namespace MWSound } SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, - const ESMS::ESMStore &store, - boost::filesystem::path dataDir, - bool useSound, bool fsstrict, MWWorld::Environment& environment) - : mData(NULL), fsStrict (fsstrict), mEnvironment (environment) + const ESMS::ESMStore &store, const Files::PathContainer& dataDirs, + 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); + for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) + { + MP3Lookup((*it) / "Music/Explore/"); + } + if(useSound) + { + mData = new SoundImpl(root, camera, store, dataDirs /* Sound */, dataDirs /* Music */, fsstrict); + } test.name = ""; total = 0; - - } SoundManager::~SoundManager() @@ -407,14 +427,12 @@ namespace MWSound { if(mData->hasFile(filename, true)) { - std::string fullpath = mData->convertPath(filename, true); - streamMusicFull(fullpath); + streamMusicFull(mData->convertPath(filename, true)); } } - - void SoundManager::MP3Lookup(boost::filesystem::path dir) -{ + void SoundManager::MP3Lookup(const boost::filesystem::path& dir) + { boost::filesystem::directory_iterator dir_iter(dir), dir_end; std::string mp3extension = ".mp3"; @@ -425,35 +443,30 @@ namespace MWSound files.push_back(*dir_iter); } } -} + } void SoundManager::startRandomTitle() -{ - std::vector::iterator fileIter; - - if(files.size() > 0) + { + if(!files.empty()) { - fileIter = files.begin(); - srand ( time(NULL) ); + Files::PathContainer::iterator fileIter = files.begin(); + srand( time(NULL) ); int r = rand() % files.size() + 1; //old random code - for(int i = 1; i < r; i++) - { - fileIter++; - } + std::advance(fileIter, r - 1); std::string music = fileIter->string(); + std::cout << "Playing " << music << "\n"; + try { - std::cout << "Playing " << music << "\n"; streamMusicFull(music); } - catch(std::exception &e) + catch (std::exception &e) { std::cout << " Music Error: " << e.what() << "\n"; } } -} - + } bool SoundManager::isMusicPlaying() { @@ -465,14 +478,12 @@ namespace MWSound return test; } - SoundManager::SoundImpl SoundManager::getMData() + SoundManager::SoundImpl SoundManager::getMData() { // bool test = mData->music->isPlaying(); return *mData; } - - void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) { // The range values are not tested @@ -480,7 +491,7 @@ namespace MWSound if(mData->hasFile(filename)) mData->add(mData->convertPath(filename), ptr, "_say_sound", 1, 1, 100, 20000, false); else - cout << "Sound file " << filename << " not found, skipping.\n"; + std::cout << "Sound file " << filename << " not found, skipping.\n"; } bool SoundManager::sayDone (MWWorld::Ptr ptr) const @@ -490,20 +501,20 @@ namespace MWSound } - void SoundManager::playSound (const std::string& soundId, float volume, float pitch) + void SoundManager::playSound(const std::string& soundId, float volume, float pitch) { if(!mData) return; // Play and forget float min, max; const std::string &file = mData->lookup(soundId, volume, min, max); - if(file != "") - { + if (file != "") + { SoundPtr snd = mData->mgr->load(file); snd->setVolume(volume); snd->setRange(min,max); snd->setPitch(pitch); snd->play(); - } + } } void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, @@ -514,7 +525,7 @@ namespace MWSound // Look up the sound in the ESM data float min, max; const std::string &file = mData->lookup(soundId, volume, min, max); - if(file != "") + if (file != "") mData->add(file, ptr, soundId, volume, pitch, min, max, loop); } @@ -541,18 +552,19 @@ namespace MWSound void SoundManager::updateObject(MWWorld::Ptr ptr) { - if(!mData) return; - mData->updatePositions(ptr); + if (mData != NULL) + { + 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){ + if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10) + { timer.restart(); if (test.name != current->cell->region) { @@ -564,11 +576,12 @@ namespace MWSound { std::vector::iterator soundIter = test.soundList.begin(); //mEnvironment.mSoundManager - if(total == 0){ - while (!(soundIter == test.soundList.end())) + if(total == 0) + { + while (soundIter != test.soundList.end()) { - ESM::NAME32 go = soundIter->sound; int chance = (int) soundIter->chance; + //ESM::NAME32 go = soundIter->sound; //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; soundIter++; total += chance; @@ -578,7 +591,7 @@ namespace MWSound int r = rand() % total; //old random code int pos = 0; soundIter = test.soundList.begin(); - while (!(soundIter == test.soundList.end())) + while (soundIter != test.soundList.end()) { const ESM::NAME32 go = soundIter->sound; int chance = (int) soundIter->chance; @@ -586,13 +599,11 @@ namespace MWSound 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); + mEnvironment.mSoundManager->playSound(go.name, 20.0, 1.0); break; - } pos += chance; } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 7dff16c76..5c3f473f2 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -2,14 +2,15 @@ #define GAME_SOUND_SOUNDMANAGER_H #include -#include #include +#include + #include "../mwworld/ptr.hpp" #include +#include -#include namespace Ogre { @@ -37,7 +38,7 @@ namespace MWSound struct SoundImpl; SoundImpl *mData; - std::vector files; + Files::PathContainer files; bool fsStrict; MWWorld::Environment& mEnvironment; @@ -52,7 +53,7 @@ namespace MWSound public: SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - boost::filesystem::path dataDir, bool useSound, bool fsstrict, + const Files::PathContainer& dataDir, bool useSound, bool fsstrict, MWWorld::Environment& environment); ~SoundManager(); @@ -61,7 +62,7 @@ namespace MWSound /// \param filename name of a sound file in "Music/" in the data directory. void startRandomTitle(); - void MP3Lookup(boost::filesystem::path dir); + void MP3Lookup(const boost::filesystem::path& dir); bool isMusicPlaying(); diff --git a/components/file_finder/file_finder.hpp b/components/file_finder/file_finder.hpp index 0e1e07226..8a15af73a 100644 --- a/components/file_finder/file_finder.hpp +++ b/components/file_finder/file_finder.hpp @@ -1,9 +1,11 @@ #ifndef FILE_FINDER_MAIN_H #define FILE_FINDER_MAIN_H +#include + #include "search.hpp" #include "filename_less.hpp" -#include +#include namespace FileFinder { @@ -11,7 +13,8 @@ namespace FileFinder template class FileFinderT { - std::map table; + typedef std::map TableContainer; + TableContainer table; struct Inserter : ReturnPath { @@ -35,12 +38,12 @@ public: // Remember the original path length, so we can cut it away from // the relative paths used as keys - std::string pstring = path.string(); + const std::string& pstring = path.string(); inserter.cut = pstring.size(); // If the path does not end in a slash, then boost will add one // later, which means one more character we have to remove. - char last = pstring[pstring.size()-1]; + char last = *pstring.rbegin(); if(last != '\\' && last != '/') inserter.cut++; @@ -56,12 +59,84 @@ public: // Find the full path from a relative path. const std::string &lookup(const std::string& file) const { - return table.find(file)->second; + static std::string empty; + typename TableContainer::const_iterator it = table.find(file); + return (it != table.end()) ? it->second : empty; } }; +template +< + class LESS +> +struct TreeFileFinder +{ + typedef TreeFileFinder finder_t; + + TreeFileFinder(const Files::PathContainer& paths, bool recurse = true) + { + struct : ReturnPath + { + finder_t *owner; + int cut; + + void add(const boost::filesystem::path &pth) + { + std::string file = pth.string(); + std::string key = file.substr(cut); + owner->mTable[key] = file; + } + } inserter; + + inserter.owner = this; + + for (Files::PathContainer::const_iterator it = paths.begin(); it != paths.end(); ++it) + { + + // Remember the original path length, so we can cut it away from + // the relative paths used as keys + const std::string& pstring = it->string(); + inserter.cut = pstring.size(); + + // If the path does not end in a slash, then boost will add one + // later, which means one more character we have to remove. + char last = *pstring.rbegin(); + if (last != '\\' && last != '/') + { + inserter.cut++; + } + + // Fill the map + find(*it, inserter, recurse); + } + } + + bool has(const std::string& file) const + { + return mTable.find(file) != mTable.end(); + } + + const std::string& lookup(const std::string& file) const + { + static std::string empty; + typename TableContainer::const_iterator it = mTable.find(file); + return (it != mTable.end()) ? it->second : empty; + } + + private: + typedef std::map TableContainer; + TableContainer mTable; + +// Inserter inserter; +}; + + // The default is to use path_less for equality checks typedef FileFinderT FileFinder; typedef FileFinderT FileFinderStrict; -} -#endif + +typedef TreeFileFinder LessTreeFileFinder; +typedef TreeFileFinder StrictTreeFileFinder; + +} /* namespace FileFinder */ +#endif /* FILE_FINDER_MAIN_H */ diff --git a/components/file_finder/search.cpp b/components/file_finder/search.cpp index b05b30e83..eb4392abc 100644 --- a/components/file_finder/search.cpp +++ b/components/file_finder/search.cpp @@ -2,27 +2,27 @@ #include -using namespace std; -using namespace boost::filesystem; - -void FileFinder::find(const path & dir_path, ReturnPath &ret, bool recurse) +void FileFinder::find(const boost::filesystem::path & dir_path, ReturnPath &ret, bool recurse) { - if ( !exists( dir_path ) ) + if ( !boost::filesystem::exists( dir_path ) ) { - cout << "Path " << dir_path << " not found\n"; + std::cout << "Path " << dir_path << " not found" << std::endl; return; } - directory_iterator end_itr; // default construction yields past-the-end - for ( directory_iterator itr(dir_path); - itr != end_itr; - ++itr ) + boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end + for (boost::filesystem::directory_iterator itr(dir_path); itr != end_itr; ++itr) { - if ( is_directory( *itr ) ) + if (boost::filesystem::is_directory( *itr )) + { + if (recurse) + { + find(*itr, ret); + } + } + else { - if(recurse) find(*itr, ret); + ret.add(*itr); } - else - ret.add(*itr); } } diff --git a/components/files/multidircollection.hpp b/components/files/multidircollection.hpp index 391f8b6a4..e8abeb45d 100644 --- a/components/files/multidircollection.hpp +++ b/components/files/multidircollection.hpp @@ -68,7 +68,7 @@ namespace Files /// \param foldCase Ignore filename case boost::filesystem::path getPath (const std::string& file) const; - ///< Return full path (including filename) of \æ file. + ///< Return full path (including filename) of \a file. /// /// If the file does not exist, an exception is thrown. \a file must include /// the extension.