mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-25 04:59:01 +08:00
feat(serializer): 添加运行时类型序列化器接口并重构序列化模块
- 新增 IRuntimeTypeSerializer 接口支持运行时类型序列化 - 将序列化器接口从 Game 模块迁移到 Core 模块 - 更新 JsonSerializer 的命名空间引用 - 为 Godot 音频和图形设置类添加持久化应用接口实现 - 重构设置模型的初始化和去重逻辑 - 移除批量加载所有设置的功能 - 优化设置应用过程为异步执行 - 在存储接口中添加异步删除方法 - 为各种存储实现添加异步删除功能 - 为 Godot 文件存储添加标准文件系统路径删除支持 - 删除废弃的设置数据基类实现
This commit is contained in:
parent
b49079de3e
commit
19c0830a7d
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2026 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.serializer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 运行时类型序列化器接口,继承自ISerializer接口
|
||||||
|
/// 提供基于运行时类型的对象序列化和反序列化功能
|
||||||
|
/// </summary>
|
||||||
|
public interface IRuntimeTypeSerializer : ISerializer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将指定对象序列化为字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">要序列化的对象</param>
|
||||||
|
/// <param name="type">对象的运行时类型</param>
|
||||||
|
/// <returns>序列化后的字符串表示</returns>
|
||||||
|
string Serialize(object obj, Type type);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将字符串数据反序列化为指定类型的对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">要反序列化的字符串数据</param>
|
||||||
|
/// <param name="type">目标对象的运行时类型</param>
|
||||||
|
/// <returns>反序列化后的对象实例</returns>
|
||||||
|
object Deserialize(string data, Type type);
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.utility;
|
||||||
|
|
||||||
namespace GFramework.Game.Abstractions.serializer;
|
namespace GFramework.Core.Abstractions.serializer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义序列化器接口,提供对象序列化和反序列化的通用方法
|
/// 定义序列化器接口,提供对象序列化和反序列化的通用方法
|
||||||
@ -68,4 +68,11 @@ public interface IStorage : IUtility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">要删除的键</param>
|
/// <param name="key">要删除的键</param>
|
||||||
void Delete(string key);
|
void Delete(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步删除指定键的存储项
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">要删除的键</param>
|
||||||
|
/// <returns>表示异步操作的Task</returns>
|
||||||
|
Task DeleteAsync(string key);
|
||||||
}
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) 2026 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
namespace GFramework.Game.Abstractions.setting;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可持久化的应用设置接口
|
||||||
|
/// 同时具备数据持久化和应用逻辑能力
|
||||||
|
/// </summary>
|
||||||
|
public interface IPersistentApplyAbleSettings : ISettingsData, IApplyAbleSettings;
|
||||||
@ -32,9 +32,4 @@ public interface ISettingsPersistence : IContextUtility
|
|||||||
/// 保存所有设置数据
|
/// 保存所有设置数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SaveAllAsync(IEnumerable<ISettingsData> allData);
|
Task SaveAllAsync(IEnumerable<ISettingsData> allData);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加载所有已知类型的设置数据
|
|
||||||
/// </summary>
|
|
||||||
Task<IDictionary<Type, ISettingsData>> LoadAllAsync(IEnumerable<Type> knownTypes);
|
|
||||||
}
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace GFramework.Game.Abstractions.setting;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置数据抽象基类,提供默认的 Reset() 实现
|
|
||||||
/// </summary>
|
|
||||||
public abstract class SettingsData : ISettingsData
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 重置设置为默认值
|
|
||||||
/// 使用反射将所有属性重置为它们的默认值
|
|
||||||
/// </summary>
|
|
||||||
public virtual void Reset()
|
|
||||||
{
|
|
||||||
var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
|
||||||
foreach (var prop in properties)
|
|
||||||
{
|
|
||||||
if (!prop.CanWrite || !prop.CanRead) continue;
|
|
||||||
|
|
||||||
var defaultValue = GetDefaultValue(prop.PropertyType);
|
|
||||||
prop.SetValue(this, defaultValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取指定类型的默认值
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">要获取默认值的类型</param>
|
|
||||||
/// <returns>类型的默认值</returns>
|
|
||||||
private static object? GetDefaultValue(Type type)
|
|
||||||
{
|
|
||||||
return type.IsValueType ? Activator.CreateInstance(type) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
using GFramework.Game.Abstractions.serializer;
|
using GFramework.Core.Abstractions.serializer;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace GFramework.Game.serializer;
|
namespace GFramework.Game.serializer;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using GFramework.Core.model;
|
using GFramework.Core.extensions;
|
||||||
|
using GFramework.Core.model;
|
||||||
using GFramework.Game.Abstractions.setting;
|
using GFramework.Game.Abstractions.setting;
|
||||||
|
|
||||||
namespace GFramework.Game.setting;
|
namespace GFramework.Game.setting;
|
||||||
@ -10,6 +11,7 @@ public class SettingsModel : AbstractModel, ISettingsModel
|
|||||||
{
|
{
|
||||||
private readonly Dictionary<Type, IApplyAbleSettings> _applicators = new();
|
private readonly Dictionary<Type, IApplyAbleSettings> _applicators = new();
|
||||||
private readonly Dictionary<Type, ISettingsData> _dataSettings = new();
|
private readonly Dictionary<Type, ISettingsData> _dataSettings = new();
|
||||||
|
private ISettingsPersistence? _persistence;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取或创建数据设置
|
/// 获取或创建数据设置
|
||||||
@ -40,6 +42,13 @@ public class SettingsModel : AbstractModel, ISettingsModel
|
|||||||
{
|
{
|
||||||
var type = typeof(T);
|
var type = typeof(T);
|
||||||
_applicators[type] = applicator;
|
_applicators[type] = applicator;
|
||||||
|
|
||||||
|
// 如果这个应用设置同时也是数据设置,也注册到数据字典中
|
||||||
|
if (applicator is ISettingsData data)
|
||||||
|
{
|
||||||
|
_dataSettings[type] = data;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,9 +97,41 @@ public class SettingsModel : AbstractModel, ISettingsModel
|
|||||||
/// <returns>包含所有设置节的可枚举集合</returns>
|
/// <returns>包含所有设置节的可枚举集合</returns>
|
||||||
public IEnumerable<ISettingsSection> All()
|
public IEnumerable<ISettingsSection> All()
|
||||||
{
|
{
|
||||||
// 合并数据设置和应用器设置的所有值
|
// 使用 HashSet 去重(避免同时实现两个接口的设置被重复返回)
|
||||||
return _dataSettings.Values
|
var sections = new HashSet<ISettingsSection>();
|
||||||
.Concat(_applicators.Values.Cast<ISettingsSection>());
|
|
||||||
|
foreach (var applicator in _applicators.Values)
|
||||||
|
sections.Add(applicator);
|
||||||
|
|
||||||
|
foreach (var data in _dataSettings.Values)
|
||||||
|
sections.Add(data);
|
||||||
|
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化并加载指定类型的设置数据
|
||||||
|
/// </summary>
|
||||||
|
public async Task InitializeAsync(params Type[] settingTypes)
|
||||||
|
{
|
||||||
|
foreach (var type in settingTypes)
|
||||||
|
{
|
||||||
|
if (!typeof(ISettingsData).IsAssignableFrom(type) ||
|
||||||
|
!type.IsClass ||
|
||||||
|
type.GetConstructor(Type.EmptyTypes) == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 使用反射调用泛型方法 LoadAsync<T>
|
||||||
|
var method = typeof(ISettingsPersistence)
|
||||||
|
.GetMethod(nameof(ISettingsPersistence.LoadAsync))!
|
||||||
|
.MakeGenericMethod(type);
|
||||||
|
|
||||||
|
var task = (Task)method.Invoke(_persistence, null)!;
|
||||||
|
await task;
|
||||||
|
|
||||||
|
var loaded = (ISettingsData)((dynamic)task).Result;
|
||||||
|
_dataSettings[type] = loaded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,5 +140,6 @@ public class SettingsModel : AbstractModel, ISettingsModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void OnInit()
|
protected override void OnInit()
|
||||||
{
|
{
|
||||||
|
_persistence = this.GetUtility<ISettingsPersistence>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ public class SettingsPersistence : AbstractContextUtility, ISettingsPersistence
|
|||||||
public async Task DeleteAsync<T>() where T : class, ISettingsData
|
public async Task DeleteAsync<T>() where T : class, ISettingsData
|
||||||
{
|
{
|
||||||
var key = GetKey<T>();
|
var key = GetKey<T>();
|
||||||
_storage.Delete(key);
|
await _storage.DeleteAsync(key);
|
||||||
this.SendEvent(new SettingsDeletedEvent(typeof(T)));
|
this.SendEvent(new SettingsDeletedEvent(typeof(T)));
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -86,38 +86,6 @@ public class SettingsPersistence : AbstractContextUtility, ISettingsPersistence
|
|||||||
this.SendEvent(new SettingsBatchSavedEvent(dataList));
|
this.SendEvent(new SettingsBatchSavedEvent(dataList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异步加载所有已知类型的设置数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="knownTypes">已知设置数据类型的集合</param>
|
|
||||||
/// <returns>类型与对应设置数据的字典映射</returns>
|
|
||||||
public async Task<IDictionary<Type, ISettingsData>> LoadAllAsync(IEnumerable<Type> knownTypes)
|
|
||||||
{
|
|
||||||
var result = new Dictionary<Type, ISettingsData>();
|
|
||||||
var allSettings = new List<ISettingsSection>();
|
|
||||||
|
|
||||||
foreach (var type in knownTypes)
|
|
||||||
{
|
|
||||||
var key = GetKey(type);
|
|
||||||
|
|
||||||
if (!await _storage.ExistsAsync(key)) continue;
|
|
||||||
// 使用反射调用泛型方法
|
|
||||||
var method = typeof(IStorage)
|
|
||||||
.GetMethod(nameof(IStorage.ReadAsync))!
|
|
||||||
.MakeGenericMethod(type);
|
|
||||||
|
|
||||||
var task = (Task)method.Invoke(_storage, [key])!;
|
|
||||||
await task;
|
|
||||||
|
|
||||||
var loaded = (ISettingsData)((dynamic)task).Result;
|
|
||||||
result[type] = loaded;
|
|
||||||
allSettings.Add(loaded);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SendEvent(new SettingsAllLoadedEvent(allSettings));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInit()
|
protected override void OnInit()
|
||||||
{
|
{
|
||||||
_storage = this.GetUtility<IStorage>()!;
|
_storage = this.GetUtility<IStorage>()!;
|
||||||
|
|||||||
@ -16,12 +16,10 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
|
|||||||
/// 应用所有设置配置
|
/// 应用所有设置配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>完成的任务</returns>
|
/// <returns>完成的任务</returns>
|
||||||
public Task ApplyAll()
|
public async Task ApplyAll()
|
||||||
{
|
{
|
||||||
// 遍历所有设置配置并尝试应用
|
// 遍历所有设置配置并尝试应用
|
||||||
foreach (var section in _model.All()) TryApply(section);
|
foreach (var section in _model.All()) await TryApplyAsync(section);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -39,13 +37,12 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settingsType">设置配置类型</param>
|
/// <param name="settingsType">设置配置类型</param>
|
||||||
/// <returns>完成的任务</returns>
|
/// <returns>完成的任务</returns>
|
||||||
public Task Apply(Type settingsType)
|
public async Task Apply(Type settingsType)
|
||||||
{
|
{
|
||||||
if (!_model.TryGet(settingsType, out var section))
|
if (_model.TryGet(settingsType, out var section))
|
||||||
return Task.CompletedTask;
|
{
|
||||||
|
await TryApplyAsync(section);
|
||||||
TryApply(section);
|
}
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -53,14 +50,16 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settingsTypes">设置配置类型集合</param>
|
/// <param name="settingsTypes">设置配置类型集合</param>
|
||||||
/// <returns>完成的任务</returns>
|
/// <returns>完成的任务</returns>
|
||||||
public Task Apply(IEnumerable<Type> settingsTypes)
|
public async Task Apply(IEnumerable<Type> settingsTypes)
|
||||||
{
|
{
|
||||||
// 去重后遍历设置类型,获取并应用对应的设置配置
|
// 去重后遍历设置类型,获取并应用对应的设置配置
|
||||||
foreach (var type in settingsTypes.Distinct())
|
foreach (var type in settingsTypes.Distinct())
|
||||||
|
{
|
||||||
if (_model.TryGet(type, out var section))
|
if (_model.TryGet(type, out var section))
|
||||||
TryApply(section);
|
{
|
||||||
|
await TryApplyAsync(section);
|
||||||
return Task.CompletedTask;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -75,20 +74,20 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
|
|||||||
/// 尝试应用可应用的设置配置
|
/// 尝试应用可应用的设置配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="section">设置配置对象</param>
|
/// <param name="section">设置配置对象</param>
|
||||||
private void TryApply(ISettingsSection section)
|
private async Task TryApplyAsync(ISettingsSection section)
|
||||||
{
|
{
|
||||||
if (section is not IApplyAbleSettings applyAbleSettings) return;
|
if (section is not IApplyAbleSettings applyAbleSettings) return;
|
||||||
|
|
||||||
this.SendEvent(new SettingsApplyingEvent<ISettingsSection>(section));
|
this.SendEvent(new SettingsApplyingEvent<ISettingsSection>(section));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
applyAbleSettings.Apply();
|
await applyAbleSettings.Apply();
|
||||||
this.SendEvent(new SettingsAppliedEvent<ISettingsSection>(section, true));
|
this.SendEvent(new SettingsAppliedEvent<ISettingsSection>(section, true));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
this.SendEvent(new SettingsAppliedEvent<ISettingsSection>(section, false, ex));
|
this.SendEvent(new SettingsAppliedEvent<ISettingsSection>(section, false, ex));
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using GFramework.Game.Abstractions.serializer;
|
using GFramework.Core.Abstractions.serializer;
|
||||||
using GFramework.Game.Abstractions.storage;
|
using GFramework.Game.Abstractions.storage;
|
||||||
|
|
||||||
namespace GFramework.Game.storage;
|
namespace GFramework.Game.storage;
|
||||||
@ -33,26 +33,6 @@ public sealed class FileStorage : IFileStorage
|
|||||||
Directory.CreateDirectory(_rootPath);
|
Directory.CreateDirectory(_rootPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Delete
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除指定键的存储项
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">存储键</param>
|
|
||||||
public void Delete(string key)
|
|
||||||
{
|
|
||||||
var path = ToPath(key);
|
|
||||||
var keyLock = _keyLocks.GetOrAdd(path, _ => new object());
|
|
||||||
|
|
||||||
lock (keyLock)
|
|
||||||
{
|
|
||||||
if (File.Exists(path))
|
|
||||||
File.Delete(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清理文件段字符串,将其中的无效文件名字符替换为下划线
|
/// 清理文件段字符串,将其中的无效文件名字符替换为下划线
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -105,6 +85,31 @@ public sealed class FileStorage : IFileStorage
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Delete
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除指定键的存储项
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">存储键</param>
|
||||||
|
public void Delete(string key)
|
||||||
|
{
|
||||||
|
var path = ToPath(key);
|
||||||
|
var keyLock = _keyLocks.GetOrAdd(path, _ => new object());
|
||||||
|
|
||||||
|
lock (keyLock)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DeleteAsync(string key)
|
||||||
|
{
|
||||||
|
return Task.Run(() => Delete(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Exists
|
#region Exists
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -95,6 +95,16 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
|
|||||||
inner.Delete(Key(key));
|
inner.Delete(Key(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步删除指定键
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">要删除的键</param>
|
||||||
|
/// <returns>异步操作任务</returns>
|
||||||
|
public async Task DeleteAsync(string key)
|
||||||
|
{
|
||||||
|
await inner.DeleteAsync(Key(key));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 为给定的键添加前缀
|
/// 为给定的键添加前缀
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -6,10 +6,10 @@ namespace GFramework.Godot.setting;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Godot音频设置实现类,用于应用音频配置到Godot音频系统
|
/// Godot音频设置实现类,用于应用音频配置到Godot音频系统
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioSettings">音频设置对象,包含主音量、背景音乐音量和音效音量</param>
|
/// <param name="settings">音频设置对象,包含主音量、背景音乐音量和音效音量</param>
|
||||||
/// <param name="audioBusMapSettings">音频总线映射对象,定义了不同音频类型的总线名称</param>
|
/// <param name="audioBusMapSettings">音频总线映射对象,定义了不同音频类型的总线名称</param>
|
||||||
public class GodotAudioSettings(AudioSettings audioSettings, AudioBusMapSettings audioBusMapSettings)
|
public class GodotAudioSettings(AudioSettings settings, AudioBusMapSettings audioBusMapSettings)
|
||||||
: IApplyAbleSettings
|
: IPersistentApplyAbleSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 应用音频设置到Godot音频系统
|
/// 应用音频设置到Godot音频系统
|
||||||
@ -17,12 +17,17 @@ public class GodotAudioSettings(AudioSettings audioSettings, AudioBusMapSettings
|
|||||||
/// <returns>表示异步操作的任务</returns>
|
/// <returns>表示异步操作的任务</returns>
|
||||||
public Task Apply()
|
public Task Apply()
|
||||||
{
|
{
|
||||||
SetBus(audioBusMapSettings.Master, audioSettings.MasterVolume);
|
SetBus(audioBusMapSettings.Master, settings.MasterVolume);
|
||||||
SetBus(audioBusMapSettings.Bgm, audioSettings.BgmVolume);
|
SetBus(audioBusMapSettings.Bgm, settings.BgmVolume);
|
||||||
SetBus(audioBusMapSettings.Sfx, audioSettings.SfxVolume);
|
SetBus(audioBusMapSettings.Sfx, settings.SfxVolume);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
audioBusMapSettings.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置指定音频总线的音量
|
/// 设置指定音频总线的音量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace GFramework.Godot.setting;
|
|||||||
/// Godot图形设置应用器
|
/// Godot图形设置应用器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settings">图形设置配置对象</param>
|
/// <param name="settings">图形设置配置对象</param>
|
||||||
public class GodotGraphicsSettings(GraphicsSettings settings) : IApplyAbleSettings
|
public class GodotGraphicsSettings(GraphicsSettings settings) : IPersistentApplyAbleSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 应用图形设置到Godot引擎
|
/// 应用图形设置到Godot引擎
|
||||||
@ -40,4 +40,9 @@ public class GodotGraphicsSettings(GraphicsSettings settings) : IApplyAbleSettin
|
|||||||
|
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
settings.Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using GFramework.Core.Abstractions.serializer;
|
||||||
using GFramework.Core.Abstractions.storage;
|
using GFramework.Core.Abstractions.storage;
|
||||||
using GFramework.Game.Abstractions.serializer;
|
|
||||||
using GFramework.Godot.extensions;
|
using GFramework.Godot.extensions;
|
||||||
using Godot;
|
using Godot;
|
||||||
using FileAccess = Godot.FileAccess;
|
using FileAccess = Godot.FileAccess;
|
||||||
@ -44,6 +44,7 @@ public sealed class GodotFileStorage : IStorage
|
|||||||
|
|
||||||
lock (keyLock)
|
lock (keyLock)
|
||||||
{
|
{
|
||||||
|
// 处理Godot文件系统路径的删除操作
|
||||||
if (path.IsGodotPath())
|
if (path.IsGodotPath())
|
||||||
{
|
{
|
||||||
if (FileAccess.FileExists(path))
|
if (FileAccess.FileExists(path))
|
||||||
@ -53,6 +54,7 @@ public sealed class GodotFileStorage : IStorage
|
|||||||
throw new IOException($"Failed to delete Godot file: {path}, error: {err}");
|
throw new IOException($"Failed to delete Godot file: {path}, error: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 处理标准文件系统路径的删除操作
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (File.Exists(path)) File.Delete(path);
|
if (File.Exists(path)) File.Delete(path);
|
||||||
@ -63,6 +65,16 @@ public sealed class GodotFileStorage : IStorage
|
|||||||
_keyLocks.TryRemove(path, out _);
|
_keyLocks.TryRemove(path, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步删除指定键对应的文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">存储键</param>
|
||||||
|
/// <returns>异步任务</returns>
|
||||||
|
public async Task DeleteAsync(string key)
|
||||||
|
{
|
||||||
|
await Task.Run(() => Delete(key));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Helpers
|
#region Helpers
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user