1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-29 22:06:45 +00:00

Merge branch 'master' into occlusionquery

This commit is contained in:
scrawl 2012-04-01 14:16:25 +02:00
commit 30407d3a2c
33 changed files with 332 additions and 344 deletions

View file

@ -212,13 +212,18 @@ OMW::Engine::~Engine()
void OMW::Engine::loadBSA() void OMW::Engine::loadBSA()
{ {
const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa"); const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
std::string dataDirectory;
for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter) for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter)
{ {
std::cout << "Adding " << iter->second.string() << std::endl; std::cout << "Adding " << iter->second.string() << std::endl;
Bsa::addBSA(iter->second.string()); Bsa::addBSA(iter->second.string());
}
dataDirectory = iter->second.parent_path().string(); const Files::PathContainer& dataDirs = mFileCollections.getPaths();
std::string dataDirectory;
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl; std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict); Bsa::addDir(dataDirectory, mFSStrict);
} }

View file

@ -56,7 +56,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -60,7 +60,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -58,7 +58,7 @@ namespace MWClass
{ {
// TODO implement reading // TODO implement reading
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -57,7 +57,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -85,7 +85,7 @@ namespace MWClass
{ {
// TODO check for key // TODO check for key
std::cout << "Locked container" << std::endl; std::cout << "Locked container" << std::endl;
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false); environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
else else
@ -100,7 +100,7 @@ namespace MWClass
{ {
// Trap activation goes here // Trap activation goes here
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0, false); environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0);
ptr.getCellRef().trap = ""; ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }

View file

@ -73,7 +73,7 @@ namespace MWClass
// TODO check for key // TODO check for key
// TODO report failure to player (message, sound?). Look up behaviour of original MW. // TODO report failure to player (message, sound?). Look up behaviour of original MW.
std::cout << "Locked!" << std::endl; std::cout << "Locked!" << std::endl;
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false); environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
@ -81,7 +81,7 @@ namespace MWClass
{ {
// Trap activation // Trap activation
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0, false); environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0);
ptr.getCellRef().trap = ""; ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
@ -110,7 +110,7 @@ namespace MWClass
// TODO return action for rotating the door // TODO return action for rotating the door
// This is a little pointless, but helps with testing // This is a little pointless, but helps with testing
environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0, false); environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
} }

View file

@ -54,7 +54,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -59,7 +59,7 @@ namespace MWClass
if (!ref->base->sound.empty()) if (!ref->base->sound.empty())
{ {
environment.mSoundManager->playSound3D (ptr, ref->base->sound, 1.0, 1.0, true); environment.mSoundManager->playSound3D (ptr, ref->base->sound, 1.0, 1.0, MWSound::Play_Loop);
} }
} }
@ -83,7 +83,7 @@ namespace MWClass
if (!(ref->base->data.flags & ESM::Light::Carry)) if (!(ref->base->data.flags & ESM::Light::Carry))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -58,7 +58,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -56,7 +56,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -56,7 +56,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -57,7 +57,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -56,7 +56,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -57,7 +57,7 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true); environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

View file

@ -180,71 +180,58 @@ void WindowManager::updateVisible()
// Mouse is visible whenever we're not in game mode // Mouse is visible whenever we're not in game mode
MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
// If in game mode, don't show anything. switch(mode) {
if(mode == GM_Game) //Use a switch/case structure case GM_Game:
{ // If in game mode, don't show anything.
return; break;
} case GM_MainMenu:
menu->setVisible(true);
break;
case GM_Console:
console->enable();
break;
case GM_Name:
case GM_Race:
case GM_Class:
case GM_ClassPick:
case GM_ClassCreate:
case GM_Birth:
case GM_ClassGenerate:
case GM_Review:
mCharGen->spawnDialog(mode);
break;
case GM_Inventory:
{
// First, compute the effective set of windows to show.
// This is controlled both by what windows the
// user has opened/closed (the 'shown' variable) and by what
// windows we are allowed to show (the 'allowed' var.)
int eff = shown & allowed;
if(mode == GM_MainMenu) // Show the windows we want
{ map -> setVisible( (eff & GW_Map) != 0 );
// Enable the main menu stats -> setVisible( (eff & GW_Stats) != 0 );
menu->setVisible(true); break;
return;
}
if(mode == GM_Console)
{
console->enable();
return;
}
//There must be a more elegant solution
if (mode == GM_Name || mode == GM_Race || mode == GM_Class || mode == GM_ClassPick || mode == GM_ClassCreate || mode == GM_Birth || mode == GM_ClassGenerate || mode == GM_Review)
{
mCharGen->spawnDialog(mode);
return;
}
if(mode == GM_Inventory)
{
// Ah, inventory mode. First, compute the effective set of
// windows to show. This is controlled both by what windows the
// user has opened/closed (the 'shown' variable) and by what
// windows we are allowed to show (the 'allowed' var.)
int eff = shown & allowed;
// Show the windows we want
map -> setVisible( (eff & GW_Map) != 0 );
stats -> setVisible( (eff & GW_Stats) != 0 );
return;
}
if (mode == GM_Dialogue)
{
dialogueWindow->open();
return;
}
if(mode == GM_InterMessageBox)
{
if(!mMessageBoxManager->isInteractiveMessageBox()) {
setGuiMode(GM_Game);
} }
return; case GM_Dialogue:
dialogueWindow->open();
break;
case GM_InterMessageBox:
if(!mMessageBoxManager->isInteractiveMessageBox()) {
setGuiMode(GM_Game);
}
break;
case GM_Journal:
mJournal->setVisible(true);
mJournal->open();
break;
default:
// Unsupported mode, switch back to game
// Note: The call will eventually end up this method again but
// will stop at the check if mode is GM_Game.
setGuiMode(GM_Game);
break;
} }
if(mode == GM_Journal)
{
mJournal->setVisible(true);
mJournal->open();
return;
}
// Unsupported mode, switch back to game
// Note: The call will eventually end up this method again but
// will stop at the check if(mode == GM_Game) above.
setGuiMode(GM_Game);
} }
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)

