Converted sound effects file to XML. Along the way, refactored the audio code to be more flexible. before, when a sound changed, you needed to edit the config file of STK, edit the enum in the header, edit the loader in the .cpp... was annoying. Now you only need to edit the config file.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4728 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
b167931b9c
commit
93cc5209f7
@ -53,11 +53,7 @@ SFXManager::SFXManager()
|
||||
// The sound manager initialises OpenAL
|
||||
m_initialized = sound_manager->initialized();
|
||||
m_masterGain = 1.0f;
|
||||
m_sfx_buffers.resize(NUM_SOUNDS);
|
||||
m_sfx_positional.resize(NUM_SOUNDS);
|
||||
m_sfx_rolloff.resize(NUM_SOUNDS);
|
||||
m_sfx_gain.resize(NUM_SOUNDS);
|
||||
if(!m_initialized) return;
|
||||
if (!m_initialized) return;
|
||||
|
||||
loadSfx();
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
@ -67,19 +63,34 @@ SFXManager::SFXManager()
|
||||
//-----------------------------------------------------------------------------
|
||||
SFXManager::~SFXManager()
|
||||
{
|
||||
//make sure there aren't any stray sfx's sitting around anywhere
|
||||
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
// ---- clear m_all_sfx
|
||||
const int sfxAmount = m_all_sfx.size();
|
||||
for (int n=0; n<sfxAmount; n++)
|
||||
{
|
||||
delete (*i);
|
||||
} // for i in m_all_sfx
|
||||
delete m_all_sfx[n];
|
||||
}
|
||||
m_all_sfx.clear();
|
||||
|
||||
//the unbuffer all of the buffers
|
||||
for(unsigned int ii = 0; ii != m_sfx_buffers.size(); ii++)
|
||||
// ---- clear m_quick_sounds
|
||||
{
|
||||
alDeleteBuffers(1, &(m_sfx_buffers[ii]));
|
||||
}
|
||||
std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.begin();
|
||||
for (; i != m_quick_sounds.end(); i++)
|
||||
{
|
||||
SFXBase* snd = (*i).second;
|
||||
delete snd;
|
||||
}
|
||||
}
|
||||
m_quick_sounds.clear();
|
||||
|
||||
// ---- clear m_all_sfx_types
|
||||
{
|
||||
std::map<std::string, SFXBufferInfo>::iterator i = m_all_sfx_types.begin();
|
||||
for (; i != m_all_sfx_types.end(); i++)
|
||||
{
|
||||
(*i).second.freeBuffer();
|
||||
}
|
||||
m_all_sfx_types.clear();
|
||||
}
|
||||
|
||||
sfx_manager = NULL;
|
||||
} // ~SFXManager
|
||||
@ -97,56 +108,35 @@ bool SFXManager::sfxAllowed()
|
||||
*/
|
||||
void SFXManager::loadSfx()
|
||||
{
|
||||
// TODO : implement as XML
|
||||
const lisp::Lisp* root = 0;
|
||||
std::string sfx_config_name = file_manager->getSFXFile("sfx.config");
|
||||
try
|
||||
std::string sfx_config_name = file_manager->getSFXFile("sfx.xml");
|
||||
XMLNode* root = file_manager->createXMLTree(sfx_config_name);
|
||||
if (!root)
|
||||
{
|
||||
lisp::Parser parser;
|
||||
root = parser.parse(sfx_config_name);
|
||||
std::cerr << "Could not read sounf effects XML file " << sfx_config_name.c_str() << std::endl;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
|
||||
const int amount = root->getNumNodes();
|
||||
for (int i=0; i<amount; i++)
|
||||
{
|
||||
(void)e; // avoid warning about unreferenced local variable
|
||||
std::ostringstream msg;
|
||||
msg << "Sfx config file '" << sfx_config_name
|
||||
<< "' does not exist - aborting.\n";
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
|
||||
const lisp::Lisp* lisp = root->getLisp("sfx-config");
|
||||
if(!lisp)
|
||||
{
|
||||
std::string msg="No sfx-config node";
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
loadSingleSfx(lisp, "ugh", SOUND_UGH );
|
||||
loadSingleSfx(lisp, "skid", SOUND_SKID );
|
||||
loadSingleSfx(lisp, "locked", SOUND_LOCKED );
|
||||
loadSingleSfx(lisp, "bowling_roll", SOUND_BOWLING_ROLL );
|
||||
loadSingleSfx(lisp, "bowling_strike",SOUND_BOWLING_STRIKE );
|
||||
loadSingleSfx(lisp, "winner", SOUND_WINNER );
|
||||
loadSingleSfx(lisp, "crash", SOUND_CRASH );
|
||||
loadSingleSfx(lisp, "grab", SOUND_GRAB );
|
||||
loadSingleSfx(lisp, "goo", SOUND_GOO );
|
||||
loadSingleSfx(lisp, "shot", SOUND_SHOT );
|
||||
loadSingleSfx(lisp, "wee", SOUND_WEE );
|
||||
loadSingleSfx(lisp, "explosion", SOUND_EXPLOSION );
|
||||
loadSingleSfx(lisp, "bzzt", SOUND_BZZT );
|
||||
loadSingleSfx(lisp, "beep", SOUND_BEEP );
|
||||
loadSingleSfx(lisp, "back_menu", SOUND_BACK_MENU );
|
||||
loadSingleSfx(lisp, "use_anvil", SOUND_USE_ANVIL );
|
||||
loadSingleSfx(lisp, "use_parachute", SOUND_USE_PARACHUTE );
|
||||
loadSingleSfx(lisp, "select_menu", SOUND_SELECT_MENU );
|
||||
loadSingleSfx(lisp, "move_menu", SOUND_MOVE_MENU );
|
||||
loadSingleSfx(lisp, "full", SOUND_FULL );
|
||||
loadSingleSfx(lisp, "prestart", SOUND_PRESTART );
|
||||
loadSingleSfx(lisp, "start", SOUND_START );
|
||||
loadSingleSfx(lisp, "swap", SOUND_SWAP );
|
||||
|
||||
loadSingleSfx(lisp, "engine_small", SOUND_ENGINE_SMALL );
|
||||
loadSingleSfx(lisp, "engine_large", SOUND_ENGINE_LARGE );
|
||||
} // loadSfx
|
||||
const XMLNode* node = root->getNode(i);
|
||||
|
||||
if (node->getName() == "sfx-config")
|
||||
{
|
||||
// outer node, ignore
|
||||
}
|
||||
else if (node->getName() == "sfx")
|
||||
{
|
||||
loadSingleSfx(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown node in sfx XML file : " << node->getName().c_str() << std::endl;
|
||||
throw std::runtime_error("Unknown node in sfx XML file");
|
||||
}
|
||||
}// nend for
|
||||
|
||||
delete root;
|
||||
} // loadSfx
|
||||
//----------------------------------------------------------------------------
|
||||
/** Load a vorbis file into an OpenAL buffer
|
||||
based on a routine by Peter Mulholland, used with permission (quote : "Feel free to use")
|
||||
@ -226,7 +216,7 @@ getCustomTagName(int id)
|
||||
I'm just too stupid with C++ to figure it out. The switch code is
|
||||
less then ideal.
|
||||
*/
|
||||
|
||||
/*
|
||||
const char *SFXManager::getCustomTagName(int id)
|
||||
{
|
||||
switch (id)
|
||||
@ -244,7 +234,7 @@ const char *SFXManager::getCustomTagName(int id)
|
||||
};
|
||||
return "";
|
||||
} // getCustomTagName
|
||||
|
||||
*/
|
||||
/*
|
||||
|
||||
addSingleSfx()
|
||||
@ -254,100 +244,153 @@ addSingleSfx()
|
||||
individual karts (character voices) so that we can avoid creating an
|
||||
enumeration for each effect, for each kart.
|
||||
|
||||
sfxFile must be an absolute pathname, so get that straight first.
|
||||
\param sfxFile must be an absolute pathname
|
||||
\return whether loading this sound effect was successful
|
||||
|
||||
*/
|
||||
int SFXManager::addSingleSfx(std::string sfxFile,
|
||||
int positional,
|
||||
float rolloff,
|
||||
float gain)
|
||||
/* Returns sfx ID or -1 on error*/
|
||||
bool SFXManager::addSingleSfx(const char* sfx_name,
|
||||
std::string sfxFile,
|
||||
bool positional,
|
||||
float rolloff,
|
||||
float gain)
|
||||
{
|
||||
int sfxID;
|
||||
std::string filename;
|
||||
|
||||
SFXBufferInfo sfxInfo;
|
||||
|
||||
|
||||
m_sfx_buffers.push_back(0);
|
||||
sfxID = m_sfx_buffers.size() - 1;
|
||||
|
||||
/* FIXME: Check for existance of file before resizing vectors */
|
||||
|
||||
m_sfx_rolloff.push_back(rolloff);
|
||||
m_sfx_positional.push_back(positional);
|
||||
m_sfx_gain.push_back(gain);
|
||||
|
||||
alGenBuffers(1, &(m_sfx_buffers[sfxID]));
|
||||
if (!checkError("generating a buffer")) return -1;
|
||||
|
||||
if (!loadVorbisBuffer(sfxFile.c_str(), m_sfx_buffers[sfxID]))
|
||||
sfxInfo.m_sfx_rolloff = rolloff;
|
||||
sfxInfo.m_sfx_positional = positional;
|
||||
sfxInfo.m_sfx_gain = gain;
|
||||
|
||||
printf("Loading SFX %s\n", sfxFile.c_str());
|
||||
|
||||
alGetError(); // clear errors from previously
|
||||
|
||||
alGenBuffers(1, &sfxInfo.m_sfx_buffer);
|
||||
if (!checkError("generating a buffer"))
|
||||
{
|
||||
printf("Failed to load sound effect %s\n", sfxFile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// debugging
|
||||
/*printf("addSingleSfx() id:%d sfxFile:%s\n", sfxID, sfxFile.c_str());*/
|
||||
|
||||
return sfxID;
|
||||
|
||||
if (!loadVorbisBuffer(sfx_name, sfxInfo.m_sfx_buffer))
|
||||
{
|
||||
fprintf(stderr, "Could not load sound effect %s\n", sfx_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_all_sfx_types[sfx_name] = sfxInfo;
|
||||
|
||||
return true;
|
||||
} // addSingleSFX
|
||||
|
||||
void SFXManager::loadSingleSfx(const lisp::Lisp* lisp,
|
||||
const char *name, int item)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void SFXManager::loadSingleSfx(const XMLNode* node)
|
||||
{
|
||||
if (item < 0 || item >= (int)m_sfx_gain.size())
|
||||
std::string filename;
|
||||
std::string sfx_name;
|
||||
|
||||
SFXBufferInfo sfxInfo;
|
||||
|
||||
if (node->get("filename", &filename) == 0)
|
||||
{
|
||||
printf("loadSingleSfx: Invalid SFX ID.\n");
|
||||
fprintf(stderr, "/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->get("name", &sfx_name) == 0)
|
||||
{
|
||||
fprintf(stderr, "/!\\ The 'name' attribute is mandatory in the SFX XML file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
node->get("rolloff", &sfxInfo.m_sfx_rolloff );
|
||||
node->get("positional", &sfxInfo.m_sfx_positional );
|
||||
node->get("volume", &sfxInfo.m_sfx_gain );
|
||||
|
||||
const lisp::Lisp* sfxLisp = lisp->getLisp(name);
|
||||
std::string wav; float rolloff = 0.1f; float gain = 1.0f; int positional = 0;
|
||||
|
||||
sfxLisp->get("filename", wav );
|
||||
sfxLisp->get("roll-off", rolloff );
|
||||
sfxLisp->get("positional", positional );
|
||||
sfxLisp->get("volume", gain );
|
||||
|
||||
m_sfx_rolloff[item] = rolloff;
|
||||
m_sfx_positional[item] = positional;
|
||||
m_sfx_gain[item] = gain;
|
||||
|
||||
std::string path = file_manager->getSFXFile(wav);
|
||||
std::string path = file_manager->getSFXFile(filename);
|
||||
printf("Loading SFX %s\n", path.c_str());
|
||||
|
||||
alGenBuffers(1, &(m_sfx_buffers[item]));
|
||||
alGenBuffers(1, &sfxInfo.m_sfx_buffer);
|
||||
if (!checkError("generating a buffer")) return;
|
||||
|
||||
if(!loadVorbisBuffer(path.c_str(), m_sfx_buffers[item]))
|
||||
assert( alIsBuffer(sfxInfo.m_sfx_buffer) );
|
||||
|
||||
if (!loadVorbisBuffer(path.c_str(), sfxInfo.m_sfx_buffer))
|
||||
{
|
||||
printf("Could not load sound effect %s\n", name);
|
||||
fprintf(stderr, "Could not load sound effect %s\n", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//printf(">>>>>> Addind sound effect '%s' to the map\n", sfx_name.c_str());
|
||||
|
||||
m_all_sfx_types[sfx_name.c_str()] = sfxInfo;
|
||||
|
||||
assert( alIsBuffer(m_all_sfx_types[sfx_name.c_str()].m_sfx_buffer) );
|
||||
|
||||
/*
|
||||
std::map<std::string, SFXBufferInfo>::iterator i = m_all_sfx_types.begin();
|
||||
for (; i != m_all_sfx_types.end(); i++ )
|
||||
{
|
||||
printf(" got '%s', buffer is %i\n", i->first.c_str(), i->second.m_sfx_buffer);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} // loadSingleSfx
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Creates a new SFX object. The memory for this object is managed completely
|
||||
* by the SFXManager. This makes it easy to use different implementations of
|
||||
* SFX - since newSFX can return whatever type is used. To free the memory,
|
||||
* SFX - since createSoundSource can return whatever type is used. To free the memory,
|
||||
* call deleteSFX().
|
||||
* \param id Identifier of the sound effect to create.
|
||||
*/
|
||||
SFXBase *SFXManager::newSFX(int id)
|
||||
SFXBase* SFXManager::createSoundSource(const SFXBufferInfo& info, const bool addToSFXList)
|
||||
{
|
||||
bool positional = false;
|
||||
|
||||
if (id < 0 || id >= (int)m_sfx_gain.size())
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
printf("newSFX: Invalid SFX ID %d.\n", id);
|
||||
return NULL;
|
||||
positional = info.m_sfx_positional;
|
||||
}
|
||||
|
||||
if(race_manager->getNumLocalPlayers() < 2)
|
||||
positional = m_sfx_positional[id]!=0;
|
||||
assert( alIsBuffer(info.m_sfx_buffer) );
|
||||
|
||||
SFXBase *p = new SFXOpenAL(m_sfx_buffers[id], positional, m_sfx_rolloff[id], m_sfx_gain[id]);
|
||||
SFXBase* sfx = new SFXOpenAL(info.m_sfx_buffer, positional, info.m_sfx_rolloff, info.m_sfx_gain);
|
||||
|
||||
// debugging
|
||||
/*printf("newSfx(): id:%d buffer:%p, rolloff:%f, gain:%f %p\n", id, m_sfx_buffers[id], m_sfx_rolloff[id], m_sfx_gain[id], p);*/
|
||||
p->volume(m_masterGain);
|
||||
m_all_sfx.push_back(p);
|
||||
return p;
|
||||
} // newSFX
|
||||
|
||||
sfx->volume(m_masterGain);
|
||||
|
||||
if (addToSFXList) m_all_sfx.push_back(sfx);
|
||||
|
||||
return sfx;
|
||||
} // createSoundSource
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
SFXBase* SFXManager::createSoundSource(const char* name, const bool addToSFXList)
|
||||
{
|
||||
std::map<std::string, SFXBufferInfo>::iterator i = m_all_sfx_types.find(name);
|
||||
if ( i == m_all_sfx_types.end() )
|
||||
{
|
||||
fprintf( stderr, "SFXManager::createSoundSource could not find the requested sound effect : '%s'\n", name);
|
||||
|
||||
/*
|
||||
std::map<std::string, SFXBufferInfo>::iterator it = m_all_sfx_types.begin();
|
||||
for (; it != m_all_sfx_types.end(); it++ )
|
||||
{
|
||||
printf(" got '%s'\n", it->first.c_str());
|
||||
}*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return createSoundSource( i->second, addToSFXList );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Delete a sound effect object, and removes it from the internal list of
|
||||
@ -379,7 +422,7 @@ void SFXManager::deleteSFX(SFXBase *sfx)
|
||||
*/
|
||||
void SFXManager::pauseAll()
|
||||
{
|
||||
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
{
|
||||
(*i)->pause();
|
||||
@ -390,13 +433,12 @@ void SFXManager::pauseAll()
|
||||
*/
|
||||
void SFXManager::resumeAll()
|
||||
{
|
||||
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
{
|
||||
SFXStatus status = (*i)->getStatus();
|
||||
// Initial happens when
|
||||
if(status==SFX_PAUSED)
|
||||
(*i)->resume();
|
||||
if (status==SFX_PAUSED) (*i)->resume();
|
||||
} // for i in m_all_sfx
|
||||
} // resumeAll
|
||||
|
||||
@ -418,19 +460,29 @@ bool SFXManager::checkError(const std::string &context)
|
||||
//-----------------------------------------------------------------------------
|
||||
void SFXManager::setMasterSFXVolume(float gain)
|
||||
{
|
||||
if(gain > 1.0)
|
||||
gain = 1.0f;
|
||||
if(gain < 0.0f)
|
||||
gain = 0.0f;
|
||||
if (gain > 1.0) gain = 1.0f;
|
||||
if (gain < 0.0f) gain = 0.0f;
|
||||
|
||||
m_masterGain = gain;
|
||||
|
||||
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
// regular SFX
|
||||
{
|
||||
(*i)->volume(m_masterGain);
|
||||
} // for i in m_all_sfx
|
||||
|
||||
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
|
||||
i!=m_all_sfx.end(); i++)
|
||||
{
|
||||
(*i)->volume(m_masterGain);
|
||||
} // for i in m_all_sfx
|
||||
}
|
||||
|
||||
// quick SFX
|
||||
{
|
||||
std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.begin();
|
||||
for (; i != m_quick_sounds.end(); i++)
|
||||
{
|
||||
(*i).second->volume(m_masterGain);
|
||||
}
|
||||
}
|
||||
|
||||
} // setMasterSFXVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -449,18 +501,19 @@ const std::string SFXManager::getErrorString(int err)
|
||||
} // getErrorString
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SFXManager::quickSound(SFXType soundType)
|
||||
{
|
||||
static std::map<SFXType, SFXBase*> allSounds;
|
||||
|
||||
std::map<std::string, SFXBase*> SFXManager::m_quick_sounds;
|
||||
|
||||
void SFXManager::quickSound(const char* soundType)
|
||||
{
|
||||
std::map<std::string, SFXBase*>::iterator sound = m_quick_sounds.find(soundType);
|
||||
|
||||
std::map<SFXType, SFXBase*>::iterator sound = allSounds.find(soundType);
|
||||
|
||||
if (sound == allSounds.end())
|
||||
if (sound == m_quick_sounds.end())
|
||||
{
|
||||
// sound not yet in our list
|
||||
SFXBase* newSound = sfx_manager->newSFX(soundType);
|
||||
// sound not yet in our local list of quick sounds
|
||||
SFXBase* newSound = sfx_manager->createSoundSource(soundType, false);
|
||||
newSound->play();
|
||||
allSounds[soundType] = newSound;
|
||||
m_quick_sounds[soundType] = newSound;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define HEADER_SFX_MANAGER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#ifdef __APPLE__
|
||||
# include <OpenAL/al.h>
|
||||
#else
|
||||
@ -31,7 +32,7 @@
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class SFXBase;
|
||||
|
||||
class XMLNode;
|
||||
|
||||
/** Manager of all sound effects. The manager reads all sound effects and
|
||||
* maintains the corresponding buffers. Each sound effect objects uses
|
||||
@ -40,21 +41,11 @@ class SFXBase;
|
||||
class SFXManager
|
||||
{
|
||||
public:
|
||||
/** The different type of sound effects. */
|
||||
enum SFXType
|
||||
{
|
||||
SOUND_UGH, SOUND_SKID, SOUND_BOWLING_ROLL, SOUND_BOWLING_STRIKE, SOUND_WINNER, SOUND_CRASH, SOUND_GRAB,
|
||||
SOUND_SHOT, SOUND_GOO, SOUND_WEE, SOUND_EXPLOSION, SOUND_BZZT, SOUND_BEEP, SOUND_BACK_MENU, SOUND_USE_ANVIL,
|
||||
SOUND_USE_PARACHUTE, SOUND_SELECT_MENU, SOUND_MOVE_MENU, SOUND_FULL, SOUND_LOCKED,
|
||||
SOUND_PRESTART, SOUND_START, SOUND_ENGINE_SMALL, SOUND_ENGINE_LARGE, SOUND_SWAP,
|
||||
NUM_SOUNDS
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Entries for custom SFX sounds. These are unique for each kart.
|
||||
eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN)
|
||||
*/
|
||||
/**
|
||||
* Entries for custom SFX sounds. These are unique for each kart.
|
||||
* eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN)
|
||||
*/
|
||||
enum CustomSFX
|
||||
{
|
||||
CUSTOM_HORN, // Replaces default horn
|
||||
@ -70,10 +61,6 @@ public:
|
||||
NUM_CUSTOMS
|
||||
};
|
||||
|
||||
// LISP (or in the future xml) tag for each custom sound
|
||||
const char *getCustomTagName(int id);
|
||||
|
||||
|
||||
/** Status of a sound effect. */
|
||||
enum SFXStatus
|
||||
{
|
||||
@ -82,32 +69,67 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
/** The buffers for all sound effects. These are shared among all
|
||||
|
||||
class SFXBufferInfo
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ALuint m_sfx_buffer;
|
||||
bool m_sfx_positional;
|
||||
float m_sfx_rolloff;
|
||||
float m_sfx_gain;
|
||||
|
||||
SFXBufferInfo()
|
||||
{
|
||||
m_sfx_buffer = 0;
|
||||
m_sfx_gain = 1.0f;
|
||||
m_sfx_rolloff = 0.1f;
|
||||
m_sfx_positional = false;
|
||||
}
|
||||
|
||||
|
||||
/** Cannot appear in destructor because copy-constructors may be used,
|
||||
* and the OpenAL source must not be deleted on a copy */
|
||||
void freeBuffer()
|
||||
{
|
||||
alDeleteBuffers(1, &m_sfx_buffer);
|
||||
m_sfx_buffer = 0;
|
||||
}
|
||||
~SFXBufferInfo()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** The buffers and info for all sound effects. These are shared among all
|
||||
* instances of SFXOpenal. */
|
||||
std::vector<ALuint> m_sfx_buffers;
|
||||
std::vector<int> m_sfx_positional;
|
||||
std::vector<float> m_sfx_rolloff;
|
||||
std::vector<float> m_sfx_gain;
|
||||
std::vector<SFXBase*> m_all_sfx;
|
||||
std::map<std::string, SFXBufferInfo> m_all_sfx_types;
|
||||
|
||||
/** The actual instances (sound sources) */
|
||||
std::vector<SFXBase*> m_all_sfx;
|
||||
|
||||
/** To play non-positional sounds without having to create a new object for each */
|
||||
static std::map<std::string, SFXBase*> m_quick_sounds;
|
||||
|
||||
bool m_initialized;
|
||||
float m_masterGain;
|
||||
|
||||
void loadSfx();
|
||||
|
||||
void loadSingleSfx(const lisp::Lisp *lisp,
|
||||
const char *name,
|
||||
int type);
|
||||
void loadSingleSfx(const XMLNode* node);
|
||||
|
||||
public:
|
||||
SFXManager();
|
||||
virtual ~SFXManager();
|
||||
bool sfxAllowed();
|
||||
int addSingleSfx( std::string filename,
|
||||
int positional,
|
||||
bool addSingleSfx( const char* sfx_name,
|
||||
std::string filename,
|
||||
bool positional,
|
||||
float rolloff,
|
||||
float gain);
|
||||
|
||||
SFXBase *newSFX(int id);
|
||||
SFXBase* createSoundSource(const SFXBufferInfo& info, const bool addToSFXList=true);
|
||||
SFXBase* createSoundSource(const char* name, const bool addToSFXList=true);
|
||||
|
||||
void deleteSFX(SFXBase *sfx);
|
||||
void pauseAll();
|
||||
void resumeAll();
|
||||
@ -120,7 +142,7 @@ public:
|
||||
|
||||
/** Positional sound is cool, but creating a new object just to play a simple
|
||||
menu sound is not. This function allows for 'quick sounds' in a single call.*/
|
||||
static void quickSound(SFXType soundType);
|
||||
static void quickSound(const char* soundName);
|
||||
|
||||
};
|
||||
|
||||
|
@ -43,18 +43,27 @@ SFXOpenAL::SFXOpenAL(ALuint buffer, bool positional, float rolloff, float gain)
|
||||
m_defaultGain = gain;
|
||||
|
||||
alGenSources(1, &m_soundSource );
|
||||
if(!SFXManager::checkError("generating a source")) return;
|
||||
if (!SFXManager::checkError("generating a source")) return;
|
||||
|
||||
assert( alIsBuffer(m_soundBuffer) );
|
||||
assert( alIsSource(m_soundSource) );
|
||||
|
||||
//std::cout << "Setting a source with buffer " << m_soundBuffer << ", rolloff " << rolloff
|
||||
// << ", gain=" << m_defaultGain << ", positional=" << (positional ? "true" : "false") << std::endl;
|
||||
|
||||
alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer);
|
||||
|
||||
if (!SFXManager::checkError("attaching the buffer to the source")) return;
|
||||
|
||||
alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0);
|
||||
alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
||||
alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0);
|
||||
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, rolloff );
|
||||
alSourcef (m_soundSource, AL_GAIN, m_defaultGain);
|
||||
if(positional)
|
||||
alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||
else
|
||||
alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
|
||||
|
||||
if (positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||
else alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
|
||||
m_positional = positional;
|
||||
m_ok = SFXManager::checkError("setting up the source");
|
||||
|
@ -44,7 +44,7 @@ UnlockManager::UnlockManager()
|
||||
// in main).
|
||||
unlock_manager=this;
|
||||
|
||||
m_locked_sound = sfx_manager->newSFX(SFXManager::SOUND_LOCKED);
|
||||
m_locked_sound = sfx_manager->createSoundSource("locked");
|
||||
|
||||
// Read challenges from .../data
|
||||
// -----------------------------
|
||||
|
@ -30,7 +30,7 @@
|
||||
const float explosion_time = 1.5f;
|
||||
const float burst_time = 0.1f;
|
||||
|
||||
Explosion::Explosion(const Vec3& coord, const int explosion_sound)
|
||||
Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
|
||||
{
|
||||
m_remaining_time = burst_time; // short emision time, explosion, not constant flame
|
||||
m_node = irr_driver->addParticleNode();
|
||||
@ -69,7 +69,7 @@ Explosion::Explosion(const Vec3& coord, const int explosion_sound)
|
||||
//paf->drop();
|
||||
|
||||
|
||||
m_explode_sound = sfx_manager->newSFX( (SFXManager::SFXType)explosion_sound );
|
||||
m_explode_sound = sfx_manager->createSoundSource( explosion_sound );
|
||||
init(coord);
|
||||
} // Explosion
|
||||
|
||||
|
@ -34,7 +34,7 @@ private:
|
||||
scene::IParticleSystemSceneNode *m_node;
|
||||
|
||||
public:
|
||||
Explosion(const Vec3& coord, const int explosion_sound);
|
||||
Explosion(const Vec3& coord, const char* explosion_sound);
|
||||
~Explosion();
|
||||
void init (const Vec3& coord);
|
||||
void update (float delta_t);
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
static void init(const XMLNode &node, scene::IMesh *bowling);
|
||||
virtual void update(float dt);
|
||||
|
||||
int getExplosionSound() const { return SFXManager::SOUND_BOWLING_STRIKE; }
|
||||
const char* getExplosionSound() const { return "bowling_strike"; }
|
||||
|
||||
}; // Bowling
|
||||
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
void setHasHit () { m_has_hit_something = true; }
|
||||
void reset () { Moveable::reset(); }
|
||||
bool isOwnerImmunity(const Kart *kart_hit) const;
|
||||
virtual int getExplosionSound() const { return SFXManager::SOUND_EXPLOSION; }
|
||||
virtual const char* getExplosionSound() const { return "explosion"; }
|
||||
/** Indicates if an explosion needs to be added if this flyable
|
||||
* is removed. */
|
||||
virtual bool needsExplosion() const {return true;}
|
||||
|
@ -81,30 +81,30 @@ void Powerup::set(PowerupType type, int n)
|
||||
break ;
|
||||
|
||||
case POWERUP_BOWLING:
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_BOWLING_ROLL);
|
||||
m_sound_use = sfx_manager->createSoundSource("bowling_roll");
|
||||
break ;
|
||||
|
||||
case POWERUP_ANVIL:
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_USE_ANVIL);
|
||||
m_sound_use = sfx_manager->createSoundSource("use_anvil");
|
||||
break;
|
||||
|
||||
case POWERUP_PARACHUTE:
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_USE_PARACHUTE);
|
||||
m_sound_use = sfx_manager->createSoundSource("use_parachute");
|
||||
break;
|
||||
|
||||
case POWERUP_BUBBLEGUM:
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_GOO);
|
||||
m_sound_use = sfx_manager->createSoundSource("goo");
|
||||
break ;
|
||||
|
||||
case POWERUP_SWITCH:
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_SWAP);
|
||||
m_sound_use = sfx_manager->createSoundSource("swap");
|
||||
break;
|
||||
|
||||
case POWERUP_NOTHING:
|
||||
case POWERUP_CAKE:
|
||||
case POWERUP_PLUNGER:
|
||||
default :
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_SHOT);
|
||||
m_sound_use = sfx_manager->createSoundSource("shot");
|
||||
break ;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ void Powerup::use()
|
||||
{
|
||||
//if (m_type == POWERUP_SWITCH) m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_SWAP);
|
||||
//else
|
||||
m_sound_use = sfx_manager->newSFX(SFXManager::SOUND_SHOT);
|
||||
m_sound_use = sfx_manager->createSoundSource("shot");
|
||||
}
|
||||
|
||||
m_number--;
|
||||
|
@ -186,7 +186,7 @@ Flyable *ProjectileManager::newProjectile(Kart *kart, PowerupType type)
|
||||
// -----------------------------------------------------------------------------
|
||||
/** See if there is an old, unused explosion object available. If so,
|
||||
* reuse this object, otherwise create a new one. */
|
||||
Explosion* ProjectileManager::newExplosion(const Vec3& coord, const int explosion_sound)
|
||||
Explosion* ProjectileManager::newExplosion(const Vec3& coord, const char* explosion_sound)
|
||||
{
|
||||
Explosion *e = new Explosion(coord, explosion_sound);
|
||||
m_active_explosions.push_back(e);
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
void cleanup ();
|
||||
void update (float dt);
|
||||
Flyable* newProjectile (Kart *kart, PowerupType type);
|
||||
Explosion* newExplosion (const Vec3& coord, const int explosion_sound=(SFXManager::SFXType)SFXManager::SOUND_EXPLOSION);
|
||||
Explosion* newExplosion (const Vec3& coord, const char* explosion_sound="explosion");
|
||||
void Deactivate (Flyable *p) {}
|
||||
void removeTextures ();
|
||||
};
|
||||
|
@ -50,11 +50,11 @@ PlayerController::PlayerController(Kart *kart, ActivePlayer *player,
|
||||
kart->setCamera(new Camera(player_index, kart));
|
||||
kart->getCamera()->setMode(Camera::CM_NORMAL);
|
||||
|
||||
m_bzzt_sound = sfx_manager->newSFX(SFXManager::SOUND_BZZT );
|
||||
m_wee_sound = sfx_manager->newSFX(SFXManager::SOUND_WEE );
|
||||
m_ugh_sound = sfx_manager->newSFX(SFXManager::SOUND_UGH );
|
||||
m_grab_sound = sfx_manager->newSFX(SFXManager::SOUND_GRAB );
|
||||
m_full_sound = sfx_manager->newSFX(SFXManager::SOUND_FULL );
|
||||
m_bzzt_sound = sfx_manager->createSoundSource( "bzzt" );
|
||||
m_wee_sound = sfx_manager->createSoundSource( "wee" );
|
||||
m_ugh_sound = sfx_manager->createSoundSource( "ugh" );
|
||||
m_grab_sound = sfx_manager->createSoundSource( "grab" );
|
||||
m_full_sound = sfx_manager->createSoundSource( "full" );
|
||||
|
||||
reset();
|
||||
} // PlayerController
|
||||
|
@ -88,8 +88,8 @@ Kart::Kart (const std::string& ident, int position,
|
||||
|
||||
m_view_blocked_by_plunger = 0;
|
||||
|
||||
// Initialize custom sound vector
|
||||
m_custom_sounds.resize(SFXManager::NUM_CUSTOMS);
|
||||
// Initialize custom sound vector (TODO: add back when properly done)
|
||||
// m_custom_sounds.resize(SFXManager::NUM_CUSTOMS);
|
||||
|
||||
// Set position and heading:
|
||||
m_reset_transform = init_transform;
|
||||
@ -109,21 +109,24 @@ Kart::Kart (const std::string& ident, int position,
|
||||
m_kart_mode = KM_RACE;
|
||||
m_wheel_rotation = 0;
|
||||
|
||||
// Create SFXBase for each custom sound
|
||||
// Create SFXBase for each custom sound (TODO: add back when properly done)
|
||||
/*
|
||||
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
|
||||
{
|
||||
int id = m_kart_properties->getCustomSfxId((SFXManager::CustomSFX)n);
|
||||
|
||||
// If id == -1 the custom sound was not defined in the .irrkart config file
|
||||
if (id != -1)
|
||||
{
|
||||
m_custom_sounds[n] = sfx_manager->newSFX(id);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
m_engine_sound = sfx_manager->newSFX(m_kart_properties->getEngineSfxType());
|
||||
m_beep_sound = sfx_manager->newSFX( SFXManager::SOUND_BEEP );
|
||||
m_crash_sound = sfx_manager->newSFX( SFXManager::SOUND_CRASH );
|
||||
m_goo_sound = sfx_manager->newSFX( SFXManager::SOUND_GOO );
|
||||
m_skid_sound = sfx_manager->newSFX( SFXManager::SOUND_SKID );
|
||||
m_engine_sound = sfx_manager->createSoundSource(m_kart_properties->getEngineSfxType());
|
||||
m_beep_sound = sfx_manager->createSoundSource( "beep" );
|
||||
m_crash_sound = sfx_manager->createSoundSource( "crash" );
|
||||
m_goo_sound = sfx_manager->createSoundSource( "goo" );
|
||||
m_skid_sound = sfx_manager->createSoundSource( "skid" );
|
||||
|
||||
if(!m_engine_sound)
|
||||
{
|
||||
@ -280,12 +283,13 @@ Kart::~Kart()
|
||||
m_engine_sound->stop();
|
||||
}
|
||||
|
||||
// Delete all custom sounds
|
||||
// Delete all custom sounds (TODO: add back when properly done)
|
||||
/*
|
||||
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
|
||||
{
|
||||
if (m_custom_sounds[n] != NULL)
|
||||
sfx_manager->deleteSFX(m_custom_sounds[n]);
|
||||
}
|
||||
}*/
|
||||
|
||||
sfx_manager->deleteSFX(m_engine_sound );
|
||||
sfx_manager->deleteSFX(m_crash_sound );
|
||||
@ -669,11 +673,13 @@ void Kart::update(float dt)
|
||||
|
||||
Moveable::update(dt);
|
||||
|
||||
/* (TODO: add back when properly done)
|
||||
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
|
||||
{
|
||||
if (m_custom_sounds[n] != NULL) m_custom_sounds[n]->position ( getXYZ() );
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
m_beep_sound->position ( getXYZ() );
|
||||
m_engine_sound->position ( getXYZ() );
|
||||
m_crash_sound->position ( getXYZ() );
|
||||
@ -993,6 +999,10 @@ void Kart::beep()
|
||||
|
||||
bool Kart::playCustomSFX(unsigned int type)
|
||||
{
|
||||
// (TODO: add back when properly done)
|
||||
return false;
|
||||
|
||||
/*
|
||||
bool ret = false;
|
||||
|
||||
// Stop all other character voices for this kart before playing a new one
|
||||
@ -1012,13 +1022,16 @@ bool Kart::playCustomSFX(unsigned int type)
|
||||
if (m_custom_sounds[type] != NULL)
|
||||
{
|
||||
ret = true;
|
||||
printf("Kart SFX: playing %s for %s.\n", sfx_manager->getCustomTagName(type), m_kart_properties->getIdent().c_str());
|
||||
//printf("Kart SFX: playing %s for %s.\n", sfx_manager->getCustomTagName(type), m_kart_properties->getIdent().c_str());
|
||||
// If it's already playing, let it finish
|
||||
if (m_custom_sounds[type]->getStatus() != SFXManager::SFX_PLAYING)
|
||||
{
|
||||
m_custom_sounds[type]->play();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
*/
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void Kart::updatePhysics (float dt)
|
||||
|
@ -80,10 +80,10 @@ KartProperties::KartProperties(const std::string &filename) : m_icon_material(0)
|
||||
m_version = 0;
|
||||
m_color = video::SColor(255, 0, 0, 0);
|
||||
m_shape = 32; // close enough to a circle.
|
||||
m_engine_sfx_type = SFXManager::SOUND_ENGINE_SMALL;
|
||||
m_engine_sfx_type = "engine_small";
|
||||
|
||||
// The default constructor for stk_config uses filename=""
|
||||
if(filename!="")
|
||||
load(filename);
|
||||
if (filename != "") load(filename);
|
||||
} // KartProperties
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -222,13 +222,13 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
std::string sfx_type_string;
|
||||
root->get("engine-sound", &sfx_type_string);
|
||||
|
||||
if(sfx_type_string == "large")
|
||||
if (sfx_type_string == "large")
|
||||
{
|
||||
m_engine_sfx_type = SFXManager::SOUND_ENGINE_LARGE;
|
||||
m_engine_sfx_type = "engine_large";
|
||||
}
|
||||
else if(sfx_type_string == "small")
|
||||
else if (sfx_type_string == "small")
|
||||
{
|
||||
m_engine_sfx_type = SFXManager::SOUND_ENGINE_SMALL;
|
||||
m_engine_sfx_type = "engine_small";
|
||||
}
|
||||
|
||||
root->get("has-skidmarks", &m_has_skidmarks);
|
||||
@ -362,7 +362,8 @@ void KartProperties::getAllData(const lisp::Lisp* lisp)
|
||||
lisp->get("brake-factor", m_brake_factor);
|
||||
lisp->get("mass", m_mass);
|
||||
|
||||
// Load custom kart SFX files
|
||||
/*
|
||||
// Load custom kart SFX files (TODO: enable back when it's implemented properly)
|
||||
for (int i = 0; i < SFXManager::NUM_CUSTOMS; i++)
|
||||
{
|
||||
std::string tempFile;
|
||||
@ -385,24 +386,26 @@ void KartProperties::getAllData(const lisp::Lisp* lisp)
|
||||
m_custom_sfx_id[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
std::string sfx_type_string;
|
||||
lisp->get("engine-sound", sfx_type_string);
|
||||
if(sfx_type_string == "large")
|
||||
{
|
||||
m_engine_sfx_type = SFXManager::SOUND_ENGINE_LARGE;
|
||||
m_engine_sfx_type = "engine_large";
|
||||
}
|
||||
else if(sfx_type_string == "small")
|
||||
{
|
||||
m_engine_sfx_type = SFXManager::SOUND_ENGINE_SMALL;
|
||||
m_engine_sfx_type = "engine_small";
|
||||
}
|
||||
|
||||
std::vector<float> v;
|
||||
if(lisp->getVector("max-speed-radius", v))
|
||||
{
|
||||
if(v.size()!=2)
|
||||
if (v.size()!=2)
|
||||
{
|
||||
printf("Incorrect max-speed-angle specifications for kart '%s'\n",
|
||||
getIdent().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_max_speed_turn = v[0];
|
||||
|
@ -107,8 +107,7 @@ private:
|
||||
float m_rubber_band_duration;/**< Duration a rubber band works. */
|
||||
float m_wheel_base; /**< Wheel base of the kart. */
|
||||
float m_nitro_power_boost; /**< Nitro power boost. */
|
||||
SFXManager::SFXType
|
||||
m_engine_sfx_type; /**< Engine sound effect. */
|
||||
std::string m_engine_sfx_type; /**< Engine sound effect. */
|
||||
|
||||
// bullet physics data
|
||||
// -------------------
|
||||
@ -207,8 +206,7 @@ public:
|
||||
float getTimeFullSteerAI () const {return m_time_full_steer_ai; }
|
||||
float getBrakeFactor () const {return m_brake_factor; }
|
||||
float getMaxSpeedReverseRatio () const {return m_max_speed_reverse_ratio; }
|
||||
SFXManager::SFXType getEngineSfxType()
|
||||
const {return m_engine_sfx_type; }
|
||||
const char* getEngineSfxType () const {return m_engine_sfx_type.c_str(); }
|
||||
|
||||
//bullet physics get functions
|
||||
float getSuspensionStiffness () const {return m_suspension_stiffness; }
|
||||
|
@ -34,8 +34,8 @@ WorldStatus::WorldStatus()
|
||||
m_phase = SETUP_PHASE;
|
||||
|
||||
// FIXME - is it a really good idea to reload and delete the sound every race??
|
||||
m_prestart_sound = sfx_manager->newSFX(SFXManager::SOUND_PRESTART);
|
||||
m_start_sound = sfx_manager->newSFX(SFXManager::SOUND_START);
|
||||
m_prestart_sound = sfx_manager->createSoundSource("prestart");
|
||||
m_start_sound = sfx_manager->createSoundSource("start");
|
||||
} // WorldStatus
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -423,7 +423,7 @@ FocusDispatcher* g_dispatcher = NULL;
|
||||
playerName->elementRemoved();
|
||||
playerName = NULL;
|
||||
|
||||
SFXManager::quickSound( SFXManager::SOUND_WEE );
|
||||
SFXManager::quickSound( "wee" );
|
||||
|
||||
modelView->setRotateTo(30.0f, 150.0f);
|
||||
|
||||
@ -834,7 +834,7 @@ bool KartSelectionScreen::playerQuit(ActivePlayer* player)
|
||||
// Check that this player has not already confirmed, then they can't back out
|
||||
if (m_kart_widgets[n].isReady())
|
||||
{
|
||||
sfx_manager->quickSound( SFXManager::SOUND_USE_ANVIL );
|
||||
sfx_manager->quickSound( "use_anvil" );
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1311,7 +1311,7 @@ void KartSelectionScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
|
||||
//SFXType sound;
|
||||
//SOUND_UGH SOUND_CRASH SOUND_USE_ANVIL SOUND_EXPLOSION SOUND_MOVE_MENU SOUND_SELECT_MENU
|
||||
sfx_manager->quickSound( SFXManager::SOUND_USE_ANVIL );
|
||||
sfx_manager->quickSound( "use_anvil" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -160,8 +160,7 @@ void OptionsScreenAV::eventCallback(Widget* widget, const std::string& name, con
|
||||
SpinnerWidget* w = dynamic_cast<SpinnerWidget*>(widget);
|
||||
assert(w != NULL);
|
||||
|
||||
if(sample_sound == NULL)
|
||||
sample_sound = sfx_manager->newSFX( SFXManager::SOUND_SKID );
|
||||
if (sample_sound == NULL) sample_sound = sfx_manager->createSoundSource( "skid" );
|
||||
sample_sound->volume(1);
|
||||
|
||||
sfx_manager->setMasterSFXVolume( w->getValue()/10.0f );
|
||||
|
Loading…
Reference in New Issue
Block a user