123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- ----------------------------------------------------------------------------------------------------
- --
- -- Copyright (c) Contributors to the Open 3D Engine Project.
- -- For complete copyright and license terms please see the LICENSE at the root of this distribution.
- --
- -- SPDX-License-Identifier: Apache-2.0 OR MIT
- --
- --
- --
- ----------------------------------------------------------------------------------------------------
- -- audio area entity - to be attached to an area
- -- reports a normalized (0-1) fade value depending on the listener's distance to the area
- AudioAreaEntity = {
- type = "AudioAreaEntity",
-
- Editor = {
- Model = "Editor/Objects/Sound.cgf",
- Icon = "AudioAreaEntity.bmp",
- },
-
- Properties = {
- bEnabled = true,
- audioEnvironmentEnvironment = "",
- eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE,
- fFadeDistance = 5.0,
- fEnvironmentDistance = 5.0,
- },
-
- fFadeValue = 0.0,
- nState = 0, -- 0 = far, 1 = near, 2 = inside
- fFadeOnUnregister = 1.0,
- hEnvironmentID = nil,
- tObstructionType = {},
- }
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:_ActivateOutput(sPortName, value)
- if (self.Properties.bEnabled) then
- self:ActivateOutput(sPortName, value);
- end
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:_UpdateParameters()
- -- Set the distances as the very first thing!
- self:SetFadeDistance(self.Properties.fFadeDistance);
- self:SetEnvironmentFadeDistance(self.Properties.fEnvironmentDistance);
-
- if (self.Properties.bEnabled) then
- self.hEnvironmentID = AudioUtils.LookupAudioEnvironmentID(self.Properties.audioEnvironmentEnvironment);
- if (self.hEnvironmentID ~= nil) then
- self:SetAudioEnvironmentID(self.hEnvironmentID);
- end
- else
- self:SetAudioEnvironmentID(INVALID_AUDIO_ENVIRONMENT_ID);
- end
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:_LookupObstructionSwitchIDs()
- -- cache the obstruction switch and state IDs
- self.tObstructionType = AudioUtils.LookupObstructionSwitchAndStates();
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:_SetObstruction()
- local nStateIdx = self.Properties.eiSoundObstructionType + 1;
- self:SetAudioObstructionCalcType(self.Properties.eiSoundObstructionType, self:GetDefaultAuxAudioProxyID());
- if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
- self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
- end
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:OnSpawn()
- self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:OnLoad(load)
- self.Properties = load.Properties;
- self.fFadeOnUnregister = load.fFadeOnUnregister;
- self:_SetObstruction();
- self.nState = 0;
- self.fFadeValue = 0.0;
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:OnPostLoad()
- self:_UpdateParameters();
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:OnSave(save)
- save.Properties = self.Properties;
- save.fFadeOnUnregister = self.fFadeOnUnregister;
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:OnPropertyChange()
- self:_UpdateParameters();
-
- if (self.Properties.eiSoundObstructionType < AUDIO_OBSTRUCTION_TYPE_IGNORE) then
- self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE;
- elseif (self.Properties.eiSoundObstructionType > AUDIO_OBSTRUCTION_TYPE_MULTI) then
- self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_MULTI;
- end
-
- self:ResetAudioRtpcValues(self:GetDefaultAuxAudioProxyID());
- self:_SetObstruction();
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:CliSrv_OnInit()
- self.nState = 0;
- self.fFadeValue = 0.0;
- self.fFadeOnUnregister = 1.0;
- self:SetFlags(ENTITY_FLAG_VOLUME_SOUND, 0);
-
- self:_UpdateParameters();
- end
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:UpdateFadeValue(player, fFade, fDistSq)
- if (not(self.Properties.bEnabled) or (fFade == 0.0 and fDistSq == 0.0)) then
- if (self.fFadeValue ~= 0.0) then
- self:_ActivateOutput("FadeValue", 0.0);
- end
- self.fFadeValue = 0.0;
- do return end;
- end
-
- if (self.Properties.fFadeDistance > 0.0) then
- if (self.nState == 2) then
- if (self.fFadeValue ~= fFade) then
- self.fFadeValue = math.abs(fFade);
- self:_ActivateOutput("FadeValue", self.fFadeValue);
- end
- else
- local fLocalFade = 1.0 - (math.sqrt(fDistSq) / self.Properties.fFadeDistance);
- self.fFadeValue = math.max(0, fLocalFade);
- self:_ActivateOutput("FadeValue", self.fFadeValue);
- end
- end
- end
- ----------------------------------------------------------------------------------------
- AudioAreaEntity.Server = {
- OnInit = function(self)
- self:CliSrv_OnInit();
- end,
-
- OnShutDown = function(self)
- end,
- }
- ----------------------------------------------------------------------------------------
- AudioAreaEntity.Client = {
- OnInit = function(self)
- self:RegisterForAreaEvents(1);
- self:_LookupObstructionSwitchIDs();
- self:_SetObstruction();
- self:CliSrv_OnInit();
- end,
-
- OnShutDown = function(self)
- self.nState = 0;
- self:RegisterForAreaEvents(0);
- end,
-
- OnAudioListenerEnterNearArea = function(self, player, nAreaID, fFade)
- if (self.nState == 0) then
- self:_SetObstruction();
- self:_ActivateOutput("OnFarToNear", true);
- elseif (self.nState == 2) then
- self:_ActivateOutput("OnInsideToNear", true);
- end
-
- self.nState = 1;
- self.fFadeValue = 0.0;
- self:_ActivateOutput("FadeValue", self.fFadeValue);
- end,
-
- OnAudioListenerMoveNearArea = function(self, player, areaId, fFade, fDistsq)
- self.nState = 1;
- self:UpdateFadeValue(player, fFade, fDistsq);
- end,
-
- OnAudioListenerEnterArea = function(self, player, areaId, fFade)
- if (self.nState == 0) then
- -- possible if the listener is teleported or gets spawned inside the area
- -- technically, the listener enters the Near Area and the Inside Area at the same time
- -- however, in this case the AreaManager is responsible to first call OnEnterNear and then OnEnter so this is technically circumventing a possible bug :)
- self:_SetObstruction();
- self:_ActivateOutput("OnFarToNear", true);
- end
-
- self.nState = 2;
- self.fFadeValue = 1.0;
- self:_ActivateOutput("OnNearToInside", true);
- self:_ActivateOutput("FadeValue", self.fFadeValue);
- end,
-
- OnAudioListenerProceedFadeArea = function(self, player, areaId, fExternalFade)
- -- fExternalFade holds the fade value which was calculated by an inner, higher priority area
- -- in the AreaManager to fade out the outer sound dependent on the largest fade distance of all attached entities
- if (fExternalFade > 0.0) then
- self.nState = 2;
- self:UpdateFadeValue(player, fExternalFade, 0.0);
- else
- self:UpdateFadeValue(player, 0.0, 0.0);
- end
- end,
-
- OnAudioListenerLeaveArea = function(self, player, nAreaID, fFade)
- self.nState = 1;
- self:_ActivateOutput("OnInsideToNear", true);
- end,
-
- OnAudioListenerLeaveNearArea = function(self, player, nAreaID, fFade)
- self.nState = 0;
- self.fFadeValue = 0.0;
- self:_ActivateOutput("OnNearToFar", true);
- self:_ActivateOutput("FadeValue", self.fFadeValue);
- end,
-
- OnUnBindThis = function(self)
- self.nState = 0;
- end,
- }
- ----------------------------------------------------------------------------------------
- -- Event Handlers
- ----------------------------------------------------------------------------------------
- function AudioAreaEntity:Event_Enable(sender)
- self.Properties.bEnabled = true;
- self:OnPropertyChange();
- end
- function AudioAreaEntity:Event_Disable(sender)
- self.Properties.bEnabled = false;
- self:OnPropertyChange();
- end
- AudioAreaEntity.FlowEvents =
- {
- Inputs =
- {
- Enable = { AudioAreaEntity.Event_Enable, "bool" },
- Disable = { AudioAreaEntity.Event_Disable, "bool" },
- },
-
- Outputs =
- {
- FadeValue = "float",
- OnFarToNear = "bool",
- OnNearToInside = "bool",
- OnInsideToNear = "bool",
- OnNearToFar = "bool",
- },
- }
|