View file

@ -126,6 +126,11 @@ namespace MWRender{
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
shapeNumber = 0; shapeNumber = 0;
if (allshapes == NULL || creaturemodel == NULL || skel == NULL)
{
return;
}
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter; std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)

View file

@ -27,11 +27,7 @@ bool Debugging::toggleRenderMode (int mode){
switch (mode) switch (mode)
{ {
case MWWorld::World::Render_CollisionDebug: case MWWorld::World::Render_CollisionDebug:
return eng->toggleDebugRendering();
// TODO use a proper function instead of accessing the member variable
// directly.
eng->setDebugRenderingMode (!eng->isDebugCreated);
return eng->isDebugCreated;
} }
return false; return false;

View file

@ -50,7 +50,7 @@ namespace Ogre
terrain. terrain.
@note Requires the Cg plugin to render correctly @note Requires the Cg plugin to render correctly
*/ */
class _OgreTerrainExport TerrainMaterialGeneratorB : public TerrainMaterialGenerator class TerrainMaterialGeneratorB : public TerrainMaterialGenerator
{ {
public: public:
TerrainMaterialGeneratorB(); TerrainMaterialGeneratorB();
@ -58,7 +58,7 @@ namespace Ogre
/** Shader model 2 profile target. /** Shader model 2 profile target.
*/ */
class _OgreTerrainExport SM2Profile : public TerrainMaterialGenerator::Profile class SM2Profile : public TerrainMaterialGenerator::Profile
{ {
public: public:
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc); SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
@ -161,7 +161,7 @@ namespace Ogre
void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt); void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt);
/// Interface definition for helper class to generate shaders /// Interface definition for helper class to generate shaders
class _OgreTerrainExport ShaderHelper : public TerrainAlloc class ShaderHelper : public TerrainAlloc
{ {
public: public:
ShaderHelper() {} ShaderHelper() {}
@ -194,7 +194,7 @@ namespace Ogre
}; };
/// Utility class to help with generating shaders for Cg / HLSL. /// Utility class to help with generating shaders for Cg / HLSL.
class _OgreTerrainExport ShaderHelperCg : public ShaderHelper class ShaderHelperCg : public ShaderHelper
{ {
protected: protected:
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
@ -212,7 +212,7 @@ namespace Ogre
void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
}; };
class _OgreTerrainExport ShaderHelperHLSL : public ShaderHelperCg class ShaderHelperHLSL : public ShaderHelperCg
{ {
protected: protected:
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
@ -220,7 +220,7 @@ namespace Ogre
}; };
/// Utility class to help with generating shaders for GLSL. /// Utility class to help with generating shaders for GLSL.
class _OgreTerrainExport ShaderHelperGLSL : public ShaderHelper class ShaderHelperGLSL : public ShaderHelper
{ {
protected: protected:
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);

View file

@ -130,7 +130,7 @@ namespace MWScript
std::string sound = runtime.getStringLiteral (runtime[0].mInteger); std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
context.getSoundManager().playSound3D (ptr, sound, 1.0, 1.0, mLoop); context.getSoundManager().playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWSound::Play_Loop : 0);
} }
}; };
@ -159,7 +159,7 @@ namespace MWScript
Interpreter::Type_Float pitch = runtime[0].mFloat; Interpreter::Type_Float pitch = runtime[0].mFloat;
runtime.pop(); runtime.pop();
context.getSoundManager().playSound3D (ptr, sound, volume, pitch, mLoop); context.getSoundManager().playSound3D (ptr, sound, volume, pitch, mLoop ? MWSound::Play_Loop : 0);
} }
}; };

View file

