Files
aibis-dream/Assets/Scripts/Framework/AudioKit/YarnGlobalParameterRegistry.cs
T

150 lines
5.1 KiB
C#

using System;
using System.Collections.Generic;
using FMOD;
using FMOD.Studio;
using FMODUnity;
namespace AibisDream.Kit
{
internal interface IFmodGlobalParameterApi
{
RESULT SetParameterByName(string name, float value, bool ignoreSeekSpeed);
RESULT GetParameterByName(string name, out float value, out float finalValue);
RESULT GetParameterDescriptionByName(string name, out PARAMETER_DESCRIPTION description);
RESULT SetParameterById(PARAMETER_ID id, float value, bool ignoreSeekSpeed);
}
internal sealed class RuntimeFmodGlobalParameterApi : IFmodGlobalParameterApi
{
public RESULT SetParameterByName(string name, float value, bool ignoreSeekSpeed)
{
return RuntimeManager.StudioSystem.setParameterByName(name, value, ignoreSeekSpeed);
}
public RESULT GetParameterByName(string name, out float value, out float finalValue)
{
return RuntimeManager.StudioSystem.getParameterByName(name, out value, out finalValue);
}
public RESULT GetParameterDescriptionByName(
string name,
out PARAMETER_DESCRIPTION description)
{
return RuntimeManager.StudioSystem.getParameterDescriptionByName(name, out description);
}
public RESULT SetParameterById(PARAMETER_ID id, float value, bool ignoreSeekSpeed)
{
return RuntimeManager.StudioSystem.setParameterByID(id, value, ignoreSeekSpeed);
}
}
/// <summary>
/// 只记录曾被 Yarn set_global_param 成功修改的参数名。
/// 参数值与默认值始终以 FMOD Studio System 为唯一来源。
/// </summary>
internal sealed class YarnGlobalParameterRegistry
{
private readonly IFmodGlobalParameterApi _api;
private readonly HashSet<string> _trackedNames =
new(StringComparer.OrdinalIgnoreCase);
internal YarnGlobalParameterRegistry(IFmodGlobalParameterApi api)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
}
internal IReadOnlyCollection<string> TrackedNames => _trackedNames;
internal RESULT SetFromYarn(string name, float value)
{
if (string.IsNullOrWhiteSpace(name))
{
return RESULT.ERR_INVALID_PARAM;
}
var result = _api.SetParameterByName(name, value, ignoreSeekSpeed: false);
if (result == RESULT.OK)
{
_trackedNames.Add(name);
}
return result;
}
internal Dictionary<string, float> CaptureFinalValues(Action<string> warn)
{
var values = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);
foreach (var name in _trackedNames)
{
var result = _api.GetParameterByName(name, out _, out var finalValue);
if (result == RESULT.OK)
{
values[name] = finalValue;
continue;
}
warn?.Invoke(
$"[AudioManager] 捕获 Yarn 全局参数 {name} 失败:{result}。本次存档跳过该参数。");
}
return values;
}
internal void ResetToDefaults(Action<string> warn)
{
var names = new List<string>(_trackedNames);
foreach (var name in names)
{
var descriptionResult =
_api.GetParameterDescriptionByName(name, out var description);
if (descriptionResult != RESULT.OK)
{
warn?.Invoke(
$"[AudioManager] 查询 Yarn 全局参数 {name} 默认值失败:{descriptionResult}。保留追踪以便稍后重试。");
continue;
}
var resetResult = _api.SetParameterById(
description.id,
description.defaultvalue,
ignoreSeekSpeed: true);
if (resetResult != RESULT.OK)
{
warn?.Invoke(
$"[AudioManager] 重置 Yarn 全局参数 {name} 失败:{resetResult}。保留追踪以便稍后重试。");
continue;
}
_trackedNames.Remove(name);
}
}
internal void RestoreFinalValues(
IReadOnlyDictionary<string, float> values,
Action<string> warn)
{
if (values == null)
{
return;
}
foreach (var pair in values)
{
var result = _api.SetParameterByName(
pair.Key,
pair.Value,
ignoreSeekSpeed: true);
if (result == RESULT.OK)
{
_trackedNames.Add(pair.Key);
continue;
}
warn?.Invoke(
$"[AudioManager] 恢复 Yarn 全局参数 {pair.Key} 失败:{result}。跳过该参数。");
}
}
}
}