From d1327742e7ae13b6ae39952928a6899453a57542 Mon Sep 17 00:00:00 2001 From: BeaR Date: Thu, 27 Nov 2014 16:18:15 +0100 Subject: [PATCH 1/6] Start adding support for custom shaped audio fields Add version check for sound layers --- src/game/client/components/mapsounds.cpp | 6 ++++ src/game/editor/io.cpp | 3 ++ src/game/mapitems.h | 35 +++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index 7f1e578e9..408d72c9d 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -63,6 +63,9 @@ void CMapSounds::OnMapLoad() { CMapItemLayerSounds *pSoundLayer = (CMapItemLayerSounds *)pLayer; + if(pSoundLayer->m_Version < 1 || pSoundLayer->m_Version > CMapItemLayerSounds::CURRENT_VERSION) + continue; + if(pSoundLayer->m_Sound == -1) continue; @@ -149,6 +152,9 @@ void CMapSounds::OnRender() if(pLayer->m_Type == LAYERTYPE_SOUNDS) { CMapItemLayerSounds *pSoundLayer = (CMapItemLayerSounds *)pLayer; + + if(pSoundLayer->m_Version < 1 || pSoundLayer->m_Version > CMapItemLayerSounds::CURRENT_VERSION) + continue; CSoundSource *pSources = (CSoundSource *)Layers()->Map()->GetDataSwapped(pSoundLayer->m_Data); diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index e46d4f310..bf67892f4 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -996,6 +996,9 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag else if(pLayerItem->m_Type == LAYERTYPE_SOUNDS) { CMapItemLayerSounds *pSoundsItem = (CMapItemLayerSounds *)pLayerItem; + if(pSoundsItem->m_Version < 1 || pSoundsItem->m_Version > CMapItemLayerSounds::CURRENT_VERSION) + continue; + CLayerSounds *pSounds = new CLayerSounds; pSounds->m_pEditor = m_pEditor; pLayer = pSounds; diff --git a/src/game/mapitems.h b/src/game/mapitems.h index b0aa01a95..e603d42eb 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -18,6 +18,7 @@ enum LAYERTYPE_SPEEDUP, LAYERTYPE_SWITCH, LAYERTYPE_TUNE, + LAYERTYPE_SOUNDS_DEPRECATED, // deprecated! do not use this, this is just for compatibility reasons LAYERTYPE_SOUNDS, MAPITEMTYPE_VERSION=0, @@ -329,23 +330,55 @@ struct CMapItemEnvelope : public CMapItemEnvelope_v1 int m_Synchronized; }; +struct CSoundShape +{ + enum + { + SHAPE_RECTANGLE, + SHAPE_CIRCLE, + NUM_SHAPES, + }; + + struct CRectangle + { + int m_PosX, m_PosY; // fxp 22.10 + int m_Width, m_Height; // fxp 22.10 + }; + + struct CCircle + { + int m_PosX, m_PosY; // fxp 22.10 + int m_Radius; // fxp 22.10 + }; + + int m_Type; + + union + { + CRectangle m_Rectangle; + CCircle m_Circle; + }; +}; + struct CSoundSource { CPoint m_Position; int m_Loop; int m_TimeDelay; // in s int m_FalloffDistance; + int m_Falloff; // [0,255] // 0 - No falloff, 255 - full int m_PosEnv; int m_PosEnvOffset; int m_SoundEnv; int m_SoundEnvOffset; + CSoundShape m_Shape; }; struct CMapItemLayerSounds { - enum { CURRENT_VERSION=1 }; + enum { CURRENT_VERSION=2 }; CMapItemLayer m_Layer; int m_Version; From 99967511613d418ab61681097651ec498bf79786 Mon Sep 17 00:00:00 2001 From: BeaR Date: Fri, 28 Nov 2014 19:21:59 +0100 Subject: [PATCH 2/6] Remove deprecated falloff distance --- src/engine/client/sound.cpp | 20 +------------------- src/engine/client/sound.h | 1 - src/engine/sound.h | 1 - src/game/client/components/mapsounds.cpp | 1 - src/game/editor/layer_sounds.cpp | 3 +-- src/game/editor/popups.cpp | 2 -- src/game/mapitems.h | 1 - 7 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 5b7b483cd..23e20a799 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -49,7 +49,6 @@ struct CVoice int m_Age; // increases when reused int m_Tick; int m_Vol; // 0 - 255 - int m_FalloffDistance; // 0 - inifinitee (well int) int m_Flags; int m_X, m_Y; } ; @@ -137,7 +136,7 @@ static void Mix(short *pFinalOut, unsigned Frames) int dy = v->m_Y - m_CenterY; int Dist = (int)sqrtf((float)dx*dx+dy*dy); // float here. nasty int p = IntAbs(dx); - int Range = v->m_FalloffDistance; + int Range = DefaultDistance; if(Dist >= 0 && Dist < Range) { // panning @@ -646,22 +645,6 @@ void CSound::SetVoiceVolume(CVoiceHandle Voice, float Volume) m_aVoices[VoiceID].m_Vol = (int)(Volume*255.0f); } -void CSound::SetVoiceMaxDistance(CVoiceHandle Voice, int Distance) -{ - if(!Voice.IsValid()) - return; - - int VoiceID = Voice.Id(); - - if(m_aVoices[VoiceID].m_Age != Voice.Age()) - return; - - if(Distance < 0) - return; - - m_aVoices[VoiceID].m_FalloffDistance = Distance; -} - void CSound::SetVoiceLocation(CVoiceHandle Voice, float x, float y) { if(!Voice.IsValid()) @@ -752,7 +735,6 @@ ISound::CVoiceHandle CSound::Play(int ChannelID, int SampleID, int Flags, float m_aVoices[VoiceID].m_Flags = Flags; m_aVoices[VoiceID].m_X = (int)x; m_aVoices[VoiceID].m_Y = (int)y; - m_aVoices[VoiceID].m_FalloffDistance = DefaultDistance; Age = m_aVoices[VoiceID].m_Age; } diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index 98b429888..4fc133384 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -41,7 +41,6 @@ public: virtual void SetChannel(int ChannelID, float Vol, float Pan); virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume); - virtual void SetVoiceMaxDistance(CVoiceHandle Voice, int Distance); virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y); virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float offset); // in s diff --git a/src/engine/sound.h b/src/engine/sound.h index 78d51580b..405bb0f8d 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -48,7 +48,6 @@ public: virtual void SetListenerPos(float x, float y) = 0; virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume) = 0; - virtual void SetVoiceMaxDistance(CVoiceHandle Voice, int Distance) = 0; virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y) = 0; virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float offset) = 0; // in s diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index 408d72c9d..0b815e741 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -122,7 +122,6 @@ void CMapSounds::OnRender() if(pSource->m_pSource->m_Loop) Flags |= ISound::FLAG_LOOP; pSource->m_Voice = m_pClient->m_pSounds->PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[pSource->m_Sound], 1.0f, vec2(fx2f(pSource->m_pSource->m_Position.x), fx2f(pSource->m_pSource->m_Position.y)), Flags); - Sound()->SetVoiceMaxDistance(pSource->m_Voice, pSource->m_pSource->m_FalloffDistance); Sound()->SetVoiceTimeOffset(pSource->m_Voice, offset); } } diff --git a/src/game/editor/layer_sounds.cpp b/src/game/editor/layer_sounds.cpp index d925c97ac..8b234e3c4 100644 --- a/src/game/editor/layer_sounds.cpp +++ b/src/game/editor/layer_sounds.cpp @@ -40,7 +40,7 @@ void CLayerSounds::Render() OffsetY = aChannels[1]; } - m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, pSource->m_FalloffDistance, 32); + m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, 2500.0f, 32); // fix } Graphics()->QuadsEnd(); @@ -84,7 +84,6 @@ CSoundSource *CLayerSounds::NewSource() pSource->m_Loop = 1; pSource->m_TimeDelay = 0; - pSource->m_FalloffDistance = 1500; pSource->m_PosEnv = -1; pSource->m_PosEnvOffset = 0; diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 94e0cf12a..7dea9b877 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -643,7 +643,6 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) {"Pos Y", pSource->m_Position.y/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Loop", pSource->m_Loop, PROPTYPE_BOOL, 0, 1}, {"Delay", pSource->m_TimeDelay, PROPTYPE_INT_SCROLL, 0, 1000000}, - {"Distance", pSource->m_FalloffDistance, PROPTYPE_INT_SCROLL, 0, 1000000}, {"Pos. Env", pSource->m_PosEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1}, {"Pos. TO", pSource->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Sound Env", pSource->m_SoundEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1}, @@ -662,7 +661,6 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) if(Prop == PROP_POS_Y) pSource->m_Position.y = NewVal*1000; if(Prop == PROP_LOOP) pSource->m_Loop = NewVal; if(Prop == PROP_TIME_DELAY) pSource->m_TimeDelay = NewVal; - if(Prop == PROP_DISTANCE) pSource->m_FalloffDistance = NewVal; if(Prop == PROP_POS_ENV) { int Index = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); diff --git a/src/game/mapitems.h b/src/game/mapitems.h index e603d42eb..a23cc3f08 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -365,7 +365,6 @@ struct CSoundSource CPoint m_Position; int m_Loop; int m_TimeDelay; // in s - int m_FalloffDistance; int m_Falloff; // [0,255] // 0 - No falloff, 255 - full int m_PosEnv; From a045a20fbaa69d88f847ac4878e605037c102add Mon Sep 17 00:00:00 2001 From: BeaR Date: Fri, 28 Nov 2014 20:01:25 +0100 Subject: [PATCH 3/6] Render sound shapes --- src/game/editor/layer_sounds.cpp | 28 +++++++++++++++++++++++++++- src/game/mapitems.h | 4 +--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/game/editor/layer_sounds.cpp b/src/game/editor/layer_sounds.cpp index 8b234e3c4..fea83c517 100644 --- a/src/game/editor/layer_sounds.cpp +++ b/src/game/editor/layer_sounds.cpp @@ -40,7 +40,23 @@ void CLayerSounds::Render() OffsetY = aChannels[1]; } - m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, 2500.0f, 32); // fix + switch(pSource->m_Shape.m_Type) + { + case CSoundShape::SHAPE_CIRCLE: + { + m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, + pSource->m_Shape.m_Circle.m_Radius, 32); + break; + } + case CSoundShape::SHAPE_RECTANGLE: + { + float Width = fx2f(pSource->m_Shape.m_Rectangle.m_Width); + float Height = fx2f(pSource->m_Shape.m_Rectangle.m_Height); + m_pEditor->RenderTools()->DrawRoundRect(fx2f(pSource->m_Position.x)+OffsetX - Width/2, fx2f(pSource->m_Position.y)+OffsetY - Height/2, + Width, Height, 0.0f); + break; + } + } } Graphics()->QuadsEnd(); @@ -90,6 +106,16 @@ CSoundSource *CLayerSounds::NewSource() pSource->m_SoundEnv = -1; pSource->m_SoundEnvOffset = 0; + pSource->m_Falloff = 255; + /* + pSource->m_Shape.m_Type = CSoundShape::SHAPE_CIRCLE; + pSource->m_Shape.m_Circle.m_Radius = 1500; + */ + + pSource->m_Shape.m_Type = CSoundShape::SHAPE_RECTANGLE; + pSource->m_Shape.m_Rectangle.m_Width = f2fx(1500.0f); + pSource->m_Shape.m_Rectangle.m_Height = f2fx(1000.0f); + return pSource; } diff --git a/src/game/mapitems.h b/src/game/mapitems.h index a23cc3f08..f41e6550d 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -341,14 +341,12 @@ struct CSoundShape struct CRectangle { - int m_PosX, m_PosY; // fxp 22.10 int m_Width, m_Height; // fxp 22.10 }; struct CCircle { - int m_PosX, m_PosY; // fxp 22.10 - int m_Radius; // fxp 22.10 + int m_Radius; }; int m_Type; From fbcd560eb08c67d14c8a1982716da85a2d19e74b Mon Sep 17 00:00:00 2001 From: BeaR Date: Fri, 28 Nov 2014 20:25:43 +0100 Subject: [PATCH 4/6] Working on adding editor UI support for sound shapes --- src/game/editor/popups.cpp | 75 +++++++++++++++++++++++++++++++++++++- src/game/mapitems.h | 2 +- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 7dea9b877..34a0175b9 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -624,13 +624,46 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) return 1; } + // Sound shape button + CUIRect ShapeButton; + View.HSplitBottom(5.0f, &View, 0x0); + View.HSplitBottom(12.0f, &View, &ShapeButton); + static int s_ShapeTypeButton = 0; + + static const char *s_aShapeNames[] = { + "Rectangle", + "Circle" + }; + + if(pEditor->DoButton_Editor(&s_ShapeTypeButton, s_aShapeNames[pSource->m_Shape.m_Type], 0, &ShapeButton, 0, "Change shape")) + { + pSource->m_Shape.m_Type = (pSource->m_Shape.m_Type+1)%CSoundShape::NUM_SHAPES; + + // set default values + switch(pSource->m_Shape.m_Type) + { + case CSoundShape::SHAPE_CIRCLE: + { + pSource->m_Shape.m_Circle.m_Radius = 1000.0f; + break; + } + case CSoundShape::SHAPE_RECTANGLE: + { + pSource->m_Shape.m_Rectangle.m_Width = f2fx(1000.0f); + pSource->m_Shape.m_Rectangle.m_Height = f2fx(800.0f); + break; + } + } + } + + enum { PROP_POS_X=0, PROP_POS_Y, PROP_LOOP, PROP_TIME_DELAY, - PROP_DISTANCE, + PROP_FALLOFF, PROP_POS_ENV, PROP_POS_ENV_OFFSET, PROP_SOUND_ENV, @@ -643,6 +676,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) {"Pos Y", pSource->m_Position.y/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Loop", pSource->m_Loop, PROPTYPE_BOOL, 0, 1}, {"Delay", pSource->m_TimeDelay, PROPTYPE_INT_SCROLL, 0, 1000000}, + {"Falloff", pSource->m_Falloff, PROPTYPE_INT_SCROLL, 0, 255}, {"Pos. Env", pSource->m_PosEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1}, {"Pos. TO", pSource->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Sound Env", pSource->m_SoundEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1}, @@ -651,6 +685,8 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) {0}, }; + + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); @@ -661,6 +697,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) if(Prop == PROP_POS_Y) pSource->m_Position.y = NewVal*1000; if(Prop == PROP_LOOP) pSource->m_Loop = NewVal; if(Prop == PROP_TIME_DELAY) pSource->m_TimeDelay = NewVal; + if(Prop == PROP_FALLOFF) pSource->m_Falloff = NewVal; if(Prop == PROP_POS_ENV) { int Index = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); @@ -692,6 +729,42 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) } if(Prop == PROP_SOUND_ENV_OFFSET) pSource->m_SoundEnvOffset = NewVal; + // source shape properties + switch(pSource->m_Shape.m_Type) + { + case CSoundShape::SHAPE_CIRCLE: + { + enum + { + PROP_CIRCLE_RADIUS=0, + NUM_CIRCLE_PROPS, + }; + + CProperty aCircleProps[] = { + {"Radius", pSource->m_Shape.m_Circle.m_Radius, PROPTYPE_INT_SCROLL, 0, 1000000}, + + {0}, + }; + + static int s_aCircleIds[NUM_CIRCLE_PROPS] = {0}; + + NewVal = 0; + Prop = pEditor->DoProperties(&View, aCircleProps, s_aCircleIds, &NewVal); + if(Prop != -1) + pEditor->m_Map.m_Modified = true; + + if(Prop == PROP_CIRCLE_RADIUS) pSource->m_Shape.m_Circle.m_Radius = NewVal; + + break; + } + + case CSoundShape::SHAPE_RECTANGLE: + { + break; + } + } + + return 0; } diff --git a/src/game/mapitems.h b/src/game/mapitems.h index f41e6550d..3158c6541 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -334,7 +334,7 @@ struct CSoundShape { enum { - SHAPE_RECTANGLE, + SHAPE_RECTANGLE = 0, SHAPE_CIRCLE, NUM_SHAPES, }; From 485aa4ce54658a6246106d52d01620e00ea09e94 Mon Sep 17 00:00:00 2001 From: BeaR Date: Sat, 29 Nov 2014 13:20:04 +0100 Subject: [PATCH 5/6] Add editor properties for rectangle shaped sources and visualize falloff distance --- src/game/editor/layer_sounds.cpp | 10 ++++++++++ src/game/editor/popups.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/game/editor/layer_sounds.cpp b/src/game/editor/layer_sounds.cpp index fea83c517..a3fe4cb75 100644 --- a/src/game/editor/layer_sounds.cpp +++ b/src/game/editor/layer_sounds.cpp @@ -46,6 +46,11 @@ void CLayerSounds::Render() { m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, pSource->m_Shape.m_Circle.m_Radius, 32); + + float Falloff = ((float)pSource->m_Falloff/255.0f); + if(Falloff > 0.0f) + m_pEditor->RenderTools()->DrawCircle(fx2f(pSource->m_Position.x)+OffsetX, fx2f(pSource->m_Position.y)+OffsetY, + pSource->m_Shape.m_Circle.m_Radius*Falloff, 32); break; } case CSoundShape::SHAPE_RECTANGLE: @@ -54,6 +59,11 @@ void CLayerSounds::Render() float Height = fx2f(pSource->m_Shape.m_Rectangle.m_Height); m_pEditor->RenderTools()->DrawRoundRect(fx2f(pSource->m_Position.x)+OffsetX - Width/2, fx2f(pSource->m_Position.y)+OffsetY - Height/2, Width, Height, 0.0f); + + float Falloff = ((float)pSource->m_Falloff/255.0f); + if(Falloff > 0.0f) + m_pEditor->RenderTools()->DrawRoundRect(fx2f(pSource->m_Position.x)+OffsetX - Falloff*Width/2, fx2f(pSource->m_Position.y)+OffsetY - Falloff*Height/2, + Width*Falloff, Height*Falloff, 0.0f); break; } } diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 34a0175b9..ddb1b6423 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -626,7 +626,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) // Sound shape button CUIRect ShapeButton; - View.HSplitBottom(5.0f, &View, 0x0); + View.HSplitBottom(3.0f, &View, 0x0); View.HSplitBottom(12.0f, &View, &ShapeButton); static int s_ShapeTypeButton = 0; @@ -760,6 +760,30 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) case CSoundShape::SHAPE_RECTANGLE: { + enum + { + PROP_RECTANGLE_WIDTH=0, + PROP_RECTANGLE_HEIGHT, + NUM_RECTANGLE_PROPS, + }; + + CProperty aRectangleProps[] = { + {"Width", pSource->m_Shape.m_Rectangle.m_Width/1024, PROPTYPE_INT_SCROLL, 0, 1000000}, + {"Height", pSource->m_Shape.m_Rectangle.m_Height/1024, PROPTYPE_INT_SCROLL, 0, 1000000}, + + {0}, + }; + + static int s_aRectangleIds[NUM_RECTANGLE_PROPS] = {0}; + + NewVal = 0; + Prop = pEditor->DoProperties(&View, aRectangleProps, s_aRectangleIds, &NewVal); + if(Prop != -1) + pEditor->m_Map.m_Modified = true; + + if(Prop == PROP_RECTANGLE_WIDTH) pSource->m_Shape.m_Rectangle.m_Width = NewVal*1024; + //if(Prop == PROP_RECTANGLE_HEIGHT) pSource->m_Shape.m_Rectangle.m_Height = NewVal*1024; + break; } } From 98d42adf9dd36f9a9ea4a5b868475466bab90ba7 Mon Sep 17 00:00:00 2001 From: BeaR Date: Sat, 29 Nov 2014 14:29:40 +0100 Subject: [PATCH 6/6] Implement sound logic for shaped sounds, fix rectangle height property in editor and submit voice shape information to audio interface --- src/engine/client/sound.cpp | 133 +++++++++++++++++++++-- src/engine/client/sound.h | 4 + src/engine/sound.h | 21 ++++ src/game/client/components/mapsounds.cpp | 15 +++ src/game/editor/popups.cpp | 2 +- 5 files changed, 164 insertions(+), 11 deletions(-) diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 23e20a799..f94797bc0 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -40,7 +40,7 @@ struct CChannel { int m_Vol; int m_Pan; -} ; +}; struct CVoice { @@ -51,7 +51,15 @@ struct CVoice int m_Vol; // 0 - 255 int m_Flags; int m_X, m_Y; -} ; + float m_Falloff; // [0.0, 1.0] + + int m_Shape; + union + { + ISound::CVoiceShapeCircle m_Circle; + ISound::CVoiceShapeRectangle m_Rectangle; + }; +}; static CSample m_aSamples[NUM_SAMPLES] = { {0} }; static CVoice m_aVoices[NUM_VOICES] = { {0} }; @@ -134,20 +142,79 @@ static void Mix(short *pFinalOut, unsigned Frames) // TODO: we should respect the channel panning value int dx = v->m_X - m_CenterX; int dy = v->m_Y - m_CenterY; - int Dist = (int)sqrtf((float)dx*dx+dy*dy); // float here. nasty + // int p = IntAbs(dx); - int Range = DefaultDistance; - if(Dist >= 0 && Dist < Range) + float FalloffX = 0.0f; + float FalloffY = 0.0f; + + int RangeX = 0; // for panning + bool InVoiceField = false; + + switch(v->m_Shape) + { + case ISound::SHAPE_CIRCLE: + { + float r = v->m_Circle.m_Radius; + RangeX = r; + + int Dist = (int)sqrtf((float)dx*dx+dy*dy); // nasty float + if(Dist < r) + { + InVoiceField = true; + + // falloff + int FalloffDistance = r*v->m_Falloff; + if(Dist > FalloffDistance) + FalloffX = FalloffY = (r-Dist)/(r-FalloffDistance); + else + FalloffX = FalloffY = 1.0f; + } + else + InVoiceField = false; + + break; + } + + case ISound::SHAPE_RECTANGLE: + { + RangeX = v->m_Rectangle.m_Width/2.0f; + + int abs_dx = abs(dx); + int abs_dy = abs(dy); + + int w = v->m_Rectangle.m_Width/2.0f; + int h = v->m_Rectangle.m_Height/2.0f; + + if(abs_dx < w && abs_dy < h) + { + InVoiceField = true; + + // falloff + int fx = v->m_Falloff * w; + int fy = v->m_Falloff * h; + + FalloffX = abs_dx > fx ? (float)(w-abs_dx)/(w-fx) : 1.0f; + FalloffY = abs_dy > fy ? (float)(h-abs_dy)/(h-fy) : 1.0f; + } + else + InVoiceField = false; + + break; + } + }; + + if(InVoiceField) { // panning if(dx > 0) - Lvol = ((Range-p)*Lvol)/Range; + Lvol = ((RangeX-p)*Lvol)/RangeX; else - Rvol = ((Range-p)*Rvol)/Range; + Rvol = ((RangeX-p)*Rvol)/RangeX; - // falloff - Lvol = (Lvol*(Range-Dist))/Range; - Rvol = (Rvol*(Range-Dist))/Range; + { + Lvol *= FalloffX; + Rvol *= FalloffY; + } } else { @@ -645,6 +712,20 @@ void CSound::SetVoiceVolume(CVoiceHandle Voice, float Volume) m_aVoices[VoiceID].m_Vol = (int)(Volume*255.0f); } +void CSound::SetVoiceFalloff(CVoiceHandle Voice, float Falloff) +{ + if(!Voice.IsValid()) + return; + + int VoiceID = Voice.Id(); + + if(m_aVoices[VoiceID].m_Age != Voice.Age()) + return; + + Falloff = clamp(Falloff, 0.0f, 1.0f); + m_aVoices[VoiceID].m_Falloff = Falloff; +} + void CSound::SetVoiceLocation(CVoiceHandle Voice, float x, float y) { if(!Voice.IsValid()) @@ -696,6 +777,35 @@ void CSound::SetVoiceTimeOffset(CVoiceHandle Voice, float offset) lock_release(m_SoundLock); } +void CSound::SetVoiceCircle(CVoiceHandle Voice, float Radius) +{ + if(!Voice.IsValid()) + return; + + int VoiceID = Voice.Id(); + + if(m_aVoices[VoiceID].m_Age != Voice.Age()) + return; + + m_aVoices[VoiceID].m_Shape = ISound::SHAPE_CIRCLE; + m_aVoices[VoiceID].m_Circle.m_Radius = max(0.0f, Radius); +} + +void CSound::SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) +{ + if(!Voice.IsValid()) + return; + + int VoiceID = Voice.Id(); + + if(m_aVoices[VoiceID].m_Age != Voice.Age()) + return; + + m_aVoices[VoiceID].m_Shape = ISound::SHAPE_RECTANGLE; + m_aVoices[VoiceID].m_Rectangle.m_Width = max(0.0f, Width); + m_aVoices[VoiceID].m_Rectangle.m_Height = max(0.0f, Height); +} + void CSound::SetChannel(int ChannelID, float Vol, float Pan) { m_aChannels[ChannelID].m_Vol = (int)(Vol*255.0f); @@ -735,6 +845,9 @@ ISound::CVoiceHandle CSound::Play(int ChannelID, int SampleID, int Flags, float m_aVoices[VoiceID].m_Flags = Flags; m_aVoices[VoiceID].m_X = (int)x; m_aVoices[VoiceID].m_Y = (int)y; + m_aVoices[VoiceID].m_Falloff = 0.0f; + m_aVoices[VoiceID].m_Shape = ISound::SHAPE_CIRCLE; + m_aVoices[VoiceID].m_Circle.m_Radius = DefaultDistance; Age = m_aVoices[VoiceID].m_Age; } diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index 4fc133384..09fb97260 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -41,9 +41,13 @@ public: virtual void SetChannel(int ChannelID, float Vol, float Pan); virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume); + virtual void SetVoiceFalloff(CVoiceHandle Voice, float Falloff); virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y); virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float offset); // in s + virtual void SetVoiceCircle(CVoiceHandle Voice, float Radius); + virtual void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height); + CVoiceHandle Play(int ChannelID, int SampleID, int Flags, float x, float y); virtual CVoiceHandle PlayAt(int ChannelID, int SampleID, int Flags, float x, float y); virtual CVoiceHandle Play(int ChannelID, int SampleID, int Flags); diff --git a/src/engine/sound.h b/src/engine/sound.h index 405bb0f8d..dddea910f 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -16,6 +16,23 @@ public: FLAG_ALL=3 }; + enum + { + SHAPE_CIRCLE, + SHAPE_RECTANGLE, + }; + + struct CVoiceShapeCircle + { + float m_Radius; + }; + + struct CVoiceShapeRectangle + { + float m_Width; + float m_Height; + }; + class CVoiceHandle { friend class ISound; @@ -48,9 +65,13 @@ public: virtual void SetListenerPos(float x, float y) = 0; virtual void SetVoiceVolume(CVoiceHandle Voice, float Volume) = 0; + virtual void SetVoiceFalloff(CVoiceHandle Voice, float Falloff) = 0; virtual void SetVoiceLocation(CVoiceHandle Voice, float x, float y) = 0; virtual void SetVoiceTimeOffset(CVoiceHandle Voice, float offset) = 0; // in s + virtual void SetVoiceCircle(CVoiceHandle Voice, float Radius) = 0; + virtual void SetVoiceRectangle(CVoiceHandle Voice, float Width, float Height) = 0; + virtual CVoiceHandle PlayAt(int ChannelID, int SampleID, int Flags, float x, float y) = 0; virtual CVoiceHandle Play(int ChannelID, int SampleID, int Flags) = 0; virtual void Stop(int SampleID) = 0; diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index 0b815e741..369348cf8 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -123,6 +123,21 @@ void CMapSounds::OnRender() pSource->m_Voice = m_pClient->m_pSounds->PlaySampleAt(CSounds::CHN_MAPSOUND, m_aSounds[pSource->m_Sound], 1.0f, vec2(fx2f(pSource->m_pSource->m_Position.x), fx2f(pSource->m_pSource->m_Position.y)), Flags); Sound()->SetVoiceTimeOffset(pSource->m_Voice, offset); + Sound()->SetVoiceFalloff(pSource->m_Voice, pSource->m_pSource->m_Falloff/255.0f); + switch(pSource->m_pSource->m_Shape.m_Type) + { + case CSoundShape::SHAPE_CIRCLE: + { + Sound()->SetVoiceCircle(pSource->m_Voice, pSource->m_pSource->m_Shape.m_Circle.m_Radius); + break; + } + + case CSoundShape::SHAPE_RECTANGLE: + { + Sound()->SetVoiceRectangle(pSource->m_Voice, fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Width), fx2f(pSource->m_pSource->m_Shape.m_Rectangle.m_Height)); + break; + } + }; } } else diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index ddb1b6423..8019df2fc 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -782,7 +782,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) pEditor->m_Map.m_Modified = true; if(Prop == PROP_RECTANGLE_WIDTH) pSource->m_Shape.m_Rectangle.m_Width = NewVal*1024; - //if(Prop == PROP_RECTANGLE_HEIGHT) pSource->m_Shape.m_Rectangle.m_Height = NewVal*1024; + if(Prop == PROP_RECTANGLE_HEIGHT) pSource->m_Shape.m_Rectangle.m_Height = NewVal*1024; break; }