@ -25,14 +25,20 @@ static void throwALCerror(ALCdevice *device)
{ {
ALCenum err = alcGetError(device); ALCenum err = alcGetError(device);
if(err != ALC_NO_ERROR) if(err != ALC_NO_ERROR)
fail(alcGetString(device, err)); {
const ALCchar *errstring = alcGetString(device, err);
fail(errstring ? errstring : "");
}
} }
static void throwALerror() static void throwALerror()
{ {
ALenum err = alGetError(); ALenum err = alGetError();
if(err != AL_NO_ERROR) if(err != AL_NO_ERROR)
fail(alGetString(err)); {
const ALchar *errstring = alGetString(err);
fail(errstring ? errstring : "");
}
} }
@ -89,8 +95,7 @@ public:
virtual void stop(); virtual void stop();
virtual bool isPlaying(); virtual bool isPlaying();
virtual void setVolume(float volume); virtual void update();
virtual void update(const float *pos);
void play(); void play();
bool process(); bool process();
@ -187,7 +192,6 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode
} }
catch(std::exception &e) catch(std::exception &e)
{ {
mOutput.mFreeSources.push_back(mSource);
alDeleteBuffers(sNumBuffers, mBuffers); alDeleteBuffers(sNumBuffers, mBuffers);
alGetError(); alGetError();
throw; throw;
@ -255,16 +259,10 @@ bool OpenAL_SoundStream::isPlaying()
return !mIsFinished; return !mIsFinished;
} }
void OpenAL_SoundStream::setVolume(float volume) void OpenAL_SoundStream::update()
{ {
alSourcef(mSource, AL_GAIN, volume*mBaseVolume); alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
throwALerror(); alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
mVolume = volume;
}
void OpenAL_SoundStream::update(const float *pos)
{
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]);
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
throwALerror(); throwALerror();
@ -321,15 +319,17 @@ bool OpenAL_SoundStream::process()
} }
// //
// A regular OpenAL sound // A regular 2D OpenAL sound
// //
class OpenAL_Sound : public Sound class OpenAL_Sound : public Sound
{ {
protected:
OpenAL_Output &mOutput; OpenAL_Output &mOutput;
ALuint mSource; ALuint mSource;
ALuint mBuffer; ALuint mBuffer;
private:
OpenAL_Sound(const OpenAL_Sound &rhs); OpenAL_Sound(const OpenAL_Sound &rhs);
OpenAL_Sound& operator=(const OpenAL_Sound &rhs); OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
@ -339,8 +339,23 @@ public:
virtual void stop(); virtual void stop();
virtual bool isPlaying(); virtual bool isPlaying();
virtual void setVolume(float volume); virtual void update();
virtual void update(const float *pos); };
//
// A regular 3D OpenAL sound
//
class OpenAL_Sound3D : public OpenAL_Sound
{
OpenAL_Sound3D(const OpenAL_Sound &rhs);
OpenAL_Sound3D& operator=(const OpenAL_Sound &rhs);
public:
OpenAL_Sound3D(OpenAL_Output &output, ALuint src, ALuint buf)
: OpenAL_Sound(output, src, buf)
{ }
virtual void update();
}; };
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf) OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf)
@ -372,16 +387,22 @@ bool OpenAL_Sound::isPlaying()
return state==AL_PLAYING; return state==AL_PLAYING;
} }
void OpenAL_Sound::setVolume(float volume) void OpenAL_Sound::update()
{ {
alSourcef(mSource, AL_GAIN, volume*mBaseVolume); alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
throwALerror(); throwALerror();
mVolume = volume;
} }
void OpenAL_Sound::update(const float *pos) void OpenAL_Sound3D::update()
{ {
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]); if(mPos.squaredDistance(mOutput.mPos) > mMaxDistance*mMaxDistance)
alSourcef(mSource, AL_GAIN, 0.0f);
else
alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
throwALerror(); throwALerror();
@ -410,8 +431,7 @@ std::vector<std::string> OpenAL_Output::enumerate()
void OpenAL_Output::init(const std::string &devname) void OpenAL_Output::init(const std::string &devname)
{ {
if(mDevice || mContext) deinit();
fail("Device already open");
mDevice = alcOpenDevice(devname.c_str()); mDevice = alcOpenDevice(devname.c_str());
if(!mDevice) if(!mDevice)
@ -428,7 +448,12 @@ void OpenAL_Output::init(const std::string &devname)
mContext = alcCreateContext(mDevice, NULL); mContext = alcCreateContext(mDevice, NULL);
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE) if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
{
if(mContext)
alcDestroyContext(mContext);
mContext = 0;
fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice))); fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice)));
}
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
throwALerror(); throwALerror();
@ -442,33 +467,13 @@ void OpenAL_Output::init(const std::string &devname)
{ {
ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256); ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256);
if (maxtotal == 0) // workaround for broken implementations if (maxtotal == 0) // workaround for broken implementations
{
maxtotal = 256; maxtotal = 256;
bool stop = false; for(size_t i = 0;i < maxtotal;i++)
for(size_t i = 0;i < maxtotal && !stop;i++) // generate source until error returned
{
ALuint src = 0;
alGenSources(1, &src);
ALenum err = alGetError();
if(err != AL_NO_ERROR)
{
stop = true;
}
else
{
mFreeSources.push_back(src);
}
}
}
else // normal case
{ {
for(size_t i = 0;i < maxtotal;i++) ALuint src = 0;
{ alGenSources(1, &src);
ALuint src = 0; throwALerror();
alGenSources(1, &src); mFreeSources.push_back(src);
throwALerror();
mFreeSources.push_back(src);
}
} }
} }
catch(std::exception &e) catch(std::exception &e)
@ -602,10 +607,8 @@ void OpenAL_Output::bufferFinished(ALuint buf)
} }
SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, bool loop) SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, int flags)
{ {
throwALerror();
boost::shared_ptr<OpenAL_Sound> sound; boost::shared_ptr<OpenAL_Sound> sound;
ALuint src=0, buf=0; ALuint src=0, buf=0;
@ -640,7 +643,7 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float
alSourcef(src, AL_PITCH, pitch); alSourcef(src, AL_PITCH, pitch);
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE)); alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE);
throwALerror(); throwALerror();
alSourcei(src, AL_BUFFER, buf); alSourcei(src, AL_BUFFER, buf);
@ -650,11 +653,9 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float
return sound; return sound;
} }
SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos, float volume, float pitch, SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch,
float min, float max, bool loop) float min, float max, int flags)
{ {
throwALerror();
boost::shared_ptr<OpenAL_Sound> sound; boost::shared_ptr<OpenAL_Sound> sound;
ALuint src=0, buf=0; ALuint src=0, buf=0;
@ -666,7 +667,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
try try
{ {
buf = getBuffer(fname); buf = getBuffer(fname);
sound.reset(new OpenAL_Sound(*this, src, buf)); sound.reset(new OpenAL_Sound3D(*this, src, buf));
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@ -677,7 +678,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
throw; throw;
} }
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]); alSource3f(src, AL_POSITION, pos.x, pos.z, -pos.y);
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
@ -685,11 +686,12 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
alSourcef(src, AL_MAX_DISTANCE, max); alSourcef(src, AL_MAX_DISTANCE, max);
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f); alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
alSourcef(src, AL_GAIN, volume); alSourcef(src, AL_GAIN, (pos.squaredDistance(mPos) > max*max) ?
0.0f : volume);
alSourcef(src, AL_PITCH, pitch); alSourcef(src, AL_PITCH, pitch);
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE); alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE)); alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE);
throwALerror(); throwALerror();
alSourcei(src, AL_BUFFER, buf); alSourcei(src, AL_BUFFER, buf);
@ -702,8 +704,6 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch) SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch)
{ {
throwALerror();
boost::shared_ptr<OpenAL_SoundStream> sound; boost::shared_ptr<OpenAL_SoundStream> sound;
ALuint src; ALuint src;
@ -743,61 +743,21 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa
return sound; return sound;
} }
SoundPtr OpenAL_Output::streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
float min, float max) void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir)
{ {
throwALerror(); mPos = pos;
boost::shared_ptr<OpenAL_SoundStream> sound; if(mContext)
ALuint src;
if(mFreeSources.empty())
fail("No free sources");
src = mFreeSources.front();
mFreeSources.pop_front();
try
{ {
DecoderPtr decoder = mManager.getDecoder(); ALfloat orient[6] = {
decoder->open(fname); atdir.x, atdir.z, -atdir.y,
sound.reset(new OpenAL_SoundStream(*this, src, decoder)); updir.x, updir.z, -updir.y
};
alListener3f(AL_POSITION, mPos.x, mPos.z, -mPos.y);
alListenerfv(AL_ORIENTATION, orient);
throwALerror();
} }
catch(std::exception &e)
{
mFreeSources.push_back(src);
throw;
}
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
alSourcef(src, AL_REFERENCE_DISTANCE, min);
alSourcef(src, AL_MAX_DISTANCE, max);
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
alSourcef(src, AL_GAIN, volume);
alSourcef(src, AL_PITCH, pitch);
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
alSourcei(src, AL_LOOPING, AL_FALSE);
throwALerror();
sound->play();
return sound;
}
void OpenAL_Output::updateListener(const float *pos, const float *atdir, const float *updir)
{
float orient[6] = {
atdir[0], atdir[2], -atdir[1],
updir[0], updir[2], -updir[1]
};
alListener3f(AL_POSITION, pos[0], pos[2], -pos[1]);
alListenerfv(AL_ORIENTATION, orient);
throwALerror();
} }

