00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <landscape/LandscapeMusicManager.h>
00022 #include <landscapedef/LandscapeTex.h>
00023 #include <landscapedef/LandscapeDefn.h>
00024 #include <landscapemap/LandscapeMaps.h>
00025 #include <graph/OptionsDisplay.h>
00026 #include <client/ScorchedClient.h>
00027 #include <client/ClientState.h>
00028 #include <common/Defines.h>
00029 #include <sound/Sound.h>
00030 #include <XML/XMLFile.h>
00031
00032 LandscapeMusicManager *LandscapeMusicManager::instance()
00033 {
00034 static LandscapeMusicManager instance_;
00035 return &instance_;
00036 }
00037
00038 LandscapeMusicManager::LandscapeMusicManager() :
00039 GameStateI("LandscapeMusicManager")
00040 {
00041 addMusics();
00042 }
00043
00044 LandscapeMusicManager::~LandscapeMusicManager()
00045 {
00046 }
00047
00048 void LandscapeMusicManager::addMusics()
00049 {
00050 stateMusic_.clear();
00051
00052
00053
00054 readGlobalMusicFile();
00055
00056
00057 LandscapeDefn *defn =
00058 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getDefn();
00059 LandscapeTex *tex =
00060 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getTex();
00061
00062
00063 if (tex) addMusic(tex->texDefn.includes);
00064 if (defn) addMusic(defn->texDefn.includes);
00065 }
00066
00067 void LandscapeMusicManager::readGlobalMusicFile()
00068 {
00069 std::string filePath = S3D::getDataFile("data/music.xml");
00070
00071
00072 XMLFile file;
00073 if (!file.readFile(filePath))
00074 {
00075 S3D::dialogExit("Scorched3D", S3D::formatStringBuffer(
00076 "ERROR: Failed to parse music file \"%s\"\n"
00077 "%s",
00078 filePath.c_str(),
00079 file.getParserError()));
00080 }
00081
00082
00083 if (!file.getRootNode()) return;
00084
00085 XMLNode *musicNode = 0;
00086 while (file.getRootNode()->getNamedChild("music", musicNode, false))
00087 {
00088 LandscapeMusicType musicType;
00089 musicType.playstates.clear();
00090 if (!musicType.readXML(musicNode))
00091 {
00092 S3D::dialogExit("Scorched3D", S3D::formatStringBuffer(
00093 "ERROR: Failed to parse music file \"%s\"\n",
00094 filePath.c_str()));
00095 }
00096 addMusicType(&musicType);
00097 }
00098 }
00099
00100 void LandscapeMusicManager::addMusic(std::vector<LandscapeInclude *> &musics)
00101 {
00102 std::vector<LandscapeInclude *>::iterator includeitor;
00103 for (includeitor = musics.begin();
00104 includeitor != musics.end();
00105 includeitor++)
00106 {
00107 LandscapeInclude *include = (*includeitor);
00108 addMusicTypes(include->musics);
00109 }
00110 }
00111
00112 void LandscapeMusicManager::addMusicTypes(std::vector<LandscapeMusicType *> &musics)
00113 {
00114 std::vector<LandscapeMusicType *>::iterator itor;
00115 for (itor = musics.begin();
00116 itor != musics.end();
00117 itor++)
00118 {
00119 LandscapeMusicType *music = (*itor);
00120 addMusicType(music);
00121 }
00122 }
00123
00124 void LandscapeMusicManager::addMusicType(LandscapeMusicType *music)
00125 {
00126 std::vector<LandscapeMusicType::PlayState>::iterator stateitor;
00127 for (stateitor = music->playstates.begin();
00128 stateitor != music->playstates.end();
00129 stateitor++)
00130 {
00131 LandscapeMusicType::PlayState playState = (*stateitor);
00132
00133 MusicStateEntry stateEntry;
00134 stateEntry.file = music->file;
00135 stateEntry.gain = music->gain;
00136 if (stateMusic_.find(int(playState)) == stateMusic_.end())
00137 {
00138 stateMusic_.insert(std::pair<int, MusicStateEntry>(int(playState), stateEntry));
00139 }
00140 else
00141 {
00142 stateMusic_[int(playState)] = stateEntry;
00143 }
00144 }
00145 }
00146
00147 void LandscapeMusicManager::simulate(const unsigned state, float simTime)
00148 {
00149
00150 LandscapeMusicType::PlayState playState = LandscapeMusicType::StateNone;
00151 switch (state)
00152 {
00153 case ClientState::StateOptions:
00154 case ClientState::StateLoadFiles:
00155 case ClientState::StateGetPlayers:
00156 case ClientState::StateLoadPlayers:
00157 case ClientState::StateLoadLevel:
00158 case ClientState::StateConnect:
00159 playState = LandscapeMusicType::StateLoading;
00160 break;
00161 case ClientState::StateWait:
00162 playState = LandscapeMusicType::StateWait;
00163 break;
00164 case ClientState::StateBuyWeapons:
00165 case ClientState::StateAutoDefense:
00166 playState = LandscapeMusicType::StateBuying;
00167 break;
00168 case ClientState::StatePlaying:
00169 playState = LandscapeMusicType::StatePlaying;
00170 break;
00171 case ClientState::StateShot:
00172 playState = LandscapeMusicType::StateShot;
00173 break;
00174 case ClientState::StateScore:
00175 playState = LandscapeMusicType::StateScore;
00176 break;
00177 default:
00178
00179 playState = LandscapeMusicType::StateNone;
00180 break;
00181 }
00182
00183
00184 MusicStateEntry *wantedEntry = 0;
00185 if (!OptionsDisplay::instance()->getNoMusic() &&
00186 OptionsDisplay::instance()->getMusicVolume() > 0)
00187 {
00188 std::map<int, MusicStateEntry>::iterator findItor =
00189 stateMusic_.find(int(playState));
00190 if (findItor != stateMusic_.end())
00191 {
00192 wantedEntry = &(*findItor).second;
00193 }
00194 }
00195
00196
00197 bool found = false;
00198 std::list<MusicPlayingEntry *> remove;
00199 std::list<MusicPlayingEntry *>::iterator itor;
00200 for (itor = currentMusic_.begin();
00201 itor != currentMusic_.end();
00202 itor++)
00203 {
00204 MusicPlayingEntry *playingEntry = *itor;
00205
00206 float wantedGain = 0;
00207 if (wantedEntry &&
00208 wantedEntry->file == playingEntry->file)
00209 {
00210 found = true;
00211 wantedGain =
00212 float(OptionsDisplay::instance()->getMusicVolume()) / 128.0f *
00213 wantedEntry->gain;
00214 }
00215 else
00216 {
00217 wantedGain = 0;
00218 if (playingEntry->currentGain == 0)
00219 {
00220 remove.push_back(playingEntry);
00221 }
00222 }
00223
00224 if (playingEntry->currentGain < wantedGain)
00225 {
00226 playingEntry->currentGain += simTime * 0.2f;
00227 playingEntry->currentGain = MIN(
00228 wantedGain,
00229 playingEntry->currentGain);
00230 playingEntry->currentSource->setGain(playingEntry->currentGain);
00231 }
00232 else if (playingEntry->currentGain > wantedGain)
00233 {
00234 playingEntry->currentGain -= simTime * 0.2f;
00235 playingEntry->currentGain = MAX(
00236 wantedGain,
00237 playingEntry->currentGain);
00238 playingEntry->currentSource->setGain(playingEntry->currentGain);
00239 }
00240 }
00241
00242
00243
00244 for (itor = remove.begin();
00245 itor != remove.end();
00246 itor++)
00247 {
00248 MusicPlayingEntry *playingEntry = *itor;
00249 playingEntry->currentSource->stop();
00250 delete playingEntry->currentSource;
00251 currentMusic_.remove(playingEntry);
00252 delete playingEntry;
00253 }
00254
00255
00256 if (!found && wantedEntry)
00257 {
00258
00259
00260 SoundBuffer *buffer =
00261 Sound::instance()->fetchOrCreateBuffer(
00262 S3D::getDataFile(wantedEntry->file.c_str()));
00263 if (buffer)
00264 {
00265
00266 VirtualSoundSource *currentSource = new VirtualSoundSource(
00267 VirtualSoundPriority::eMusic,
00268 true,
00269 false);
00270
00271
00272 MusicPlayingEntry *playingEntry = new MusicPlayingEntry();
00273 playingEntry->currentGain = 0;
00274 playingEntry->currentSource = currentSource;
00275 playingEntry->file = wantedEntry->file;
00276 currentMusic_.push_back(playingEntry);
00277
00278
00279 playingEntry->currentSource->setGain(0);
00280 playingEntry->currentSource->setRelative();
00281 playingEntry->currentSource->play(buffer);
00282 }
00283 }
00284 }