From 0787be500a134f82ded7930d1681aea003fa92f6 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 15 May 2018 19:49:17 +0200 Subject: [PATCH] build 180515. brake cylinder and doorstep sounds, comprehensive gauge update sound trigggers, vehicle removal from marked tracks, minor bug fixes --- DynObj.cpp | 268 ++++++++++++++++++++++++++++++++++++--------- DynObj.h | 13 ++- Gauge.cpp | 17 ++- Gauge.h | 10 +- McZapkie/MOVER.h | 2 +- McZapkie/Mover.cpp | 2 +- TrkFoll.cpp | 9 +- sound.cpp | 23 ++-- sound.h | 4 +- version.h | 2 +- 10 files changed, 266 insertions(+), 84 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 67e43ddd..47593521 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3882,14 +3882,40 @@ void TDynamicObject::RenderSounds() { // brake system and braking sounds: + + // brake cylinder piston + auto const brakepressureratio { std::max( 0.0, MoverParameters->BrakePress ) / std::max( 1.0, MoverParameters->MaxBrakePress[ 3 ] ) }; + if( m_lastbrakepressure != -1.f ) { + auto const quantizedratio { static_cast( 15 * brakepressureratio ) }; + auto const lastbrakepressureratio { std::max( 0.f, m_lastbrakepressure ) / std::max( 1.0, MoverParameters->MaxBrakePress[ 3 ] ) }; + auto const quantizedratiochange { quantizedratio - static_cast( 15 * lastbrakepressureratio ) }; + if( quantizedratiochange > 0 ) { + m_brakecylinderpistonadvance + .pitch( + true == m_brakecylinderpistonadvance.is_combined() ? + quantizedratio * 0.01f : + m_brakecylinderpistonadvance.m_frequencyoffset + m_brakecylinderpistonadvance.m_frequencyfactor * 1.f ) + .play(); + } + else if( quantizedratiochange < 0 ) { + m_brakecylinderpistonrecede + .pitch( + true == m_brakecylinderpistonrecede.is_combined() ? + quantizedratio * 0.01f : + m_brakecylinderpistonrecede.m_frequencyoffset + m_brakecylinderpistonrecede.m_frequencyfactor * 1.f ) + .play(); + } + } + + // air release if( m_lastbrakepressure != -1.f ) { // calculate rate of pressure drop in brake cylinder, once it's been initialized auto const brakepressuredifference{ m_lastbrakepressure - MoverParameters->BrakePress }; m_brakepressurechange = interpolate( m_brakepressurechange, brakepressuredifference / dt, 0.005f ); } m_lastbrakepressure = MoverParameters->BrakePress; - // ensure some basic level of volume and scale it up depending on pressure in the cylinder; scale this by the leak rate - volume = 20 * m_brakepressurechange * ( 0.25 + 0.75 * ( std::max( 0.0, MoverParameters->BrakePress ) / std::max( 1.0, MoverParameters->MaxBrakePress[ 3 ] ) ) ); + // ensure some basic level of volume and scale it up depending on pressure in the cylinder; scale this by the air release rate + volume = 20 * m_brakepressurechange * ( 0.25 + 0.75 * brakepressureratio ); if( volume > 0.075f ) { rsUnbrake .gain( volume ) @@ -3917,6 +3943,7 @@ void TDynamicObject::RenderSounds() { sReleaser.stop(); } + // slipping wheels if( MoverParameters->SlippingWheels ) { if( ( MoverParameters->UnitBrakeForce > 100.0 ) @@ -3940,6 +3967,7 @@ void TDynamicObject::RenderSounds() { sSand.stop(); } + // brakes auto brakeforceratio{ 0.0 }; if( //( false == mvOccupied->SlippingWheels ) && ( MoverParameters->UnitBrakeForce > 10.0 ) @@ -4016,47 +4044,96 @@ void TDynamicObject::RenderSounds() { } } // NBMX Obsluga drzwi, MC: zuniwersalnione - if( ( true == MoverParameters->DoorLeftOpened ) - && ( dDoorMoveL < MoverParameters->DoorMaxShiftL ) ) { - - for( auto &door : m_doorsounds ) { - if( door.rsDoorClose.offset().x > 0.f ) { - // determine left side doors from their offset - door.rsDoorOpen.play( sound_flags::exclusive ); - door.rsDoorClose.stop(); + if( true == MoverParameters->DoorLeftOpened ) { + // open left door + // door sounds + if( dDoorMoveL < MoverParameters->DoorMaxShiftL ) { + for( auto &door : m_doorsounds ) { + if( door.rsDoorClose.offset().x > 0.f ) { + // determine left side doors from their offset + door.rsDoorOpen.play( sound_flags::exclusive ); + door.rsDoorClose.stop(); + } + } + } + // doorstep sounds + if( dDoorstepMoveL < 1.0 ) { + for( auto &door : m_doorsounds ) { + if( door.step_close.offset().x > 0.f ) { + door.step_open.play( sound_flags::exclusive ); + door.step_close.stop(); + } } } } - if( ( false == MoverParameters->DoorLeftOpened ) - && ( dDoorMoveL > 0.01 ) ) { - - for( auto &door : m_doorsounds ) { - if( door.rsDoorClose.offset().x > 0.f ) { - // determine left side doors from their offset - door.rsDoorClose.play( sound_flags::exclusive ); - door.rsDoorOpen.stop(); + if( false == MoverParameters->DoorLeftOpened ) { + // close left door + // door sounds can start playing before the door begins moving + if( dDoorMoveL > 0.0 ) { + for( auto &door : m_doorsounds ) { + if( door.rsDoorClose.offset().x > 0.f ) { + // determine left side doors from their offset + door.rsDoorClose.play( sound_flags::exclusive ); + door.rsDoorOpen.stop(); + } + } + } + // doorstep sounds are played only when the doorstep is moving + if( ( dDoorstepMoveL > 0.0 ) + && ( dDoorstepMoveL < 1.0 ) ) { + for( auto &door : m_doorsounds ) { + if( door.step_close.offset().x > 0.f ) { + // determine left side doors from their offset + door.step_close.play( sound_flags::exclusive ); + door.step_open.stop(); + } } } } - if( ( true == MoverParameters->DoorRightOpened ) - && ( dDoorMoveR < MoverParameters->DoorMaxShiftR ) ) { - for( auto &door : m_doorsounds ) { - if( door.rsDoorClose.offset().x < 0.f ) { - // determine left side doors from their offset - door.rsDoorOpen.play( sound_flags::exclusive ); - door.rsDoorClose.stop(); + if( true == MoverParameters->DoorRightOpened ) { + // open right door + // door sounds + if( dDoorMoveR < MoverParameters->DoorMaxShiftR ) { + for( auto &door : m_doorsounds ) { + if( door.rsDoorClose.offset().x < 0.f ) { + // determine right side doors from their offset + door.rsDoorOpen.play( sound_flags::exclusive ); + door.rsDoorClose.stop(); + } + } + } + // doorstep sounds + if( dDoorstepMoveR < 1.0 ) { + for( auto &door : m_doorsounds ) { + if( door.step_close.offset().x < 0.f ) { + door.step_open.play( sound_flags::exclusive ); + door.step_close.stop(); + } } } } - if( ( false == MoverParameters->DoorRightOpened ) - && ( dDoorMoveR > 0.01 ) ) { - - for( auto &door : m_doorsounds ) { - if( door.rsDoorClose.offset().x < 0.f ) { - // determine left side doors from their offset - door.rsDoorClose.play( sound_flags::exclusive ); - door.rsDoorOpen.stop(); + if( false == MoverParameters->DoorRightOpened ) { + // close right door + // door sounds can start playing before the door begins moving + if( dDoorMoveR > 0.0 ) { + for( auto &door : m_doorsounds ) { + if( door.rsDoorClose.offset().x < 0.f ) { + // determine left side doors from their offset + door.rsDoorClose.play( sound_flags::exclusive ); + door.rsDoorOpen.stop(); + } + } + } + // doorstep sounds are played only when the doorstep is moving + if( ( dDoorstepMoveR > 0.0 ) + && ( dDoorstepMoveR < 1.0 ) ) { + for( auto &door : m_doorsounds ) { + if( door.step_close.offset().x < 0.f ) { + // determine left side doors from their offset + door.step_close.play( sound_flags::exclusive ); + door.step_open.stop(); + } } } } @@ -5136,6 +5213,18 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, rsPisk.m_amplitudeoffset *= ( 105.f - Random( 10.f ) ) / 100.f; } + else if( token == "brakecylinderinc:" ) { + // brake cylinder pressure increase sounds + m_brakecylinderpistonadvance.deserialize( parser, sound_type::single ); + m_brakecylinderpistonadvance.owner( this ); + } + + else if( token == "brakecylinderdec:" ) { + // brake cylinder pressure decrease sounds + m_brakecylinderpistonrecede.deserialize( parser, sound_type::single ); + m_brakecylinderpistonrecede.owner( this ); + } + else if( token == "brakeacc:" ) { // plik z przyspieszaczem (upust po zlapaniu hamowania) sBrakeAcc.deserialize( parser, sound_type::single ); @@ -5234,29 +5323,53 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, } else if( token == "dooropen:" ) { - sound_source doortemplate { sound_placement::general }; - doortemplate.deserialize( parser, sound_type::single ); - doortemplate.owner( this ); + sound_source soundtemplate { sound_placement::general }; + soundtemplate.deserialize( parser, sound_type::single ); + soundtemplate.owner( this ); for( auto &door : m_doorsounds ) { // apply configuration to all defined doors, but preserve their individual offsets auto const dooroffset { door.rsDoorOpen.offset() }; - door.rsDoorOpen = doortemplate; + door.rsDoorOpen = soundtemplate; door.rsDoorOpen.offset( dooroffset ); } } else if( token == "doorclose:" ) { - sound_source doortemplate { sound_placement::general }; - doortemplate.deserialize( parser, sound_type::single ); - doortemplate.owner( this ); + sound_source soundtemplate { sound_placement::general }; + soundtemplate.deserialize( parser, sound_type::single ); + soundtemplate.owner( this ); for( auto &door : m_doorsounds ) { // apply configuration to all defined doors, but preserve their individual offsets auto const dooroffset { door.rsDoorClose.offset() }; - door.rsDoorClose = doortemplate; + door.rsDoorClose = soundtemplate; door.rsDoorClose.offset( dooroffset ); } } + else if( token == "doorstepopen:" ) { + sound_source soundtemplate { sound_placement::general }; + soundtemplate.deserialize( parser, sound_type::single ); + soundtemplate.owner( this ); + for( auto &door : m_doorsounds ) { + // apply configuration to all defined doors, but preserve their individual offsets + auto const dooroffset { door.step_open.offset() }; + door.step_open = soundtemplate; + door.step_open.offset( dooroffset ); + } + } + + else if( token == "doorstepclose:" ) { + sound_source soundtemplate { sound_placement::general }; + soundtemplate.deserialize( parser, sound_type::single ); + soundtemplate.owner( this ); + for( auto &door : m_doorsounds ) { + // apply configuration to all defined doors, but preserve their individual offsets + auto const dooroffset { door.step_close.offset() }; + door.step_close = soundtemplate; + door.step_close.offset( dooroffset ); + } + } + else if( token == "unloading:" ) { m_exchangesounds.unloading.deserialize( parser, sound_type::single ); m_exchangesounds.unloading.owner( this ); @@ -5336,6 +5449,8 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, auto const location { glm::vec3 { MoverParameters->Dim.W * 0.5f, MoverParameters->Dim.H * 0.5f, offset } }; door.rsDoorClose.offset( location ); door.rsDoorOpen.offset( location ); + door.step_close.offset( location ); + door.step_open.offset( location ); m_doorsounds.emplace_back( door ); } if( ( sides == "both" ) @@ -5344,6 +5459,8 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, auto const location { glm::vec3 { MoverParameters->Dim.W * -0.5f, MoverParameters->Dim.H * 0.5f, offset } }; door.rsDoorClose.offset( location ); door.rsDoorOpen.offset( location ); + door.step_close.offset( location ); + door.step_open.offset( location ); m_doorsounds.emplace_back( door ); } } @@ -6570,19 +6687,9 @@ vehicle_table::update( double Deltatime, int Iterationcount ) { // Ra 2015-01: tylko tu przelicza sieć trakcyjną vehicle->Update( Deltatime, totaltime ); } -/* - // TODO: re-implement - if (TDynamicObject::bDynamicRemove) - { // jeśli jest coś do usunięcia z listy, to trzeba na końcu - for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext) - if ( false == Current->DynamicObject->bEnabled) - { - DynamicRemove(Current->DynamicObject); // usunięcie tego i podłączonych - Current = nRootDynamic; // sprawdzanie listy od początku - } - TDynamicObject::bDynamicRemove = false; // na razie koniec - } -*/ + + // jeśli jest coś do usunięcia z listy, to trzeba na końcu + erase_disabled(); } // legacy method, checks for presence and height of traction wire for specified vehicle @@ -6693,3 +6800,56 @@ vehicle_table::DynamicList( bool const Onlycontrolled ) const { // informacja o końcu listy multiplayer::WyslijString( "none", 6 ); } + +// maintenance; removes from tracks consists with vehicles marked as disabled +bool +vehicle_table::erase_disabled() { + + if( false == TDynamicObject::bDynamicRemove ) { return false; } + + // go through the list and retrieve vehicles scheduled for removal... + type_sequence disabledvehicles; + for( auto *vehicle : m_items ) { + if( false == vehicle->bEnabled ) { + disabledvehicles.emplace_back( vehicle ); + } + } + // ...now propagate removal flag through affected consists... + for( auto *vehicle : disabledvehicles ) { + TDynamicObject *coupledvehicle { vehicle }; + while( ( coupledvehicle = coupledvehicle->Next() ) != nullptr ) { + coupledvehicle->bEnabled = false; + } + // (try to) run propagation in both directions, it's simpler than branching based on direction etc + coupledvehicle = vehicle; + while( ( coupledvehicle = coupledvehicle->Prev() ) != nullptr ) { + coupledvehicle->bEnabled = false; + } + } + // ...then actually remove all disabled vehicles... + auto vehicleiter = std::begin( m_items ); + while( vehicleiter != std::end( m_items ) ) { + + auto *vehicle { *vehicleiter }; + + if( true == vehicle->bEnabled ) { + ++vehicleiter; + } + else { + if( vehicle->MyTrack != nullptr ) { + vehicle->MyTrack->RemoveDynamicObject( vehicle ); + } + // clear potential train binding + Global.pWorld->TrainDelete( vehicle ); + // remove potential entries in the light array + simulation::Lights.remove( vehicle ); + // finally get rid of the vehicle and its record themselves + SafeDelete( vehicle ); + vehicleiter = m_items.erase( vehicleiter ); + } + } + // ...and call it a day + TDynamicObject::bDynamicRemove = false; + + return true; +} diff --git a/DynObj.h b/DynObj.h index 8ed4913e..597abed9 100644 --- a/DynObj.h +++ b/DynObj.h @@ -307,6 +307,8 @@ private: struct door_sounds { sound_source rsDoorOpen { sound_placement::general, 25.f }; // Ra: przeniesione z kabiny sound_source rsDoorClose { sound_placement::general, 25.f }; + sound_source step_open { sound_placement::general, 25.f }; + sound_source step_close { sound_placement::general, 25.f }; }; struct exchange_sounds { @@ -408,8 +410,10 @@ private: bool bBrakeAcc { false }; sound_source rsPisk { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // McZapkie-260302 sound_source rsUnbrake { sound_placement::external }; // yB - odglos luzowania - float m_lastbrakepressure { -1.f }; // helper, cached level of pressure in brake cylinder - float m_brakepressurechange { 0.f }; // recent change of pressure in brake cylinder + sound_source m_brakecylinderpistonadvance { sound_placement::external }; + sound_source m_brakecylinderpistonrecede { sound_placement::external }; + float m_lastbrakepressure { -1.f }; // helper, cached level of pressure in the brake cylinder + float m_brakepressurechange { 0.f }; // recent change of pressure in the brake cylinder sound_source sReleaser { sound_placement::external }; sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab sound_source sSand { sound_placement::external }; @@ -618,6 +622,11 @@ public: // legacy method, sends list of vehicles over network void DynamicList( bool const Onlycontrolled = false ) const; + +private: + // maintenance; removes from tracks consists with vehicles marked as disabled + bool + erase_disabled(); }; //--------------------------------------------------------------------------- diff --git a/Gauge.cpp b/Gauge.cpp index cb1b8440..c7e5ad1e 100644 --- a/Gauge.cpp +++ b/Gauge.cpp @@ -21,6 +21,13 @@ http://mozilla.org/MPL/2.0/. #include "logs.h" #include "renderer.h" +TGauge::TGauge( sound_source const &Soundtemplate ) : + m_soundtemplate( Soundtemplate ) +{ + m_soundfxincrease = m_soundtemplate; + m_soundfxdecrease = m_soundtemplate; +} + void TGauge::Init(TSubModel *Submodel, TGaugeType Type, float Scale, float Offset, float Friction, float Value, float const Endvalue, float const Endscale, bool const Interpolatescale ) { // ustawienie parametrów animacji submodelu SubModel = Submodel; @@ -172,7 +179,7 @@ TGauge::Load_mapping( cParser &Input ) { if( indexstart != std::string::npos ) { m_soundfxvalues.emplace( std::stoi( key.substr( indexstart, indexend - indexstart ) ), - sound_source( sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE ).deserialize( Input, sound_type::single ) ); + sound_source( m_soundtemplate ).deserialize( Input, sound_type::single ) ); } } return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized @@ -333,13 +340,15 @@ void TGauge::UpdateValue() switch (m_datatype) { // to nie jest zbyt optymalne, można by zrobić osobne funkcje case 'f': - m_targetvalue = (*fData); + UpdateValue( *fData ); break; case 'd': - m_targetvalue = (*dData); + UpdateValue( *dData ); break; case 'i': - m_targetvalue = (*iData); + UpdateValue( *iData ); + break; + default: break; } }; diff --git a/Gauge.h b/Gauge.h index 40f82cca..87e78781 100644 --- a/Gauge.h +++ b/Gauge.h @@ -27,8 +27,11 @@ class TGauge { public: // methods TGauge() = default; + explicit TGauge( sound_source const &Soundtemplate ); + inline - void Clear() { *this = TGauge(); } + void Clear() { + *this = TGauge(); } void Init(TSubModel *Submodel, TGaugeType Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false ); bool Load(cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2 = nullptr, double mul = 1.0); void UpdateValue( float fNewDesired ); @@ -73,8 +76,9 @@ private: double *dData { nullptr }; int *iData; }; - sound_source m_soundfxincrease { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // sound associated with increasing control's value - sound_source m_soundfxdecrease { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // sound associated with decreasing control's value + sound_source m_soundtemplate { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // shared properties for control's sounds + sound_source m_soundfxincrease { m_soundtemplate }; // sound associated with increasing control's value + sound_source m_soundfxdecrease { m_soundtemplate }; // sound associated with decreasing control's value std::map m_soundfxvalues; // sounds associated with specific values }; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index a645a342..ecf35362 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -637,7 +637,7 @@ struct oil_pump { start start_type { start::manual }; float resource_amount { 1.f }; float pressure_minimum { 0.f }; // lowest acceptable working pressure - float pressure_maximum { 0.f }; // oil pressure at maximum engine revolutions + float pressure_maximum { 0.65f }; // oil pressure at maximum engine revolutions float pressure_target { 0.f }; float pressure_present { 0.f }; }; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 015622e8..63198517 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6379,7 +6379,7 @@ void TMoverParameters::dizel_Heat( double const dt ) { // olej oddaje cieplo do wody gdy krazy przez wymiennik ciepla == wlaczona pompka lub silnik auto const dTo { ( dizel_heat.auxiliary_water_circuit ? - ( ( dizel_heat.kfo * ( dizel_heat.Ts - dizel_heat.To ) ) - ( dizel_heat.kfs * ( 0.3 ) * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gwO * Co ) : + ( ( dizel_heat.kfo * ( dizel_heat.Ts - dizel_heat.To ) ) - ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gwO * Co ) : ( ( dizel_heat.kfo * ( dizel_heat.Ts - dizel_heat.To ) ) - ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr ) ) ) / ( gwO * Co ) ) }; dizel_heat.To += ( dTo * dt ); diff --git a/TrkFoll.cpp b/TrkFoll.cpp index 0cc0f6d1..9427fae6 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -227,8 +227,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) { // jeśli przekroczenie toru od strony Point2 bCanSkip = ( bPrimary && pCurrentTrack->CheckDynamicObject( Owner ) ); if (bCanSkip) // tylko główna oś przenosi pojazd do innego toru - Owner->MyTrack->RemoveDynamicObject( - Owner); // zdejmujemy pojazd z dotychczasowego toru + Owner->MyTrack->RemoveDynamicObject(Owner); // zdejmujemy pojazd z dotychczasowego toru fDistance = s - pCurrentSegment->GetLength(); dir = fDirection; if (pCurrentTrack->eType == tt_Cross) @@ -236,8 +235,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 1)) return false; // wyjście z błędem } - else if (!SetCurrentTrack(pCurrentTrack->Connected(1, fDirection), - 1)) // ustawia fDirection + else if (!SetCurrentTrack(pCurrentTrack->Connected(1, fDirection), 1)) // ustawia fDirection return false; // wyjście z błędem if (dir != fDirection) //(pCurrentTrack->iNextDirection) { // gdy zmiana kierunku toru (Point2->Point2) @@ -249,8 +247,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if (bCanSkip) { // jak główna oś, to dodanie pojazdu do nowego toru pCurrentTrack->AddDynamicObject(Owner); - iEventFlag = - 3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru + iEventFlag = 3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru iEventallFlag = 3; if (!Owner->MyTrack) return false; diff --git a/sound.cpp b/sound.cpp index d634b385..bd903e66 100644 --- a/sound.cpp +++ b/sound.cpp @@ -216,7 +216,7 @@ sound_source::deserialize_mapping( cParser &Input ) { auto const pitch { Input.getToken( false, "\n\r\t ,;" ) }; for( auto &chunk : m_soundchunks ) { if( chunk.second.threshold == index ) { - chunk.second.pitch = pitch; + chunk.second.pitch = ( pitch > 0.f ? pitch : 1.f ); break; } } @@ -386,8 +386,9 @@ sound_source::play_combined() { if( soundpoint < soundchunk.second.fadein ) { break; } if( soundpoint >= soundchunk.second.fadeout ) { continue; } - if( ( soundchunk.first.playing > 0 ) - || ( soundchunk.first.buffer == null_handle ) ) { + if( ( soundchunk.first.buffer == null_handle ) + || ( ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) != 0 ) + && ( soundchunk.first.playing > 0 ) ) ) { // combined sounds only play looped, single copy of each activated chunk continue; } @@ -612,13 +613,15 @@ sound_source::update_combined( audio::openal_source &Source ) { */ if( ( soundhandle & sound_id::chunk ) != 0 ) { // for sound chunks, test whether the chunk should still be active given current value of the controlling variable - auto const soundpoint { compute_combined_point() }; - auto const &soundchunk { m_soundchunks[ soundhandle ^ sound_id::chunk ] }; - if( ( soundpoint < soundchunk.second.fadein ) - || ( soundpoint >= soundchunk.second.fadeout ) ) { - Source.stop(); - update_counter( soundhandle, -1 ); - return; + if( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) != 0 ) { + auto const soundpoint { compute_combined_point() }; + auto const &soundchunk { m_soundchunks[ soundhandle ^ sound_id::chunk ] }; + if( ( soundpoint < soundchunk.second.fadein ) + || ( soundpoint >= soundchunk.second.fadeout ) ) { + Source.stop(); + update_counter( soundhandle, -1 ); + return; + } } } diff --git a/sound.h b/sound.h index 55a0a1ed..004e662b 100644 --- a/sound.h +++ b/sound.h @@ -30,8 +30,8 @@ enum sound_parameters { }; enum sound_flags { - looping = 0x1, // the main sample will be looping; implied for multi-sounds - exclusive = 0x2, // the source won't dispatch more than one active instance of the sound; implied for multi-sounds + looping = 0x1, // the main sample will be looping + exclusive = 0x2, // the source won't dispatch more than one active instance of the sound event = 0x80 // sound was activated by an event; we should keep note of the activation state for the update() calls it may receive }; diff --git a/version.h b/version.h index 6e8f9b75..cf8ca48a 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 508 +#define VERSION_MINOR 515 #define VERSION_REVISION 0