View file

@ -40,15 +40,12 @@ namespace MWSound
virtual void init(const std::string &devname=""); virtual void init(const std::string &devname="");
virtual void deinit(); virtual void deinit();
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, bool loop); virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags);
virtual SoundPtr playSound3D(const std::string &fname, const float *pos, float volume, float pitch, virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
float min, float max, bool loop); float volume, float pitch, float min, float max, int flags);
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch); virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch);
virtual SoundPtr streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
float min, float max);
virtual void updateListener(const float *pos, const float *atdir, const float *updir); virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir);
OpenAL_Output& operator=(const OpenAL_Output &rhs); OpenAL_Output& operator=(const OpenAL_Output &rhs);
OpenAL_Output(const OpenAL_Output &rhs); OpenAL_Output(const OpenAL_Output &rhs);
@ -60,6 +57,7 @@ namespace MWSound
std::auto_ptr<StreamThread> mStreamThread; std::auto_ptr<StreamThread> mStreamThread;
friend class OpenAL_Sound; friend class OpenAL_Sound;
friend class OpenAL_Sound3D;
friend class OpenAL_SoundStream; friend class OpenAL_SoundStream;
friend class SoundManager; friend class SoundManager;
}; };

View file

@ -1,30 +1,37 @@
#ifndef GAME_SOUND_SOUND_H #ifndef GAME_SOUND_SOUND_H
#define GAME_SOUND_SOUND_H #define GAME_SOUND_SOUND_H
#include <OgreVector3.h>
namespace MWSound namespace MWSound
{ {
class Sound class Sound
{ {
virtual void update(const float *pos) = 0; virtual void update() = 0;
Sound& operator=(const Sound &rhs); Sound& operator=(const Sound &rhs);
Sound(const Sound &rhs); Sound(const Sound &rhs);
protected: protected:
Ogre::Vector3 mPos;
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */ float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
float mBaseVolume; float mBaseVolume;
float mMinDistance; float mMinDistance;
float mMaxDistance; float mMaxDistance;
int mFlags;
public: public:
virtual void stop() = 0; virtual void stop() = 0;
virtual bool isPlaying() = 0; virtual bool isPlaying() = 0;
virtual void setVolume(float volume) = 0; void setPosition(const Ogre::Vector3 &pos) { mPos = pos; }
void setVolume(float volume) { mVolume = volume; }
Sound() : mVolume(1.0f) Sound() : mPos(0.0f, 0.0f, 0.0f)
, mVolume(1.0f)
, mBaseVolume(1.0f) , mBaseVolume(1.0f)
, mMinDistance(20.0f) /* 1 * min_range_scale */ , mMinDistance(20.0f) /* 1 * min_range_scale */
, mMaxDistance(12750.0f) /* 255 * max_range_scale */ , mMaxDistance(12750.0f) /* 255 * max_range_scale */
, mFlags(Play_Normal)
{ } { }
virtual ~Sound() { } virtual ~Sound() { }

View file

@ -4,6 +4,8 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <OgreVector3.h>
#include "soundmanager.hpp" #include "soundmanager.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -22,19 +24,23 @@ namespace MWSound
virtual void init(const std::string &devname="") = 0; virtual void init(const std::string &devname="") = 0;
virtual void deinit() = 0; virtual void deinit() = 0;
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, bool loop) = 0; virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0;
virtual SoundPtr playSound3D(const std::string &fname, const float *pos, float volume, float pitch, virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
float min, float max, bool loop) = 0; float volume, float pitch, float min, float max, int flags) = 0;
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch) = 0; virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch) = 0;
virtual SoundPtr streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
float min, float max) = 0;
virtual void updateListener(const float *pos, const float *atdir, const float *updir) = 0; virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir) = 0;
Sound_Output& operator=(const Sound_Output &rhs); Sound_Output& operator=(const Sound_Output &rhs);
Sound_Output(const Sound_Output &rhs); Sound_Output(const Sound_Output &rhs);
Sound_Output(SoundManager &mgr) : mManager(mgr) { } protected:
Ogre::Vector3 mPos;
Sound_Output(SoundManager &mgr)
: mManager(mgr)
, mPos(0.0f, 0.0f, 0.0f)
{ }
public: public:
virtual ~Sound_Output() { } virtual ~Sound_Output() { }

