601 lines
17 KiB
C++
601 lines
17 KiB
C++
//=============================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File: soundloader.cpp
|
|
//
|
|
// Description: Implement SoundLoader class, which makes sure that sounds
|
|
// required in the game are allocated and resident in sound memory
|
|
//
|
|
// History: 26/06/2002 + Created -- Darren
|
|
//
|
|
//=============================================================================
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
#include <stdio.h>
|
|
|
|
#include <sound/soundloader.h>
|
|
#include <sound/soundrenderer/soundrenderingmanager.h>
|
|
#include <sound/soundrenderer/soundresourcemanager.h>
|
|
|
|
#include <memory/srrmemory.h>
|
|
#include <loading/loadingmanager.h>
|
|
#include <worldsim/redbrick/vehicle.h>
|
|
#include <constants/vehicleenum.h>
|
|
#include <mission/gameplaymanager.h>
|
|
#include <events/eventmanager.h>
|
|
#include <worldsim/character/character.h>
|
|
|
|
#include <radscript.hpp>
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Global Data, Local Data, Local Classes
|
|
//
|
|
//******************************************************************************
|
|
|
|
//
|
|
// Names of sound clusters. Used so that the loading manager can tell us
|
|
// when it's our turn to loading something. Should correspond to SoundClusterName
|
|
// enumeration
|
|
//
|
|
static const char* s_clusterNames[] =
|
|
{
|
|
"permanent",
|
|
"frontend",
|
|
"ingame",
|
|
"suburbs",
|
|
"downtown",
|
|
"seaside",
|
|
"level1",
|
|
"level2",
|
|
"level3",
|
|
"level4",
|
|
"level5",
|
|
"level6",
|
|
"level7",
|
|
"minigame",
|
|
"huh?",
|
|
"apu",
|
|
"bart",
|
|
"homer",
|
|
"lisa",
|
|
"marge",
|
|
"bart_v",
|
|
"apu_v",
|
|
"snake_v",
|
|
"homer_v",
|
|
"famil_v",
|
|
"gramp_v",
|
|
"cletu_v",
|
|
"wiggu_v",
|
|
"empty1",
|
|
"marge_v",
|
|
"empty2",
|
|
"empty3",
|
|
"smith_v",
|
|
"empty4",
|
|
"empty5",
|
|
"empty6",
|
|
"zombi_v",
|
|
"empty7",
|
|
"empty8",
|
|
"cVan",
|
|
"compactA",
|
|
"comic_v",
|
|
"skinn_v",
|
|
"cCola",
|
|
"cSedan",
|
|
"cPolice",
|
|
"cCellA",
|
|
"cCellB",
|
|
"cCellC",
|
|
"cCellD",
|
|
"minivanA_v",
|
|
"pickupA",
|
|
"taxiA_v",
|
|
"sportsA",
|
|
"sportsB",
|
|
"SUVA",
|
|
"wagonA",
|
|
"hbike_v",
|
|
"burns_v",
|
|
"honor_v",
|
|
"cArmor",
|
|
"cCurator",
|
|
"cHears",
|
|
"cKlimo",
|
|
"cLimo",
|
|
"cNerd",
|
|
"frink_v",
|
|
"cMilk",
|
|
"cDonut",
|
|
"bbman_v",
|
|
"bookb_v",
|
|
"carhom_v",
|
|
"elect_v",
|
|
"fone_v",
|
|
"gramR_v",
|
|
"moe_v",
|
|
"mrplo_v",
|
|
"otto_v",
|
|
"plowk_v",
|
|
"scorp_v",
|
|
"willi_v",
|
|
"sedanA",
|
|
"sedanB",
|
|
"cBlbart",
|
|
"cCube",
|
|
"cDuff",
|
|
"cNonup",
|
|
"lisa_v",
|
|
"krust_v",
|
|
"coffin",
|
|
"hallo",
|
|
"ship",
|
|
"witchcar",
|
|
"huska",
|
|
"atv_v",
|
|
"dune_v",
|
|
"hype_v",
|
|
"knigh_v",
|
|
"mono_v",
|
|
"oblit_v",
|
|
"rocke_v",
|
|
"ambul",
|
|
"burnsarm",
|
|
"fishtruc",
|
|
"garbage",
|
|
"icecream",
|
|
"istruck",
|
|
"nuctruck",
|
|
"pizza",
|
|
"schoolbu",
|
|
"votetruc",
|
|
"glastruc",
|
|
"cfire_v",
|
|
"cBone",
|
|
"redbrick"
|
|
};
|
|
|
|
static const int NumScriptNames = sizeof( s_clusterNames ) / sizeof( const char* );
|
|
|
|
//
|
|
// Indices of character namespaces for each level.
|
|
//
|
|
// TODO: I don't like these tables, there must be a more data-driven way to do
|
|
// this.
|
|
// 0 == Apu
|
|
// 1 == Bart
|
|
// 2 == Homer
|
|
// 3 == Lisa
|
|
// 4 == Marge
|
|
//
|
|
static unsigned int s_charNamespaceIndices[] = { 2, 1, 3, 4, 0, 1, 2, 0 };
|
|
|
|
static VehicleEnum::VehicleID s_carIndices[] = { VehicleEnum::FAMIL_V,
|
|
VehicleEnum::HONOR_V,
|
|
VehicleEnum::LISA_V,
|
|
VehicleEnum::MARGE_V,
|
|
VehicleEnum::APU_V,
|
|
VehicleEnum::BART_V,
|
|
VehicleEnum::HOMER_V,
|
|
VehicleEnum::FAMIL_V,
|
|
};
|
|
|
|
static unsigned int s_levelIndices[] = { 0, 1, 2, 0, 1, 2, 0, 0 };
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Public Member Functions
|
|
//
|
|
//******************************************************************************
|
|
|
|
//==============================================================================
|
|
// SoundLoader::SoundLoader
|
|
//==============================================================================
|
|
// Description: Constructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
SoundLoader::SoundLoader() :
|
|
m_currentCluster( SC_ALWAYS_LOADED )
|
|
{
|
|
unsigned int i;
|
|
SoundClusterName clusterIndex;
|
|
Sound::daSoundRenderingManager* renderingMgr = Sound::daSoundRenderingManagerGet();
|
|
|
|
for( i = 0; i < SC_MAX_CLUSTERS; i++ )
|
|
{
|
|
m_clusterList[i] = NULL;
|
|
}
|
|
|
|
for( clusterIndex = SC_ALWAYS_LOADED;
|
|
clusterIndex < SC_CHAR_APU;
|
|
clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) )
|
|
{
|
|
m_clusterList[clusterIndex] =
|
|
new(GMA_PERSISTENT) SoundCluster( clusterIndex,
|
|
renderingMgr->GetSoundNamespace() );
|
|
}
|
|
|
|
for( clusterIndex = SC_CHAR_APU;
|
|
clusterIndex < SC_CAR_BASE;
|
|
clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) )
|
|
{
|
|
m_clusterList[clusterIndex] =
|
|
new(GMA_PERSISTENT) SoundCluster( clusterIndex,
|
|
renderingMgr->GetCharacterNamespace( clusterIndex - SC_CHAR_APU ) );
|
|
}
|
|
|
|
for( clusterIndex = SC_CAR_BASE;
|
|
clusterIndex < SC_MAX_CLUSTERS;
|
|
clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) )
|
|
{
|
|
m_clusterList[clusterIndex] =
|
|
new(GMA_PERSISTENT) SoundCluster( clusterIndex,
|
|
renderingMgr->GetSoundNamespace() );
|
|
}
|
|
|
|
//
|
|
// Register event listeners
|
|
//
|
|
GetEventManager()->AddListener( this, EVENT_GETINTOVEHICLE_START );
|
|
}
|
|
|
|
//==============================================================================
|
|
// SoundLoader::~SoundLoader
|
|
//==============================================================================
|
|
// Description: Destructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//==============================================================================
|
|
SoundLoader::~SoundLoader()
|
|
{
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < SC_MAX_CLUSTERS; i++ )
|
|
{
|
|
if( m_clusterList[i] != NULL )
|
|
{
|
|
m_clusterList[i]->Release();
|
|
}
|
|
}
|
|
|
|
GetEventManager()->RemoveAll( this );
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::LevelLoad
|
|
//=============================================================================
|
|
// Description: Loads the sound cluster for a particular level
|
|
//
|
|
// Parameters: RenderEnums::LevelEnum level -
|
|
// enumeration indicating the level whose sound cluster
|
|
// is to be loaded
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::LevelLoad( RenderEnums::LevelEnum level )
|
|
{
|
|
IRadNameSpace* charNamespace;
|
|
unsigned int levelNum;
|
|
|
|
clusterUnload( SC_FRONTEND );
|
|
|
|
queueLoad( SC_INGAME );
|
|
|
|
if( GetGameplayManager()->IsSuperSprint() )
|
|
{
|
|
queueLoad( SC_MINIGAME );
|
|
}
|
|
else
|
|
{
|
|
rAssert( level <= RenderEnums::numLevels );
|
|
levelNum = static_cast<unsigned int>(level);
|
|
|
|
queueLoad( static_cast<SoundClusterName>( SC_LEVEL_SUBURBS + s_levelIndices[levelNum] ) );
|
|
queueLoad( static_cast<SoundClusterName>( SC_CHAR_APU + s_charNamespaceIndices[levelNum] ) );
|
|
queueLoad( static_cast<SoundClusterName>( SC_CAR_BASE + s_carIndices[levelNum] ) );
|
|
queueLoad( static_cast<SoundClusterName>( SC_LEVEL1 + levelNum ) );
|
|
|
|
charNamespace = m_clusterList[SC_CHAR_APU + s_charNamespaceIndices[level]]->GetMyNamespace();
|
|
rAssert( charNamespace != NULL );
|
|
|
|
//
|
|
// We need to do this for RadTuner, since we've got duplicate names and
|
|
// it won't necessarily find the correct character otherwise
|
|
//
|
|
charNamespace->MoveToFront();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::LevelUnload
|
|
//=============================================================================
|
|
// Description: Unloads the sound cluster for a particular level
|
|
//
|
|
// Parameters: RenderEnums::LevelEnum level -
|
|
// enumeration indicating the level whose sound cluster
|
|
// is to be unloaded
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::LevelUnload( bool goingToFe )
|
|
{
|
|
SoundClusterName clusterIndex;
|
|
|
|
//
|
|
// Unload everything that's not permanent
|
|
//
|
|
for( clusterIndex = SC_INGAME;
|
|
clusterIndex < SC_MAX_CLUSTERS;
|
|
clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) )
|
|
{
|
|
if( m_clusterList[clusterIndex]->IsLoaded() )
|
|
{
|
|
clusterUnload( clusterIndex );
|
|
}
|
|
}
|
|
|
|
if( goingToFe )
|
|
{
|
|
queueLoad( SC_FRONTEND );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::MissionLoad
|
|
//=============================================================================
|
|
// Description: Loads the sound cluster for a particular mission
|
|
//
|
|
// Parameters: RenderEnums::MissionEnum mission -
|
|
// enumeration indicating the mission whose sound cluster
|
|
// is to be loaded
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::MissionLoad( RenderEnums::MissionEnum mission )
|
|
{
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::MissionUnload
|
|
//=============================================================================
|
|
// Description: Unloads the sound cluster for a particular mission
|
|
//
|
|
// Parameters: RenderEnums::MissionEnum mission -
|
|
// enumeration indicating the mission whose sound cluster
|
|
// is to be unloaded
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::MissionUnload( RenderEnums::MissionEnum mission )
|
|
{
|
|
}
|
|
|
|
void SoundLoader::LoadCarSound( Vehicle* theCar, bool unloadOtherCars )
|
|
{
|
|
rAssert( theCar );
|
|
|
|
SoundClusterName clusterIndex;
|
|
SoundClusterName newCarCluster = static_cast<SoundClusterName>(SC_CAR_BASE + theCar->mVehicleID);
|
|
bool validCar = ( SC_CAR_BASE + theCar->mVehicleID ) < NumScriptNames;
|
|
|
|
rAssertMsg( validCar, "A new vehicle has been added that the sound system does not have a script for. Tell Esan.\n" );
|
|
|
|
//
|
|
// Have we loaded this car already?
|
|
//
|
|
if( !validCar || m_clusterList[newCarCluster]->IsLoaded() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Unload the existing car sound
|
|
//
|
|
if( unloadOtherCars )
|
|
{
|
|
for( clusterIndex = SC_CAR_BASE;
|
|
clusterIndex < SC_MAX_CLUSTERS;
|
|
clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) )
|
|
{
|
|
if( m_clusterList[clusterIndex]->IsLoaded() )
|
|
{
|
|
clusterUnload( clusterIndex );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load the new car
|
|
//
|
|
queueLoad( newCarCluster );
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::IsSoundLoaded
|
|
//=============================================================================
|
|
// Description: Indicate whether a particular sound resource has been loaded
|
|
//
|
|
// Parameters: soundKey - hashed name of the sound resource to look for
|
|
//
|
|
// Return: true if loaded, falsed otherwise
|
|
//
|
|
//=============================================================================
|
|
bool SoundLoader::IsSoundLoaded( Sound::daResourceKey soundKey )
|
|
{
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < SC_MAX_CLUSTERS; i++ )
|
|
{
|
|
if( ( m_clusterList[i] != NULL ) && ( m_clusterList[i]->ContainsResource( soundKey ) ) )
|
|
{
|
|
return( m_clusterList[i]->IsLoaded() );
|
|
}
|
|
}
|
|
|
|
return( false );
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::LoadClusterByName
|
|
//=============================================================================
|
|
// Description: Given a cluster name from the loading manager, load the
|
|
// desired cluster
|
|
//
|
|
// Parameters: clusterName - text name for the cluster
|
|
// callbackObj - loading file handler to notify on completion
|
|
//
|
|
// Return: true if cluster already loaded, false otherwise
|
|
//
|
|
//=============================================================================
|
|
bool SoundLoader::LoadClusterByName( const char* clusterName, SoundFileHandler* callbackObj )
|
|
{
|
|
const char* shortName;
|
|
unsigned int i;
|
|
|
|
// Strip out the "sound:" prefix
|
|
rAssert( strlen( clusterName ) > 6 );
|
|
shortName = &(clusterName[6]);
|
|
|
|
//
|
|
// Find the matching cluster name
|
|
//
|
|
for( i = 0; i < SC_MAX_CLUSTERS; i++ )
|
|
{
|
|
if( strcmp( shortName, s_clusterNames[i] ) == 0 )
|
|
{
|
|
return( clusterLoad( static_cast<SoundClusterName>( i ), callbackObj ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we get here, cluster not found
|
|
//
|
|
rAssert( false );
|
|
return( false );
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::HandleEvent
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( EventEnum id, void* pEventData )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::HandleEvent( EventEnum id, void* pEventData )
|
|
{
|
|
Character* theCharacter;
|
|
Vehicle* theCar;
|
|
|
|
switch( id )
|
|
{
|
|
case EVENT_GETINTOVEHICLE_START:
|
|
//
|
|
// Make sure we've got the correct car sound for this vehicle
|
|
//
|
|
theCharacter = static_cast<Character*>(pEventData);
|
|
rAssert( theCharacter != NULL );
|
|
theCar = theCharacter->GetTargetVehicle();
|
|
rAssert( theCar != NULL );
|
|
|
|
LoadCarSound( theCar, true );
|
|
break;
|
|
|
|
default:
|
|
rAssert( false );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Private Member Functions
|
|
//
|
|
//******************************************************************************
|
|
|
|
//=============================================================================
|
|
// SoundLoader::queueLoad
|
|
//=============================================================================
|
|
// Description: Queue a cluster load with the loading manager
|
|
//
|
|
// Parameters: cluster - name of cluster to queue
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void SoundLoader::queueLoad( SoundClusterName cluster )
|
|
{
|
|
char fakeFilename[50];
|
|
|
|
//
|
|
// Create a pseudo filename that we'll give to the loading manager.
|
|
// Content doesn't really matter, we'll just throw it out when the
|
|
// loading manager passes it back
|
|
//
|
|
if( cluster >= NumScriptNames )
|
|
{
|
|
//
|
|
// Just load Bart for now
|
|
//
|
|
cluster = SC_CAR_BASE;
|
|
}
|
|
|
|
sprintf( fakeFilename, "sound:%s", s_clusterNames[cluster] );
|
|
GetLoadingManager()->AddRequest( FILEHANDLER_SOUND, fakeFilename, GMA_LEVEL_AUDIO );
|
|
}
|
|
|
|
//=============================================================================
|
|
// SoundLoader::clusterLoad
|
|
//=============================================================================
|
|
// Description: Find the specified sound cluster and direct it to load sounds
|
|
//
|
|
// Parameters: SoundClusterName name - specifies which cluster to load
|
|
//
|
|
// Return: false if cluster not yet loaded, true otherwise
|
|
//
|
|
//=============================================================================
|
|
bool SoundLoader::clusterLoad( SoundClusterName name, SoundFileHandler* callbackObj )
|
|
{
|
|
bool loaded;
|
|
|
|
rAssert( name < SC_MAX_CLUSTERS );
|
|
|
|
loaded = m_clusterList[name]->IsLoaded();
|
|
if( !loaded )
|
|
{
|
|
m_clusterList[name]->LoadSounds( callbackObj );
|
|
}
|
|
|
|
return( loaded );
|
|
}
|
|
|
|
void SoundLoader::clusterUnload( SoundClusterName name )
|
|
{
|
|
rAssert( name < SC_MAX_CLUSTERS );
|
|
if( m_clusterList[name]->IsLoaded() )
|
|
{
|
|
m_clusterList[name]->UnloadSounds();
|
|
}
|
|
} |