386 lines
8.8 KiB
C++
386 lines
8.8 KiB
C++
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#include "precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "Sound.h"
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdSoundBroadcastData
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
sdSoundBroadcastData::MakeDefault
|
||
|
==============
|
||
|
*/
|
||
|
void sdSoundBroadcastData::MakeDefault( void ) {
|
||
|
isOn = true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
sdSoundBroadcastData::Write
|
||
|
==============
|
||
|
*/
|
||
|
void sdSoundBroadcastData::Write( idFile* file ) const {
|
||
|
file->WriteBool( isOn );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
sdSoundBroadcastData::Read
|
||
|
==============
|
||
|
*/
|
||
|
void sdSoundBroadcastData::Read( idFile* file ) {
|
||
|
file->ReadBool( isOn );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
idSound
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
idList< idSoundEmitter* > idSound::s_soundEmitters;
|
||
|
|
||
|
extern const idEventDef EV_TurnOn;
|
||
|
extern const idEventDef EV_TurnOff;
|
||
|
|
||
|
const idEventDefInternal EV_Speaker_Timer( "internal_timer", NULL );
|
||
|
|
||
|
CLASS_DECLARATION( idEntity, idSound )
|
||
|
EVENT( EV_Activate, idSound::Event_Trigger )
|
||
|
EVENT( EV_TurnOn, idSound::Event_On )
|
||
|
EVENT( EV_TurnOff, idSound::Event_Off )
|
||
|
EVENT( EV_Speaker_Timer, idSound::Event_Timer )
|
||
|
END_CLASS
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::idSound
|
||
|
================
|
||
|
*/
|
||
|
idSound::idSound( void ) {
|
||
|
lastSoundVol = 0.0f;
|
||
|
soundVol = 0.0f;
|
||
|
random = 0.0f;
|
||
|
wait = 0.0f;
|
||
|
timerOn = false;
|
||
|
soundOn = false;
|
||
|
playingUntilTime = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::OnNewMapLoad
|
||
|
================
|
||
|
*/
|
||
|
void idSound::OnNewMapLoad( void ) {
|
||
|
FreeMapSounds();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::OnMapClear
|
||
|
================
|
||
|
*/
|
||
|
void idSound::OnMapClear( void ) {
|
||
|
FreeMapSounds();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::FreeMapSounds
|
||
|
================
|
||
|
*/
|
||
|
void idSound::FreeMapSounds( void ) {
|
||
|
for ( int i = 0; i < s_soundEmitters.Num(); i++ ) {
|
||
|
s_soundEmitters[ i ]->Free( true );
|
||
|
}
|
||
|
s_soundEmitters.Clear();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Spawn
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Spawn( void ) {
|
||
|
spawnArgs.GetFloat( "random", "0", random );
|
||
|
spawnArgs.GetFloat( "wait", "0", wait );
|
||
|
|
||
|
if ( ( wait > 0.0f ) && ( random >= wait ) ) {
|
||
|
random = wait - 0.001f;
|
||
|
gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
|
||
|
}
|
||
|
|
||
|
soundVol = 0.0f;
|
||
|
lastSoundVol = 0.0f;
|
||
|
|
||
|
if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
|
||
|
timerOn = true;
|
||
|
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
|
||
|
} else {
|
||
|
timerOn = false;
|
||
|
soundOn = true;
|
||
|
}
|
||
|
|
||
|
if ( g_removeStaticEntities.GetBool() && !StartSynced() && !timerOn ) {
|
||
|
if ( refSound.referenceSound != NULL ) {
|
||
|
s_soundEmitters.Alloc() = refSound.referenceSound;
|
||
|
refSound.referenceSound = NULL;
|
||
|
}
|
||
|
PostEventMS( &EV_Remove, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Event_Trigger
|
||
|
|
||
|
this will toggle the idle idSound on and off
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Event_Trigger( idEntity *activator ) {
|
||
|
if ( wait > 0.0f ) {
|
||
|
if ( timerOn ) {
|
||
|
timerOn = false;
|
||
|
CancelEvents( &EV_Speaker_Timer );
|
||
|
} else {
|
||
|
timerOn = true;
|
||
|
DoSound( true );
|
||
|
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
|
||
|
}
|
||
|
} else {
|
||
|
if ( refSound.referenceSound && ( gameLocal.time < playingUntilTime ) ) {
|
||
|
DoSound( false );
|
||
|
} else {
|
||
|
DoSound( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Event_Timer
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Event_Timer( void ) {
|
||
|
DoSound( true );
|
||
|
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Think
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Think( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idSound::UpdateChangableSpawnArgs
|
||
|
===============
|
||
|
*/
|
||
|
void idSound::UpdateChangeableSpawnArgs( const idDict *source ) {
|
||
|
|
||
|
idEntity::UpdateChangeableSpawnArgs( source );
|
||
|
|
||
|
if ( source ) {
|
||
|
FreeSoundEmitter( true );
|
||
|
spawnArgs.Copy( *source );
|
||
|
idSoundEmitter *saveRef = refSound.referenceSound;
|
||
|
gameEdit->ParseSpawnArgsToRefSound( spawnArgs, refSound );
|
||
|
refSound.referenceSound = saveRef;
|
||
|
|
||
|
idVec3 origin;
|
||
|
idMat3 axis;
|
||
|
|
||
|
if ( GetPhysicsToSoundTransform( origin, axis ) ) {
|
||
|
refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
|
||
|
} else {
|
||
|
refSound.origin = GetPhysics()->GetOrigin();
|
||
|
}
|
||
|
|
||
|
spawnArgs.GetFloat( "random", "0", random );
|
||
|
spawnArgs.GetFloat( "wait", "0", wait );
|
||
|
|
||
|
if ( ( wait > 0.0f ) && ( random >= wait ) ) {
|
||
|
random = wait - 0.001f;
|
||
|
gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
|
||
|
}
|
||
|
|
||
|
if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
|
||
|
timerOn = true;
|
||
|
DoSound( false );
|
||
|
CancelEvents( &EV_Speaker_Timer );
|
||
|
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
|
||
|
} else if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
|
||
|
// start it if it isn't already playing, and we aren't waitForTrigger
|
||
|
DoSound( true );
|
||
|
timerOn = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idSound::SetSound
|
||
|
===============
|
||
|
*/
|
||
|
void idSound::SetSound( const char *sound, int channel ) {
|
||
|
const idSoundShader *shader = declHolder.declSoundShaderType.LocalFind( sound );
|
||
|
if ( shader != refSound.shader ) {
|
||
|
FreeSoundEmitter( true );
|
||
|
}
|
||
|
gameEdit->ParseSpawnArgsToRefSound( spawnArgs, refSound );
|
||
|
refSound.shader = shader;
|
||
|
// start it if it isn't already playing, and we aren't waitForTrigger
|
||
|
if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
|
||
|
DoSound( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::DoSound
|
||
|
================
|
||
|
*/
|
||
|
void idSound::DoSound( bool play ) {
|
||
|
if ( play ) {
|
||
|
StartSoundShader( refSound.shader, SND_ANY, refSound.parms.soundShaderFlags, &playingUntilTime );
|
||
|
playingUntilTime += gameLocal.time;
|
||
|
soundOn = true;
|
||
|
} else {
|
||
|
StopSound( SND_ANY );
|
||
|
playingUntilTime = 0;
|
||
|
soundOn = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Event_On
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Event_On( void ) {
|
||
|
if ( wait > 0.0f ) {
|
||
|
timerOn = true;
|
||
|
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
|
||
|
}
|
||
|
DoSound( true );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::Event_Off
|
||
|
================
|
||
|
*/
|
||
|
void idSound::Event_Off( void ) {
|
||
|
if ( timerOn ) {
|
||
|
timerOn = false;
|
||
|
CancelEvents( &EV_Speaker_Timer );
|
||
|
}
|
||
|
DoSound( false );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idSound::ShowEditingDialog
|
||
|
===============
|
||
|
*/
|
||
|
void idSound::ShowEditingDialog( void ) {
|
||
|
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, va( "selectSpeaker '%s'", name.c_str() ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idSound::ApplyNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void idSound::ApplyNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& newState ) {
|
||
|
if ( mode == NSM_BROADCAST ) {
|
||
|
NET_GET_NEW( sdSoundBroadcastData );
|
||
|
|
||
|
DoSound( newData.isOn );
|
||
|
}
|
||
|
|
||
|
idEntity::ApplyNetworkState( mode, newState );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
idSound::ReadNetworkState
|
||
|
==============
|
||
|
*/
|
||
|
void idSound::ReadNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, const idBitMsg& msg ) const {
|
||
|
if ( mode == NSM_BROADCAST ) {
|
||
|
NET_GET_STATES( sdSoundBroadcastData );
|
||
|
|
||
|
newData.isOn = msg.ReadBool();
|
||
|
}
|
||
|
|
||
|
idEntity::ReadNetworkState( mode, baseState, newState, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
idSound::WriteNetworkState
|
||
|
==============
|
||
|
*/
|
||
|
void idSound::WriteNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, idBitMsg& msg ) const {
|
||
|
if ( mode == NSM_BROADCAST ) {
|
||
|
NET_GET_STATES( sdSoundBroadcastData );
|
||
|
|
||
|
newData.isOn = soundOn;
|
||
|
msg.WriteBool( newData.isOn );
|
||
|
}
|
||
|
|
||
|
idEntity::WriteNetworkState( mode, baseState, newState, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
idSound::CheckNetworkStateChanges
|
||
|
==============
|
||
|
*/
|
||
|
bool idSound::CheckNetworkStateChanges( networkStateMode_t mode, const sdEntityStateNetworkData& baseState ) const {
|
||
|
if ( mode == NSM_BROADCAST ) {
|
||
|
NET_GET_BASE( sdSoundBroadcastData );
|
||
|
|
||
|
if ( baseData.isOn != soundOn ) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return idEntity::CheckNetworkStateChanges( mode, baseState );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
idSound::CreateNetworkStructure
|
||
|
==============
|
||
|
*/
|
||
|
sdEntityStateNetworkData* idSound::CreateNetworkStructure( networkStateMode_t mode ) const {
|
||
|
if ( mode == NSM_BROADCAST ) {
|
||
|
return new sdSoundBroadcastData();
|
||
|
}
|
||
|
return idEntity::CreateNetworkStructure( mode );
|
||
|
}
|