View file

@ -41,6 +41,8 @@ namespace MWSound
SoundManager::SoundManager(bool useSound, MWWorld::Environment& environment) SoundManager::SoundManager(bool useSound, MWWorld::Environment& environment)
: mResourceMgr(Ogre::ResourceGroupManager::getSingleton()) : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
, mEnvironment(environment) , mEnvironment(environment)
, mOutput(new DEFAULT_OUTPUT(*this))
{ {
if(!useSound) if(!useSound)
return; return;
@ -50,8 +52,6 @@ namespace MWSound
try try
{ {
mOutput.reset(new DEFAULT_OUTPUT(*this));
std::vector<std::string> names = mOutput->enumerate(); std::vector<std::string> names = mOutput->enumerate();
std::cout <<"Enumerated output devices:"<< std::endl; std::cout <<"Enumerated output devices:"<< std::endl;
for(size_t i = 0;i < names.size();i++) for(size_t i = 0;i < names.size();i++)
@ -62,8 +62,6 @@ namespace MWSound
catch(std::exception &e) catch(std::exception &e)
{ {
std::cout <<"Sound init failed: "<<e.what()<< std::endl; std::cout <<"Sound init failed: "<<e.what()<< std::endl;
mOutput.reset();
return;
} }
} }
@ -108,7 +106,7 @@ namespace MWSound
max = std::max(min, max); max = std::max(min, max);
} }
return std::string("Sound/")+snd->sound; return "Sound/"+snd->sound;
} }
@ -182,11 +180,13 @@ namespace MWSound
{ {
// The range values are not tested // The range values are not tested
float basevol = 1.0f; /* TODO: volume settings */ float basevol = 1.0f; /* TODO: volume settings */
std::string filePath = std::string("Sound/")+filename; std::string filePath = "Sound/"+filename;
const ESM::Position &pos = ptr.getCellRef().pos; const ESM::Position &pos = ptr.getCellRef().pos;
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
SoundPtr sound = mOutput->playSound3D(filePath, pos.pos, basevol, 1.0f, SoundPtr sound = mOutput->playSound3D(filePath, objpos, basevol, 1.0f,
20.0f, 12750.0f, false); 20.0f, 12750.0f, Play_Normal);
sound->mPos = objpos;
sound->mBaseVolume = basevol; sound->mBaseVolume = basevol;
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
@ -203,7 +203,7 @@ namespace MWSound
} }
SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, bool loop) SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode)
{ {
SoundPtr sound; SoundPtr sound;
try try
@ -212,11 +212,12 @@ namespace MWSound
float min, max; float min, max;
std::string file = lookup(soundId, basevol, min, max); std::string file = lookup(soundId, basevol, min, max);
sound = mOutput->playSound(file, volume*basevol, pitch, loop); sound = mOutput->playSound(file, volume*basevol, pitch, mode);
sound->mVolume = volume; sound->mVolume = volume;
sound->mBaseVolume = basevol; sound->mBaseVolume = basevol;
sound->mMinDistance = min; sound->mMinDistance = min;
sound->mMaxDistance = max; sound->mMaxDistance = max;
sound->mFlags = mode;
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
} }
@ -228,8 +229,7 @@ namespace MWSound
} }
SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId, SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId,
float volume, float pitch, bool loop, float volume, float pitch, int mode)
bool untracked)
{ {
SoundPtr sound; SoundPtr sound;
try try
@ -239,15 +239,20 @@ namespace MWSound
float min, max; float min, max;
std::string file = lookup(soundId, basevol, min, max); std::string file = lookup(soundId, basevol, min, max);
const ESM::Position &pos = ptr.getCellRef().pos; const ESM::Position &pos = ptr.getCellRef().pos;
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
sound = mOutput->playSound3D(file, pos.pos, volume*basevol, pitch, min, max, loop); sound = mOutput->playSound3D(file, objpos, volume*basevol, pitch, min, max, mode);
sound->mPos = objpos;
sound->mVolume = volume; sound->mVolume = volume;
sound->mBaseVolume = basevol; sound->mBaseVolume = basevol;
sound->mMinDistance = min; sound->mMinDistance = min;
sound->mMaxDistance = max; sound->mMaxDistance = max;
sound->mFlags = mode;
mActiveSounds[sound] = (!untracked ? std::make_pair(ptr, soundId) : if((mode&Play_NoTrack))
std::make_pair(MWWorld::Ptr(), soundId)); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
else
mActiveSounds[sound] = std::make_pair(ptr, soundId);
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@ -326,11 +331,12 @@ namespace MWSound
void SoundManager::updateObject(MWWorld::Ptr ptr) void SoundManager::updateObject(MWWorld::Ptr ptr)
{ {
const ESM::Position &pos = ptr.getCellRef().pos; const ESM::Position &pos = ptr.getCellRef().pos;
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
SoundMap::iterator snditer = mActiveSounds.begin(); SoundMap::iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end()) while(snditer != mActiveSounds.end())
{ {
if(snditer->second.first == ptr) if(snditer->second.first == ptr)
snditer->first->update(pos.pos); snditer->first->setPosition(objpos);
snditer++; snditer++;
} }
} }
@ -411,9 +417,9 @@ namespace MWSound
// The output handler is expecting vectors oriented like the game // The output handler is expecting vectors oriented like the game
// (that is, -Z goes down, +Y goes forward), but that's not what we // (that is, -Z goes down, +Y goes forward), but that's not what we
// get from Ogre's camera, so we have to convert. // get from Ogre's camera, so we have to convert.
float pos[3] = { nPos[0], -nPos[2], nPos[1] }; const Ogre::Vector3 pos(nPos[0], -nPos[2], nPos[1]);
float at[3] = { nDir[0], -nDir[2], nDir[1] }; const Ogre::Vector3 at(nDir[0], -nDir[2], nDir[1]);
float up[3] = { nUp[0], -nUp[2], nUp[1] }; const Ogre::Vector3 up(nUp[0], -nUp[2], nUp[1]);
mOutput->updateListener(pos, at, up); mOutput->updateListener(pos, at, up);
// Check if any sounds are finished playing, and trash them // Check if any sounds are finished playing, and trash them
@ -423,7 +429,10 @@ namespace MWSound
if(!snditer->first->isPlaying()) if(!snditer->first->isPlaying())
mActiveSounds.erase(snditer++); mActiveSounds.erase(snditer++);
else else
{
snditer->first->update();
snditer++; snditer++;
}
} }
} }

