00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdsound.h"
00027
00028 #include "env_sound_user.h"
00029 #include "sound.h"
00030 #include "bounding_shape.h"
00031 #include <stdlib.h>
00032
00033 using namespace std;
00034 using namespace NLMISC;
00035
00036
00037 namespace NLSOUND {
00038
00039
00040
00041
00042
00043 CEnvSoundUser::CEnvSoundUser() : _Play(false), _Source(NULL), _BoundingShape(NULL), _Transition(false), _Parent(NULL), _Mark(false), _Gain(1.0f)
00044 {
00045 }
00046
00047
00048
00049
00050
00051 CEnvSoundUser::~CEnvSoundUser()
00052 {
00053 vector<CEnvSoundUser*>::iterator ipe;
00054 for ( ipe=_Children.begin(); ipe!=_Children.end(); ++ipe )
00055 {
00056 delete (*ipe);
00057 }
00058
00059 vector<IPlayable*>::iterator ipp;
00060 for ( ipp=_SrcBank.begin(); ipp!=_SrcBank.end(); ++ipp )
00061 {
00062
00063
00064 if ( dynamic_cast<CSourceUser*>(*ipp) )
00065 {
00066 CAudioMixerUser::instance()->removeSource( static_cast<CSourceUser*>(*ipp) );
00067 }
00068 else
00069 {
00070 if ( (*ipp) != NULL )
00071 {
00072 delete (*ipp);
00073 }
00074 }
00075 }
00076
00077 if ( _BoundingShape != NULL )
00078 {
00079 delete _BoundingShape;
00080 }
00081 }
00082
00083
00084
00085
00086
00087 void CEnvSoundUser::serial( NLMISC::IStream& s )
00088 {
00089
00090
00091 s.serial( _Transition );
00092 s.serialPolyPtr( _BoundingShape );
00093 s.serialContPolyPtr( _SrcBank );
00094
00095 uint16 srcindex;
00096
00097 if ( s.isReading() )
00098 {
00099
00100 s.serial( srcindex );
00101 if ( ! _SrcBank.empty() )
00102 {
00103 _Source = _SrcBank[srcindex];
00104 }
00105 else
00106 {
00107 _Source = NULL;
00108 }
00109
00110
00111 if ( (_Source!=NULL) && (_BoundingShape != NULL) )
00112 {
00113 vector<IPlayable*>::iterator ipp;
00114 for ( ipp=_SrcBank.begin(); ipp!=_SrcBank.end(); ++ipp )
00115 {
00116 (*ipp)->moveTo( _BoundingShape->getCenter() );
00117 }
00118 }
00119
00120
00121 if ( ! _Transition )
00122 {
00123 if ( (_Source != NULL) )
00124 {
00125 vector<IPlayable*>::iterator ipp;
00126 if ( _BoundingShape != NULL )
00127 {
00128 for ( ipp=_SrcBank.begin(); ipp!=_SrcBank.end(); ++ipp )
00129 {
00130 (*ipp)->initPos( const_cast<CVector*>(&(_BoundingShape->getCenter())) );
00131 }
00132 }
00133 else
00134 {
00135
00136 for ( ipp=_SrcBank.begin(); ipp!=_SrcBank.end(); ++ipp )
00137 {
00138 (*ipp)->initPos( &CAudioMixerUser::instance()->getListenPosVector() );
00139 }
00140 }
00141 }
00142 }
00143 }
00144 else
00145 {
00146 uint i;
00147
00148 if ( _SrcBank.size() != 0 )
00149 {
00150 for ( i=0; i!=_SrcBank.size(); i++ )
00151 {
00152 if ( _SrcBank[i] == _Source )
00153 {
00154 break;
00155 }
00156 }
00157 nlassert( i != _SrcBank.size() );
00158 nlassert( i < 0x10000 );
00159 srcindex = i;
00160 }
00161 else
00162 {
00163 srcindex = 0;
00164 }
00165 s.serial( srcindex );
00166 }
00167
00168
00169 s.serialCont( _Tags );
00170 #ifdef NL_DEBUG
00171 DebugLog->display( "Envsound tags:");
00172 vector<string>::iterator ist;
00173 for ( ist=_Tags.begin(); ist!=_Tags.end(); ++ist )
00174 {
00175 DebugLog->displayRaw( (" " + (*ist)).c_str() );
00176 }
00177 DebugLog->displayRawNL("");
00178 #endif
00179
00180
00181 s.serialPtr( _Parent );
00182 s.serialContPtr( _Children );
00183 }
00184
00185
00186
00187
00188
00189 void CEnvSoundUser::selectEnv( const char *tag, bool children_too )
00190 {
00191 uint i;
00192 for ( i=0; i!= _Tags.size(); i++ )
00193 {
00194 if ( _Tags[i] == string(tag) )
00195 {
00196 if ( _Source != NULL )
00197 {
00198 _Source->enable( false, 1.0f );
00199 }
00200 _Source = _SrcBank[i];
00201 nldebug( "AM: EnvSound: Environment changed to %s", tag );
00202 CAudioMixerUser::instance()->getEnvSounds()->recompute();
00203 break;
00204 }
00205 }
00206
00207
00208
00209
00210 if ( children_too )
00211 {
00212 vector<CEnvSoundUser*>::iterator ipc;
00213 for ( ipc=_Children.begin(); ipc!=_Children.end(); ++ipc )
00214 {
00215 (*ipc)->selectEnv( tag, children_too );
00216 }
00217 }
00218 }
00219
00220
00221
00222
00223
00224 void CEnvSoundUser::serialFileHeader( NLMISC::IStream& s )
00225 {
00226
00227 s.serialCheck( (uint32)'SEN' );
00228 if ( s.serialVersion( 2 ) < 2 )
00229 {
00230 throw EOlderStream(s);
00231 }
00232
00233
00234 CSound::FileVersion = s.serialVersion( CSound::CurrentVersion );
00235 if ( CSound::FileVersion == 0 )
00236 {
00237
00238 throw EOlderStream(s);
00239 }
00240 }
00241
00242
00243
00244
00245
00246 uint32 CEnvSoundUser::getCount() const
00247 {
00248 uint32 cnt=1;
00249 vector<CEnvSoundUser*>::const_iterator ipe;
00250 for ( ipe=_Children.begin(); ipe!=_Children.end(); ++ipe )
00251 {
00252 cnt += (*ipe)->getCount();
00253 }
00254 return cnt;
00255 }
00256
00257
00258
00259
00260
00261 uint32 CEnvSoundUser::load( CEnvSoundUser* &envSoundTreeRoot, NLMISC::IStream& s )
00262 {
00263 if ( s.isReading() )
00264 {
00265 serialFileHeader( s );
00266 s.serialPtr( envSoundTreeRoot );
00267 return envSoundTreeRoot->getCount();
00268
00269
00270 CSound::FileVersion = CSound::CurrentVersion;
00271 }
00272 else
00273 {
00274 nlstop;
00275 return 0;
00276 }
00277 }
00278
00279
00280
00281
00282
00283 void CEnvSoundUser::update()
00284 {
00285 if ( _Source != NULL )
00286 {
00287 _Source->update();
00288 }
00289 vector<CEnvSoundUser*>::iterator ipe;
00290 for ( ipe=_Children.begin(); ipe!=_Children.end(); ++ipe )
00291 {
00292 (*ipe)->update();
00293 }
00294 }
00295
00296
00297
00298
00299
00300 CEnvSoundUser *CEnvSoundUser::findCurrentEnv( const NLMISC::CVector& listenerpos )
00301 {
00302
00303 vector<CEnvSoundUser*>::iterator ipe = _Children.begin();
00304 CEnvSoundUser *found = NULL;
00305 while ( ! ( (found) || (ipe==_Children.end()) ) )
00306 {
00307 found = (*ipe)->findCurrentEnv( listenerpos );
00308 ipe++;
00309 }
00310 if ( found )
00311 return found;
00312 else if ( (_BoundingShape == NULL) || (_BoundingShape->include( listenerpos )) )
00313 return this;
00314 else
00315 return NULL;
00316 }
00317
00318
00319
00320
00321
00322 void CEnvSoundUser::getPos( NLMISC::CVector& pos ) const
00323 {
00324 if ( _BoundingShape == NULL )
00325 {
00326 pos = CVector::Null;
00327 }
00328 else
00329 {
00330 pos = _BoundingShape->getCenter();
00331 }
00332 }
00333
00334
00335
00336
00337
00338 void CEnvSoundUser::setPos( const NLMISC::CVector& pos )
00339 {
00340 if ( _BoundingShape != NULL )
00341 {
00342
00343 CVector newpos;
00344 if ( (_Parent != NULL) && ( _Parent->_Transition ) )
00345 {
00346 newpos = pos + _Parent->_BoundingShape->getCenter() - _BoundingShape->getCenter();
00347 }
00348 else
00349 {
00350 newpos = pos;
00351 }
00352
00353
00354 _BoundingShape->setCenter( pos );
00355 if ( (_Parent != NULL) && ( _Parent->_Transition ) )
00356 {
00357 _Parent->_BoundingShape->setCenter( newpos );
00358 if ( _Parent->_Source != NULL )
00359 {
00360 _Parent->_Source->moveTo( newpos );
00361 }
00362 }
00363
00364
00365 CAudioMixerUser::instance()->getEnvSounds()->recompute();
00366 }
00367 }
00368
00369
00370
00371
00372
00373 std::vector<UEnvSound*>& CEnvSoundUser::getChildren()
00374 {
00375 return (vector<UEnvSound*>&)(_Children);
00376 }
00377
00378
00379
00380
00381
00382 void CEnvSoundUser::recompute()
00383 {
00384 nlassert( isRoot() );
00385
00386
00387 CVector listenerpos;
00388 CAudioMixerUser::instance()->getListener()->getPos( listenerpos );
00389 CEnvSoundUser *current = findCurrentEnv( listenerpos );
00390
00391
00392 if ( current != NULL )
00393 {
00394 current->markSources( listenerpos, 1.0f );
00395 }
00396
00397
00398 applySourcesMarks();
00399 }
00400
00401
00402
00403
00404
00405 void CEnvSoundUser::markSources( const NLMISC::CVector& listenerpos, float gain )
00406 {
00407
00408 if ( _Transition )
00409 {
00410
00411
00412
00413 nlassert( (_Children.size() == 1) && (_Children[0] != NULL) && (_Parent != NULL) );
00414 nlassert( _BoundingShape && _Children[0]->_BoundingShape );
00415 float ratio = _BoundingShape->getRatio( listenerpos, _Children[0]->_BoundingShape );
00416 nlassert( ratio >= 0.0f && ratio <= 1.0f );
00417
00418
00419
00420 _Children[0]->markSources( listenerpos, gain * ratio );
00421
00422
00423
00424 _Parent->markSources( listenerpos, gain * (1.0f-ratio) );
00425 }
00426 else
00427 {
00428
00429
00430
00431
00432 _Mark = true;
00433 _Gain = gain;
00434
00435
00436 vector<CEnvSoundUser*>::iterator ipe;
00437 for( ipe=_Children.begin(); ipe!=_Children.end(); ++ipe )
00438 {
00439 (*ipe)->_Mark = true;
00440 (*ipe)->_Gain = gain;
00441 }
00442 }
00443 }
00444
00445
00446
00447
00448
00449 void CEnvSoundUser::applySourcesMarks()
00450 {
00451 if ( ! _Play )
00452 {
00453 _Mark = false;
00454 }
00455 if ( _Source != NULL )
00456 {
00457 _Source->enable( _Mark, _Gain );
00458 }
00459 _Mark = false;
00460
00461
00462 vector<CEnvSoundUser*>::iterator ipe;
00463 for ( ipe=_Children.begin(); ipe!=_Children.end(); ++ipe )
00464 {
00465 (*ipe)->applySourcesMarks();
00466 }
00467 }
00468
00469
00470
00471
00472
00473 void CEnvSoundUser::setProperties( bool transition, IBoundingShape *bshape )
00474 {
00475 _Transition = transition;
00476 _BoundingShape = bshape;
00477 }
00478
00479
00480
00481
00482
00483
00484 void CEnvSoundUser::addEnvTag( IPlayable *source, const std::string& tag )
00485 {
00486 _SrcBank.push_back( source );
00487 _Tags.push_back( tag );
00488
00489 if ( _Source == NULL )
00490 {
00491 _Source = source;
00492 }
00493 }
00494
00495
00496
00497
00498
00499 void CEnvSoundUser::save( CEnvSoundUser *envSoundTreeRoot, NLMISC::IStream& s )
00500 {
00501 nlassert( ! s.isReading() );
00502 nlassert( envSoundTreeRoot->isRoot() );
00503
00504 serialFileHeader( s );
00505 s.serialPtr( envSoundTreeRoot );
00506 }
00507
00508
00509
00510
00511
00512 void CEnvSoundUser::play( bool children_too )
00513 {
00514 playSub( children_too );
00515
00516 CAudioMixerUser::instance()->getEnvSounds()->recompute();
00517 }
00518
00519
00520
00521
00522
00523 void CEnvSoundUser::stop( bool children_too )
00524 {
00525 stopSub( children_too );
00526
00527 CAudioMixerUser::instance()->getEnvSounds()->recompute();
00528 }
00529
00530
00531
00532
00533
00534 void CEnvSoundUser::playSub( bool children_too )
00535 {
00536 _Play = true;
00537
00538
00539 if ( (_Parent != NULL) && ( _Parent->_Transition ) )
00540 {
00541 _Parent->_Play = true;
00542 }
00543
00544
00545 if ( children_too )
00546 {
00547 vector<CEnvSoundUser*>::iterator ipc;
00548 for ( ipc=_Children.begin(); ipc!=_Children.end(); ++ipc )
00549 {
00550 (*ipc)->playSub( children_too );
00551 }
00552 }
00553 }
00554
00555
00556
00557
00558
00559 void CEnvSoundUser::stopSub( bool children_too )
00560 {
00561 _Play = false;
00562
00563
00564 if ( (_Parent != NULL) && ( _Parent->_Transition ) )
00565 {
00566 _Parent->_Play = false;
00567 }
00568
00569
00570 if ( children_too )
00571 {
00572 vector<CEnvSoundUser*>::iterator ipc;
00573 for ( ipc=_Children.begin(); ipc!=_Children.end(); ++ipc )
00574 {
00575 (*ipc)->stopSub( children_too );
00576 }
00577 }
00578 }
00579
00580
00581
00582
00583
00584 void CEnvSoundUser::addChild( CEnvSoundUser *child )
00585 {
00586 child->_Parent = this;
00587 _Children.push_back( child );
00588 }
00589
00590
00591 }