Issue #133 Handle resources across multiple data directories - WIP

Work In Progress - added support for multiple paths in SoundManager.

Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
actorid
Lukasz Gromanowski 13 years ago
parent 86f88bedae
commit b004e2479c

@ -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

@ -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;

@ -4,8 +4,6 @@
#include <algorithm>
#include <map>
using namespace std;
#include <OgreRoot.h>
#include <openengine/sound/sndmanager.hpp>
@ -15,6 +13,7 @@ using namespace std;
#include <components/file_finder/file_finder.hpp>
#include <components/esm_store/store.hpp>
#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<boost::filesystem::path>::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<ESM::Region::SoundRef>::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;
}

@ -2,14 +2,15 @@
#define GAME_SOUND_SOUNDMANAGER_H
#include <string>
#include <map>
#include <boost/filesystem.hpp>
#include <boost/timer.hpp>
#include "../mwworld/ptr.hpp"
#include <openengine/sound/sndmanager.hpp>
#include <components/files/multidircollection.hpp>
#include <boost/timer.hpp>
namespace Ogre
{
@ -37,7 +38,7 @@ namespace MWSound
struct SoundImpl;
SoundImpl *mData;
std::vector<boost::filesystem::path> 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();

@ -1,9 +1,11 @@
#ifndef FILE_FINDER_MAIN_H
#define FILE_FINDER_MAIN_H
#include <map>
#include "search.hpp"
#include "filename_less.hpp"
#include <map>
#include <components/files/multidircollection.hpp>
namespace FileFinder
{
@ -11,7 +13,8 @@ namespace FileFinder
template <typename LESS>
class FileFinderT
{
std::map<std::string, std::string, LESS> table;
typedef std::map<std::string, std::string, LESS> 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<LESS> 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<std::string, std::string, LESS> TableContainer;
TableContainer mTable;
// Inserter inserter;
};
// The default is to use path_less for equality checks
typedef FileFinderT<path_less> FileFinder;
typedef FileFinderT<path_slash> FileFinderStrict;
}
#endif
typedef TreeFileFinder<path_less> LessTreeFileFinder;
typedef TreeFileFinder<path_slash> StrictTreeFileFinder;
} /* namespace FileFinder */
#endif /* FILE_FINDER_MAIN_H */

@ -2,27 +2,27 @@
#include <iostream>
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);
}
}

@ -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.

Loading…
Cancel
Save