View file

@ -30,6 +30,19 @@ namespace MWSound
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr; typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
typedef boost::shared_ptr<Sound> SoundPtr; typedef boost::shared_ptr<Sound> SoundPtr;
enum PlayMode {
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
* but do not keep it updated (the sound will not move with
* the object and will not stop when the object is deleted. */
};
static inline int operator|(const PlayMode &a, const PlayMode &b)
{ return (int)a | (int)b; }
static inline int operator&(const PlayMode &a, const PlayMode &b)
{ return (int)a & (int)b; }
class SoundManager class SoundManager
{ {
Ogre::ResourceGroupManager& mResourceMgr; Ogre::ResourceGroupManager& mResourceMgr;
@ -87,12 +100,11 @@ namespace MWSound
bool sayDone(MWWorld::Ptr reference) const; bool sayDone(MWWorld::Ptr reference) const;
///< Is actor not speaking? ///< Is actor not speaking?
SoundPtr playSound(const std::string& soundId, float volume, float pitch, bool loop=false); SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal);
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, bool loop, float volume, float pitch, int mode=Play_Normal);
bool untracked=false);
///< Play a sound from an object ///< Play a sound from an object
void stopSound3D(MWWorld::Ptr reference, const std::string& soundId); void stopSound3D(MWWorld::Ptr reference, const std::string& soundId);

