first commit
This commit is contained in:
174
NitroxClient/MonoBehaviours/FMODEmitterController.cs
Normal file
174
NitroxClient/MonoBehaviours/FMODEmitterController.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FMOD.Studio;
|
||||
using FMODUnity;
|
||||
using NitroxClient.GameLogic.FMOD;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using NitroxModel.GameLogic.FMOD;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.MonoBehaviours;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class FMODEmitterController : MonoBehaviour
|
||||
{
|
||||
private readonly Dictionary<string, FMOD_CustomEmitter> customEmitters = new();
|
||||
private readonly Dictionary<string, Tuple<FMOD_CustomLoopingEmitter, bool, float>> loopingEmitters = new(); // Tuple<emitter, is3D, radius>
|
||||
private readonly Dictionary<string, FMOD_StudioEventEmitter> studioEmitters = new();
|
||||
private readonly Dictionary<string, EventInstance> eventInstances = new(); // 2D Sounds
|
||||
|
||||
/// <summary>
|
||||
/// When <see cref="GameObject"/>s are copied their Start()/Awake() functions don't get called again.
|
||||
/// So the FMOD Start patch that tried to locate a <see cref="NitroxEntity"/> won't find one and will error later.
|
||||
/// This function can late register missed FMOD MonoBehaviours
|
||||
/// </summary>
|
||||
public void LateRegisterEmitter()
|
||||
{
|
||||
foreach (MonoBehaviour behaviour in gameObject.GetComponentsInChildren<MonoBehaviour>(true))
|
||||
{
|
||||
switch (behaviour)
|
||||
{
|
||||
case FMOD_CustomEmitter customEmitter when this.Resolve<FMODWhitelist>().IsWhitelisted(customEmitter.asset.path, out float maxDistance):
|
||||
AddEmitter(customEmitter.asset.path, customEmitter, maxDistance);
|
||||
break;
|
||||
case FMOD_StudioEventEmitter studioEmitter when this.Resolve<FMODWhitelist>().IsWhitelisted(studioEmitter.asset.path, out float maxDistance):
|
||||
AddEmitter(studioEmitter.asset.path, studioEmitter, maxDistance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEmitter(string path, FMOD_CustomEmitter customEmitter, float maxDistance)
|
||||
{
|
||||
if (customEmitters.ContainsKey(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
customEmitter.CacheEventInstance();
|
||||
EventInstance evt = customEmitter.GetEventInstance();
|
||||
evt.getDescription(out EventDescription description);
|
||||
description.is3D(out bool is3D);
|
||||
|
||||
if (is3D)
|
||||
{
|
||||
evt.setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f);
|
||||
evt.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, maxDistance);
|
||||
|
||||
customEmitters.Add(path, customEmitter);
|
||||
|
||||
if (customEmitter is FMOD_CustomLoopingEmitter loopingEmitter)
|
||||
{
|
||||
if (loopingEmitter.assetStart && this.Resolve<FMODWhitelist>().IsWhitelisted(loopingEmitter.assetStart.path, out float radiusStart))
|
||||
{
|
||||
AddEmitter(loopingEmitter.assetStart.path, loopingEmitter, radiusStart);
|
||||
}
|
||||
|
||||
if (loopingEmitter.assetStop && this.Resolve<FMODWhitelist>().IsWhitelisted(loopingEmitter.assetStop.path, out float radiusStop))
|
||||
{
|
||||
AddEmitter(loopingEmitter.assetStop.path, loopingEmitter, radiusStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddEventInstance(customEmitter.asset.path, evt);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEmitter(string path, FMOD_CustomLoopingEmitter loopingEmitter, float radius)
|
||||
{
|
||||
if (!loopingEmitters.ContainsKey(path))
|
||||
{
|
||||
loopingEmitter.CacheEventInstance();
|
||||
|
||||
loopingEmitter.evt.getDescription(out EventDescription description);
|
||||
description.is3D(out bool is3D);
|
||||
|
||||
loopingEmitters.Add(path, new Tuple<FMOD_CustomLoopingEmitter, bool, float>(loopingEmitter, is3D, radius));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEmitter(string path, FMOD_StudioEventEmitter studioEmitter, float maxDistance)
|
||||
{
|
||||
if (!customEmitters.ContainsKey(path))
|
||||
{
|
||||
studioEmitter.CacheEventInstance();
|
||||
|
||||
studioEmitters.Add(path, studioEmitter);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEventInstance(string path, EventInstance eventInstance)
|
||||
{
|
||||
if (!eventInstances.ContainsKey(path))
|
||||
{
|
||||
eventInstances.Add(path, eventInstance);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayCustomEmitter(string path) => customEmitters[path].AliveOrNull()?.Play();
|
||||
public void SetParameterCustomEmitter(string path, string paramString, float value) => customEmitters[path].AliveOrNull()?.SetParameterValue(paramString, value);
|
||||
public void StopCustomEmitter(string path) => customEmitters[path].AliveOrNull()?.Stop();
|
||||
|
||||
public void PlayStudioEmitter(string path) => studioEmitters[path].AliveOrNull()?.PlayUI();
|
||||
public void StopStudioEmitter(string path, bool allowFadeout) => studioEmitters[path].AliveOrNull()?.Stop(allowFadeout);
|
||||
|
||||
public void PlayCustomLoopingEmitter(string path)
|
||||
{
|
||||
(FMOD_CustomLoopingEmitter loopingEmitter, bool is3D, float radius) = loopingEmitters[path];
|
||||
EventInstance eventInstance = FMODUWE.GetEventImpl(path);
|
||||
|
||||
if (is3D)
|
||||
{
|
||||
eventInstance.set3DAttributes(loopingEmitter.transform.To3DAttributes());
|
||||
eventInstance.setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f);
|
||||
eventInstance.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
eventInstance.setVolume(FMODSystem.CalculateVolume(loopingEmitter.transform.position, Player.main.transform.position, radius, 1f));
|
||||
}
|
||||
|
||||
eventInstance.start();
|
||||
eventInstance.release();
|
||||
loopingEmitter.timeLastStopSound = Time.time;
|
||||
}
|
||||
|
||||
public void PlayEventInstance(string path, float volume)
|
||||
{
|
||||
EventInstance eventInstance = eventInstances[path];
|
||||
eventInstance.setVolume(volume);
|
||||
eventInstance.start();
|
||||
}
|
||||
|
||||
public void StopEventInstance(string path)
|
||||
{
|
||||
EventInstance eventInstance = eventInstances[path];
|
||||
eventInstance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
|
||||
}
|
||||
|
||||
public static void PlayEventOneShot(FMODAsset asset, float radius, Vector3 origin, float volume = 1f) => PlayEventOneShot(asset.path, radius, origin, volume);
|
||||
|
||||
public static void PlayEventOneShot(string path, float radius, Vector3 origin, float volume = 1f)
|
||||
{
|
||||
EventInstance evt = FMODUWE.GetEventImpl(path);
|
||||
evt.getDescription(out EventDescription description);
|
||||
description.is3D(out bool is3D);
|
||||
|
||||
if (is3D)
|
||||
{
|
||||
evt.setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f);
|
||||
evt.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, radius);
|
||||
evt.setVolume(volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.setVolume(FMODSystem.CalculateVolume(origin, Player.main.transform.position, radius, volume));
|
||||
}
|
||||
|
||||
evt.set3DAttributes(origin.To3DAttributes());
|
||||
evt.start();
|
||||
evt.release();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user