View file

@ -45,6 +45,20 @@ struct ciLessBoost : std::binary_function<std::string, std::string, bool>
} }
}; };
struct pathComparer
{
private:
int m_start, m_size;
public:
pathComparer(int start, int size) : m_start(start), m_size(size) { }
bool operator() (const std::string& first, const std::string& other)
{
return lexicographical_compare(first.substr(m_start,m_size), other.substr(m_start,m_size), boost::algorithm::is_iless());
}
};
static bool fsstrict = false; static bool fsstrict = false;
/// An OGRE Archive wrapping a BSAFile archive /// An OGRE Archive wrapping a BSAFile archive
@ -55,16 +69,62 @@ class DirArchive: public Ogre::FileSystemArchive
std::map<std::string, std::vector<std::string>, ciLessBoost> m; std::map<std::string, std::vector<std::string>, ciLessBoost> m;
unsigned int cutoff; unsigned int cutoff;
bool comparePortion(std::string file1, std::string file2, int start, int size) const bool findFile(const String& filename, std::string& copy) const
{ {
for(int i = start; i < start+size; i++) if (filename.find(".tga") != std::string::npos)
return false;
{ {
char one = file1.at(i); String passed = filename;
char two = file2.at(i); if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
if(tolower(one) != tolower(two) ) || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
return false; || filename.at(filename.length() - 1) == '|')
{
passed = filename.substr(0, filename.length() - 2);
}
if(filename.at(filename.length() - 2) == '>')
passed = filename.substr(0, filename.length() - 6);
copy = passed;
} }
return true;
std::replace(copy.begin(), copy.end(), '\\', '/');
if(copy.at(0) == '/')
copy.erase(0, 1);
if(fsstrict == true)
return true;
std::string folder;
int delimiter = 0;
size_t lastSlash = copy.rfind('/');
if (lastSlash != std::string::npos)
{
folder = copy.substr(0, lastSlash);
delimiter = lastSlash+1;
}
std::vector<std::string> current;
{
std::map<std::string,std::vector<std::string>,ciLessBoost>::const_iterator found = m.find(folder);
if (found == m.end())
{
return false;
}
else
current = found->second;
}
pathComparer comp(delimiter, copy.size() - delimiter-1);
std::vector<std::string>::iterator find = std::lower_bound(current.begin(), current.end(), copy, comp);
if (find != current.end() && !comp(copy, current.front()))
{
copy = *find;
return true;
}
return false;
} }
public: public:
@ -83,16 +143,14 @@ class DirArchive: public Ogre::FileSystemArchive
//need to cut off first //need to cut off first
boost::filesystem::directory_iterator dir_iter(d), dir_end; boost::filesystem::directory_iterator dir_iter(d), dir_end;
std::vector<std::string> filesind; std::vector<std::string> filesind;
boost::filesystem::path f;
for(;dir_iter != dir_end; dir_iter++) for(;dir_iter != dir_end; dir_iter++)
{ {
if(boost::filesystem::is_directory(*dir_iter)) if(boost::filesystem::is_directory(*dir_iter))
populateMap(*dir_iter); populateMap(*dir_iter);
else else
{ {
std::string s = dir_iter->path().string();
f = *dir_iter; std::replace(s.begin(), s.end(), '\\', '/');
std::string s = f.string();
std::string small; std::string small;
if(cutoff < s.size()) if(cutoff < s.size())
@ -103,14 +161,17 @@ class DirArchive: public Ogre::FileSystemArchive
filesind.push_back(small); filesind.push_back(small);
} }
} }
std::sort(filesind.begin(), filesind.end(), ciLessBoost());
std::string small; std::string small;
std::string original = d.string(); std::string original = d.string();
std::replace(original.begin(), original.end(), '\\', '/');
if(cutoff < original.size()) if(cutoff < original.size())
small = original.substr(cutoff, original.size() - cutoff); small = original.substr(cutoff, original.size() - cutoff);
else else
small = original.substr(cutoff - 1, original.size() - cutoff); small = original.substr(cutoff - 1, original.size() - cutoff);
m[small] = filesind;
m[small] = filesind;
} }
bool isCaseSensitive() const { return fsstrict; } bool isCaseSensitive() const { return fsstrict; }
@ -120,97 +181,21 @@ class DirArchive: public Ogre::FileSystemArchive
void unload() {} void unload() {}
bool exists(const String& filename) { bool exists(const String& filename) {
std::string copy = filename; std::string copy;
if (findFile(filename, copy))
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
//std::cout << "fsstrict " << copy << "\n";
return FileSystemArchive::exists(copy); return FileSystemArchive::exists(copy);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string>& current = m[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::exists(*iter);
}
}
return false; return false;
} }
DataStreamPtr open(const String& filename, bool readonly = true) const DataStreamPtr open(const String& filename, bool readonly = true) const
{ {
std::map<std::string, std::vector<std::string>, ciLessBoost> mlocal = m; std::string copy;
std::string copy = filename;
if (findFile(filename, copy))
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
return FileSystemArchive::open(copy, readonly); return FileSystemArchive::open(copy, readonly);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string> current = mlocal[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::open(*iter, readonly);
}
}
DataStreamPtr p; DataStreamPtr p;
return p; return p;
} }
@ -261,7 +246,7 @@ bool exists(const String& filename) {
} }
// Check if the file exists. // Check if the file exists.
bool cexists(const String& filename) const { bool cexists(const String& filename) const {
String passed = filename; String passed = filename;
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
@ -272,7 +257,7 @@ bool exists(const String& filename) {
if(filename.at(filename.length() - 2) == '>') if(filename.at(filename.length() - 2) == '>')
passed = filename.substr(0, filename.length() - 6); passed = filename.substr(0, filename.length() - 6);
return arc.exists(passed.c_str()); return arc.exists(passed.c_str());
} }
time_t getModifiedTime(const String&) { return 0; } time_t getModifiedTime(const String&) { return 0; }

View file

@ -30,4 +30,9 @@ namespace Files
return iter->second; return iter->second;
} }
const Files::PathContainer& Collections::getPaths() const
{
return mDirectories;
}
} }

View file

@ -21,6 +21,8 @@ namespace Files
/// leading dot and must be all lower-case. /// leading dot and must be all lower-case.
const MultiDirCollection& getCollection(const std::string& extension) const; const MultiDirCollection& getCollection(const std::string& extension) const;
const Files::PathContainer& getPaths() const;
private: private:
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer; typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
Files::PathContainer mDirectories; Files::PathContainer mDirectories;

View file

@ -1368,7 +1368,7 @@ void NIFLoader::loadResource(Resource *resource)
if (!vfs->isFile(resourceName)) if (!vfs->isFile(resourceName))
{ {
warn("File not found."); warn("File "+resourceName+" not found.");
return; return;
} }

Binary file not shown.

View file

@ -151,7 +151,8 @@ namespace Physic
PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) :
mDebugActive(0)
{ {
// Set up the collision configuration and dispatcher // Set up the collision configuration and dispatcher
collisionConfiguration = new btDefaultCollisionConfiguration(); collisionConfiguration = new btDefaultCollisionConfiguration();
@ -203,6 +204,13 @@ namespace Physic
createDebugRendering(); createDebugRendering();
} }
mDebugDrawer->setDebugMode(mode); mDebugDrawer->setDebugMode(mode);
mDebugActive = mode;
}
bool PhysicEngine::toggleDebugRendering()
{
setDebugRenderingMode(!mDebugActive);
return mDebugActive;
} }
PhysicEngine::~PhysicEngine() PhysicEngine::~PhysicEngine()

View file

@ -199,6 +199,8 @@ namespace Physic
*/ */
void setDebugRenderingMode(int mode); void setDebugRenderingMode(int mode);
bool toggleDebugRendering();
/** /**
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1). * Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
*/ */
@ -235,6 +237,7 @@ namespace Physic
//debug rendering //debug rendering
BtOgre::DebugDrawer* mDebugDrawer; BtOgre::DebugDrawer* mDebugDrawer;
bool isDebugCreated; bool isDebugCreated;
bool mDebugActive;
}; };