diff --git a/GFramework.Core.Abstractions/architecture/ArchitectureModuleRegistry.cs b/GFramework.Core.Abstractions/architecture/ArchitectureModuleRegistry.cs new file mode 100644 index 0000000..1259545 --- /dev/null +++ b/GFramework.Core.Abstractions/architecture/ArchitectureModuleRegistry.cs @@ -0,0 +1,35 @@ +namespace GFramework.Core.Abstractions.architecture; + +/// +/// 架构模块注册表 - 用于外部模块的自动注册 +/// +public static class ArchitectureModuleRegistry +{ + private static readonly List> _factories = []; + + /// + /// 注册模块工厂 + /// + /// 模块工厂函数 + public static void Register(Func factory) + { + _factories.Add(factory); + } + + /// + /// 创建所有已注册的模块实例 + /// + /// 模块实例集合 + public static IEnumerable CreateModules() + { + return _factories.Select(f => f()); + } + + /// + /// 清空注册表(主要用于测试) + /// + public static void Clear() + { + _factories.Clear(); + } +} \ No newline at end of file diff --git a/GFramework.Core.Abstractions/properties/ArchitectureProperties.cs b/GFramework.Core.Abstractions/properties/ArchitectureProperties.cs index 1915685..f1a5eca 100644 --- a/GFramework.Core.Abstractions/properties/ArchitectureProperties.cs +++ b/GFramework.Core.Abstractions/properties/ArchitectureProperties.cs @@ -17,10 +17,4 @@ public sealed class ArchitectureProperties /// 默认值为 false,表示不启用严格验证。 /// public bool StrictPhaseValidation { get; set; } - - /// - /// 启用 ECS(Entity Component System)功能的开关。 - /// 当设置为 true 时,架构将启用 ECS 相关功能。 - /// - public bool EnableEcs { get; set; } } \ No newline at end of file diff --git a/GFramework.Core.Tests/GFramework.Core.Tests.csproj b/GFramework.Core.Tests/GFramework.Core.Tests.csproj index eed0620..f394be1 100644 --- a/GFramework.Core.Tests/GFramework.Core.Tests.csproj +++ b/GFramework.Core.Tests/GFramework.Core.Tests.csproj @@ -1,9 +1,11 @@  + net8.0;net10.0 disable enable - net10.0;net8.0 + false + true diff --git a/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs b/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs index efe5aad..936204b 100644 --- a/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs +++ b/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs @@ -15,7 +15,6 @@ using GFramework.Core.events; using GFramework.Core.ioc; using GFramework.Core.query; using Mediator; -using NUnit.Framework; using ICommand = GFramework.Core.Abstractions.command.ICommand; namespace GFramework.Core.Tests.architecture; @@ -269,27 +268,6 @@ public class ArchitectureServicesTests { Assert.That(_services!.ModuleManager, Is.Not.Null); } - - /// - /// 测试EnableEcs配置开关 - /// - [Test] - public void EnableEcs_Should_Control_Ecs_Module_Registration() - { - var propertiesWithEcs = new ArchitectureProperties { EnableEcs = true }; - var propertiesWithoutEcs = new ArchitectureProperties { EnableEcs = false }; - - var servicesWithEcs = new ArchitectureServices(); - servicesWithEcs.ModuleManager.RegisterBuiltInModules(servicesWithEcs.Container, propertiesWithEcs); - - var servicesWithoutEcs = new ArchitectureServices(); - servicesWithoutEcs.ModuleManager.RegisterBuiltInModules(servicesWithoutEcs.Container, propertiesWithoutEcs); - - var modulesWithEcs = servicesWithEcs.ModuleManager.GetModules(); - var modulesWithoutEcs = servicesWithoutEcs.ModuleManager.GetModules(); - - Assert.That(modulesWithEcs.Count, Is.GreaterThan(modulesWithoutEcs.Count)); - } } #region Test Classes diff --git a/GFramework.Core/GFramework.Core.csproj b/GFramework.Core/GFramework.Core.csproj index 05baa84..41e4b38 100644 --- a/GFramework.Core/GFramework.Core.csproj +++ b/GFramework.Core/GFramework.Core.csproj @@ -13,7 +13,5 @@ - - diff --git a/GFramework.Core/services/ServiceModuleManager.cs b/GFramework.Core/services/ServiceModuleManager.cs index 0f16073..68bd2c0 100644 --- a/GFramework.Core/services/ServiceModuleManager.cs +++ b/GFramework.Core/services/ServiceModuleManager.cs @@ -3,7 +3,6 @@ using GFramework.Core.Abstractions.ioc; using GFramework.Core.Abstractions.lifecycle; using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.properties; -using GFramework.Core.ecs; using GFramework.Core.logging; using GFramework.Core.services.modules; @@ -44,11 +43,11 @@ public sealed class ServiceModuleManager : IServiceModuleManager /// /// 注册内置服务模块,并根据优先级排序后完成服务注册。 - /// 内置模块包括事件总线、命令执行器、查询执行器等核心模块, - /// 并根据配置决定是否启用ECS模块。 + /// 内置模块包括事件总线、命令执行器、查询执行器等核心模块。 + /// 同时注册通过 ModuleInitializer 自动注册的外部模块。 /// /// IoC容器实例,用于模块服务注册。 - /// 架构属性配置,用于判断是否启用ECS模块。 + /// 架构属性配置。 public void RegisterBuiltInModules(IIocContainer container, ArchitectureProperties properties) { if (_builtInModulesRegistered) @@ -57,21 +56,25 @@ public sealed class ServiceModuleManager : IServiceModuleManager return; } + // 注册内置模块 RegisterModule(new EventBusModule()); RegisterModule(new CommandExecutorModule()); RegisterModule(new QueryExecutorModule()); RegisterModule(new AsyncQueryExecutorModule()); - if (properties.EnableEcs) + // 注册外部模块(通过 ModuleInitializer 自动注册) + foreach (var module in ArchitectureModuleRegistry.CreateModules()) { - RegisterModule(new ArchEcsModule(enabled: true)); - _logger.Info("ECS module enabled via configuration"); + RegisterModule(module); + _logger.Info($"External module registered: {module.ModuleName}"); } + // 按优先级排序 var sortedModules = _modules.OrderBy(m => m.Priority).ToList(); _modules.Clear(); _modules.AddRange(sortedModules); + // 注册服务 foreach (var module in _modules.Where(module => module.IsEnabled)) { _logger.Debug($"Registering services for module: {module.ModuleName}"); @@ -79,7 +82,7 @@ public sealed class ServiceModuleManager : IServiceModuleManager } _builtInModulesRegistered = true; - _logger.Info($"Registered {_modules.Count} built-in service modules"); + _logger.Info($"Registered {_modules.Count} service modules"); } /// diff --git a/GFramework.Ecs.Arch.Abstractions/ArchOptions.cs b/GFramework.Ecs.Arch.Abstractions/ArchOptions.cs new file mode 100644 index 0000000..926f877 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/ArchOptions.cs @@ -0,0 +1,22 @@ +namespace GFramework.Ecs.Arch.Abstractions; + +/// +/// Arch ECS 配置选项 +/// +public sealed class ArchOptions +{ + /// + /// World 初始容量 + /// + public int WorldCapacity { get; set; } = 1000; + + /// + /// 是否启用统计信息 + /// + public bool EnableStatistics { get; set; } + + /// + /// 模块优先级 + /// + public int Priority { get; set; } = 50; +} \ No newline at end of file diff --git a/GFramework.Ecs.Arch.Abstractions/Directory.Build.props b/GFramework.Ecs.Arch.Abstractions/Directory.Build.props new file mode 100644 index 0000000..8febdc4 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/Directory.Build.props @@ -0,0 +1,18 @@ + + + netstandard2.1 + true + true + preview + + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + + + diff --git a/GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj b/GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj new file mode 100644 index 0000000..b937843 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj @@ -0,0 +1,13 @@ + + + + GeWuYou.$(AssemblyName) + true + enable + + + + + + + diff --git a/GFramework.Ecs.Arch.Abstractions/GlobalUsings.cs b/GFramework.Ecs.Arch.Abstractions/GlobalUsings.cs new file mode 100644 index 0000000..9d7f7e7 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/GlobalUsings.cs @@ -0,0 +1,3 @@ +global using System; +global using System.Collections.Generic; +global using System.Threading.Tasks; \ No newline at end of file diff --git a/GFramework.Ecs.Arch.Abstractions/IArchEcsModule.cs b/GFramework.Ecs.Arch.Abstractions/IArchEcsModule.cs new file mode 100644 index 0000000..6dcc631 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/IArchEcsModule.cs @@ -0,0 +1,15 @@ +using GFramework.Core.Abstractions.architecture; + +namespace GFramework.Ecs.Arch.Abstractions; + +/// +/// Arch ECS 模块接口 - 定义 ECS 模块的核心契约 +/// +public interface IArchEcsModule : IServiceModule +{ + /// + /// 更新所有 ECS 系统 + /// + /// 帧间隔时间 + void Update(float deltaTime); +} \ No newline at end of file diff --git a/GFramework.Ecs.Arch.Abstractions/IArchSystemAdapter.cs b/GFramework.Ecs.Arch.Abstractions/IArchSystemAdapter.cs new file mode 100644 index 0000000..59c42d6 --- /dev/null +++ b/GFramework.Ecs.Arch.Abstractions/IArchSystemAdapter.cs @@ -0,0 +1,16 @@ +using GFramework.Core.Abstractions.system; + +namespace GFramework.Ecs.Arch.Abstractions; + +/// +/// Arch 系统适配器接口 - 桥接 Arch.System.ISystem<T> 到框架上下文 +/// +/// 系统数据类型(通常是 float 表示 deltaTime) +public interface IArchSystemAdapter : ISystem +{ + /// + /// 更新系统 + /// + /// 系统数据参数(通常是 deltaTime) + void Update(in T t); +} \ No newline at end of file diff --git a/GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj b/GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj new file mode 100644 index 0000000..1d5346f --- /dev/null +++ b/GFramework.Ecs.Arch.Tests/GFramework.Ecs.Arch.Tests.csproj @@ -0,0 +1,25 @@ + + + + net8.0;net10.0 + disable + enable + false + true + false + + + + + + + + + + + + + + + + diff --git a/GFramework.Ecs.Arch.Tests/GlobalUsings.cs b/GFramework.Ecs.Arch.Tests/GlobalUsings.cs new file mode 100644 index 0000000..170ef5b --- /dev/null +++ b/GFramework.Ecs.Arch.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using System; +global using System.Collections.Generic; +global using System.Threading.Tasks; +global using NUnit.Framework; +global using GFramework.Ecs.Arch; \ No newline at end of file diff --git a/GFramework.Core.Tests/ecs/EcsAdvancedTests.cs b/GFramework.Ecs.Arch.Tests/ecs/EcsAdvancedTests.cs similarity index 97% rename from GFramework.Core.Tests/ecs/EcsAdvancedTests.cs rename to GFramework.Ecs.Arch.Tests/ecs/EcsAdvancedTests.cs index 3831138..3ef8f07 100644 --- a/GFramework.Core.Tests/ecs/EcsAdvancedTests.cs +++ b/GFramework.Ecs.Arch.Tests/ecs/EcsAdvancedTests.cs @@ -2,13 +2,11 @@ using System.Diagnostics.CodeAnalysis; using Arch.Core; using GFramework.Core.Abstractions.rule; using GFramework.Core.architecture; -using GFramework.Core.ecs; -using GFramework.Core.ecs.components; -using GFramework.Core.ecs.systems; using GFramework.Core.ioc; -using NUnit.Framework; +using GFramework.Ecs.Arch.components; +using GFramework.Ecs.Arch.systems; -namespace GFramework.Core.Tests.ecs; +namespace GFramework.Ecs.Arch.Tests.ecs; /// /// ECS 高级功能测试类 - 使用 Arch 原生 API diff --git a/GFramework.Core.Tests/ecs/EcsBasicTests.cs b/GFramework.Ecs.Arch.Tests/ecs/EcsBasicTests.cs similarity index 96% rename from GFramework.Core.Tests/ecs/EcsBasicTests.cs rename to GFramework.Ecs.Arch.Tests/ecs/EcsBasicTests.cs index c1d9f52..896789a 100644 --- a/GFramework.Core.Tests/ecs/EcsBasicTests.cs +++ b/GFramework.Ecs.Arch.Tests/ecs/EcsBasicTests.cs @@ -2,13 +2,11 @@ using System.Diagnostics.CodeAnalysis; using Arch.Core; using GFramework.Core.Abstractions.rule; using GFramework.Core.architecture; -using GFramework.Core.ecs; -using GFramework.Core.ecs.components; -using GFramework.Core.ecs.systems; using GFramework.Core.ioc; -using NUnit.Framework; +using GFramework.Ecs.Arch.components; +using GFramework.Ecs.Arch.systems; -namespace GFramework.Core.Tests.ecs; +namespace GFramework.Ecs.Arch.Tests.ecs; /// /// ECS 基础功能测试类 - 使用 Arch 原生 API diff --git a/GFramework.Core.Tests/ecs/EcsIntegrationTests.cs b/GFramework.Ecs.Arch.Tests/ecs/EcsIntegrationTests.cs similarity index 97% rename from GFramework.Core.Tests/ecs/EcsIntegrationTests.cs rename to GFramework.Ecs.Arch.Tests/ecs/EcsIntegrationTests.cs index 55287a9..db9c290 100644 --- a/GFramework.Core.Tests/ecs/EcsIntegrationTests.cs +++ b/GFramework.Ecs.Arch.Tests/ecs/EcsIntegrationTests.cs @@ -2,13 +2,11 @@ using System.Diagnostics.CodeAnalysis; using Arch.Core; using GFramework.Core.Abstractions.rule; using GFramework.Core.architecture; -using GFramework.Core.ecs; -using GFramework.Core.ecs.components; -using GFramework.Core.ecs.systems; using GFramework.Core.ioc; -using NUnit.Framework; +using GFramework.Ecs.Arch.components; +using GFramework.Ecs.Arch.systems; -namespace GFramework.Core.Tests.ecs; +namespace GFramework.Ecs.Arch.Tests.ecs; /// /// ECS 集成测试类 - 使用 Arch 原生 API diff --git a/GFramework.Ecs.Arch.Tests/integration/AutoRegistrationTests.cs b/GFramework.Ecs.Arch.Tests/integration/AutoRegistrationTests.cs new file mode 100644 index 0000000..b0a6d5f --- /dev/null +++ b/GFramework.Ecs.Arch.Tests/integration/AutoRegistrationTests.cs @@ -0,0 +1,75 @@ +using System.Linq; +using Arch.Core; +using GFramework.Core.Abstractions.properties; +using GFramework.Core.architecture; +using GFramework.Core.ioc; +using GFramework.Ecs.Arch.Abstractions; + +namespace GFramework.Ecs.Arch.Tests.integration; + +/// +/// 自动注册集成测试 +/// +[TestFixture] +public class AutoRegistrationTests +{ + [SetUp] + public void Setup() + { + _container = new MicrosoftDiContainer(); + _context = new ArchitectureContext(_container); + } + + [TearDown] + public void TearDown() + { + _container?.Clear(); + _context = null; + } + + private MicrosoftDiContainer? _container; + private ArchitectureContext? _context; + + /// + /// 测试 Arch ECS 模块是否自动注册 + /// + [Test] + public void ArchEcsModule_Should_Be_Auto_Registered() + { + // Arrange - 手动触发模块初始化器(模拟自动注册) + ArchModuleInitializer.Initialize(); + + var services = new ArchitectureServices(); + var properties = new ArchitectureProperties(); + + // Act + services.ModuleManager.RegisterBuiltInModules(services.Container, properties); + var modules = services.ModuleManager.GetModules(); + + // Assert + var archModule = modules.FirstOrDefault(m => m.ModuleName == nameof(ArchEcsModule)); + Assert.That(archModule, Is.Not.Null, "ArchEcsModule should be auto-registered"); + Assert.That(archModule, Is.InstanceOf()); + } + + /// + /// 测试 World 是否正确注册到容器 + /// + [Test] + public void World_Should_Be_Registered_In_Container() + { + // Arrange - 手动触发模块初始化器 + ArchModuleInitializer.Initialize(); + + var services = new ArchitectureServices(); + var properties = new ArchitectureProperties(); + + // Act + services.ModuleManager.RegisterBuiltInModules(services.Container, properties); + services.ModuleManager.InitializeAllAsync(false).Wait(); + + // Assert + var world = services.Container.Get(); + Assert.That(world, Is.Not.Null, "World should be registered in container"); + } +} \ No newline at end of file diff --git a/GFramework.Core/ecs/ArchEcsModule.cs b/GFramework.Ecs.Arch/ArchEcsModule.cs similarity index 95% rename from GFramework.Core/ecs/ArchEcsModule.cs rename to GFramework.Ecs.Arch/ArchEcsModule.cs index 784b822..cad7205 100644 --- a/GFramework.Core/ecs/ArchEcsModule.cs +++ b/GFramework.Ecs.Arch/ArchEcsModule.cs @@ -1,13 +1,12 @@ using Arch.Core; -using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.ioc; -namespace GFramework.Core.ecs; +namespace GFramework.Ecs.Arch; /// /// Arch ECS 模块 - 核心适配器,桥接 Arch 到框架生命周期 /// -public sealed class ArchEcsModule : IServiceModule +public sealed class ArchEcsModule : IArchEcsModule { private readonly List> _systems = []; private IIocContainer? _container; diff --git a/GFramework.Ecs.Arch/ArchModuleInitializer.cs b/GFramework.Ecs.Arch/ArchModuleInitializer.cs new file mode 100644 index 0000000..5e8a7f4 --- /dev/null +++ b/GFramework.Ecs.Arch/ArchModuleInitializer.cs @@ -0,0 +1,21 @@ +using System.Runtime.CompilerServices; +using GFramework.Core.Abstractions.architecture; + +namespace GFramework.Ecs.Arch; + +/// +/// Arch ECS 模块自动初始化器 +/// 使用 ModuleInitializer 特性在程序启动时自动注册模块 +/// +public static class ArchModuleInitializer +{ + /// + /// 模块初始化方法,在程序启动时自动调用 + /// + [ModuleInitializer] + public static void Initialize() + { + // 注册 Arch ECS 模块工厂 + ArchitectureModuleRegistry.Register(() => new ArchEcsModule(enabled: true)); + } +} \ No newline at end of file diff --git a/GFramework.Core/ecs/ArchSystemAdapter.cs b/GFramework.Ecs.Arch/ArchSystemAdapter.cs similarity index 96% rename from GFramework.Core/ecs/ArchSystemAdapter.cs rename to GFramework.Ecs.Arch/ArchSystemAdapter.cs index 8a86c98..6f7e99f 100644 --- a/GFramework.Core/ecs/ArchSystemAdapter.cs +++ b/GFramework.Ecs.Arch/ArchSystemAdapter.cs @@ -3,19 +3,29 @@ using GFramework.Core.extensions; using GFramework.Core.system; using ArchSys = Arch.System; -namespace GFramework.Core.ecs; +namespace GFramework.Ecs.Arch; /// /// Arch 系统适配器 - 桥接 Arch.System.ISystem<T> 到框架上下文 /// /// 系统数据类型(通常是 float 表示 deltaTime) -public abstract class ArchSystemAdapter : AbstractSystem, ArchSys.ISystem +public abstract class ArchSystemAdapter : AbstractSystem, IArchSystemAdapter, ArchSys.ISystem { /// /// 获取或设置 Arch ECS 世界的实例 /// public World World { get; private set; } = null!; + /// + /// 显式实现 Arch.System.ISystem<T> 的主更新方法 + /// 调用受保护的虚方法 OnUpdate 以强制子类实现核心更新逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + public void Update(in T t) + { + OnUpdate(in t); + } + // ===== Arch 显式接口实现 ===== /// @@ -37,16 +47,6 @@ public abstract class ArchSystemAdapter : AbstractSystem, ArchSys.ISystem OnBeforeUpdate(in t); } - /// - /// 显式实现 Arch.System.ISystem<T> 的主更新方法 - /// 调用受保护的虚方法 OnUpdate 以强制子类实现核心更新逻辑 - /// - /// 系统数据参数(通常是 deltaTime) - public void Update(in T t) - { - OnUpdate(in t); - } - /// /// 显式实现 Arch.System.ISystem<T> 的更新后回调方法 /// 调用受保护的虚方法 OnAfterUpdate 以允许子类自定义后处理逻辑 diff --git a/GFramework.Ecs.Arch/GFramework.Ecs.Arch.csproj b/GFramework.Ecs.Arch/GFramework.Ecs.Arch.csproj new file mode 100644 index 0000000..2b58a0e --- /dev/null +++ b/GFramework.Ecs.Arch/GFramework.Ecs.Arch.csproj @@ -0,0 +1,23 @@ + + + + GeWuYou.$(AssemblyName) + net8.0;net9.0;net10.0 + disable + enable + true + true + + + + + + + + + + + + + diff --git a/GFramework.Ecs.Arch/GlobalUsings.cs b/GFramework.Ecs.Arch/GlobalUsings.cs new file mode 100644 index 0000000..50bd209 --- /dev/null +++ b/GFramework.Ecs.Arch/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using System; +global using System.Collections.Generic; +global using System.Threading.Tasks; +global using GFramework.Core.Abstractions; +global using GFramework.Ecs.Arch.Abstractions; \ No newline at end of file diff --git a/GFramework.Ecs.Arch/README.md b/GFramework.Ecs.Arch/README.md new file mode 100644 index 0000000..1525346 --- /dev/null +++ b/GFramework.Ecs.Arch/README.md @@ -0,0 +1,170 @@ +# GFramework.Ecs.Arch + +GFramework 的 Arch ECS 集成包,提供开箱即用的 ECS(Entity Component System)支持。 + +## 特性 + +- 🚀 **自动集成** - 引入 NuGet 包即可自动启用,无需手动配置 +- 🔌 **零依赖** - 不使用时,Core 包无 Arch 依赖 +- 🎯 **类型安全** - 完整的类型系统和编译时检查 +- ⚡ **高性能** - 基于 Arch ECS 的高性能实现 +- 🔧 **易扩展** - 简单的系统适配器模式 + +## 快速开始 + +### 1. 安装包 + +```bash +dotnet add package GeWuYou.GFramework.Ecs.Arch +``` + +### 2. 创建组件 + +```csharp +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Sequential)] +public struct Position(float x, float y) +{ + public float X { get; set; } = x; + public float Y { get; set; } = y; +} + +[StructLayout(LayoutKind.Sequential)] +public struct Velocity(float x, float y) +{ + public float X { get; set; } = x; + public float Y { get; set; } = y; +} +``` + +### 3. 创建系统 + +```csharp +using Arch.Core; +using GFramework.Ecs.Arch; + +public sealed class MovementSystem : ArchSystemAdapter +{ + private QueryDescription _query; + + protected override void OnArchInitialize() + { + _query = new QueryDescription() + .WithAll(); + } + + protected override void OnUpdate(in float deltaTime) + { + World.Query(in _query, (ref Position pos, ref Velocity vel) => + { + pos.X += vel.X * deltaTime; + pos.Y += vel.Y * deltaTime; + }); + } +} +``` + +### 4. 注册系统 + +```csharp +public class MyArchitecture : Architecture +{ + protected override void OnRegisterSystem(IIocContainer container) + { + container.Register(); + } +} +``` + +### 5. 创建实体 + +```csharp +var world = this.GetService(); +var entity = world.Create( + new Position(0, 0), + new Velocity(1, 1) +); +``` + +### 6. 更新系统 + +```csharp +var ecsModule = this.GetService(); +ecsModule.Update(deltaTime); +``` + +## 配置选项 + +可以通过配置文件或代码配置 Arch ECS: + +### 代码配置 + +```csharp +services.ConfigureArch(options => +{ + options.WorldCapacity = 2000; + options.EnableStatistics = true; + options.Priority = 50; +}); +``` + +### 配置文件 + +```json +{ + "GFramework": { + "Modules": { + "Arch": { + "Enabled": true, + "Priority": 50, + "WorldCapacity": 1000, + "EnableStatistics": false + } + } + } +} +``` + +## 架构说明 + +### 模块自动注册 + +本包使用 `ModuleInitializer` 特性实现自动注册,无需手动配置: + +```csharp +[ModuleInitializer] +public static void Initialize() +{ + ArchitectureModuleRegistry.Register(() => new ArchEcsModule(enabled: true)); +} +``` + +### 系统适配器 + +`ArchSystemAdapter` 桥接 Arch.System.ISystem 到 GFramework 架构: + +- 自动获取 World 实例 +- 集成到框架生命周期 +- 支持上下文感知(Context-Aware) + +### 生命周期 + +1. **注册阶段** - 模块自动注册到架构 +2. **初始化阶段** - 创建 World,初始化系统 +3. **运行阶段** - 每帧调用 Update +4. **销毁阶段** - 清理资源,销毁 World + +## 示例 + +完整示例请参考 `GFramework.Ecs.Arch.Tests` 项目。 + +## 依赖 + +- GFramework.Core >= 1.0.0 +- Arch >= 2.1.0 +- Arch.System >= 1.1.0 + +## 许可证 + +MIT License diff --git a/GFramework.Core/ecs/components/Position.cs b/GFramework.Ecs.Arch/components/Position.cs similarity index 92% rename from GFramework.Core/ecs/components/Position.cs rename to GFramework.Ecs.Arch/components/Position.cs index 204f66d..fe625d0 100644 --- a/GFramework.Core/ecs/components/Position.cs +++ b/GFramework.Ecs.Arch/components/Position.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace GFramework.Core.ecs.components; +namespace GFramework.Ecs.Arch.components; /// /// 位置组件,用于表示实体在二维空间中的坐标位置。 diff --git a/GFramework.Core/ecs/components/Velocity.cs b/GFramework.Ecs.Arch/components/Velocity.cs similarity index 93% rename from GFramework.Core/ecs/components/Velocity.cs rename to GFramework.Ecs.Arch/components/Velocity.cs index 26465b2..dab5eb6 100644 --- a/GFramework.Core/ecs/components/Velocity.cs +++ b/GFramework.Ecs.Arch/components/Velocity.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace GFramework.Core.ecs.components; +namespace GFramework.Ecs.Arch.components; /// /// 速度结构体,用于表示二维空间中实体的瞬时速度向量 diff --git a/GFramework.Ecs.Arch/extensions/ArchExtensions.cs b/GFramework.Ecs.Arch/extensions/ArchExtensions.cs new file mode 100644 index 0000000..7dcd08d --- /dev/null +++ b/GFramework.Ecs.Arch/extensions/ArchExtensions.cs @@ -0,0 +1,34 @@ +using GFramework.Core.Abstractions.architecture; +using Microsoft.Extensions.DependencyInjection; + +namespace GFramework.Ecs.Arch.extensions; + +/// +/// Arch ECS 扩展方法 +/// +public static class ArchExtensions +{ + /// + /// 配置 Arch ECS 选项 + /// + public static IServiceCollection ConfigureArch( + this IServiceCollection services, + Action configure) + { + var options = new ArchOptions(); + configure(options); + services.AddSingleton(options); + return services; + } + + /// + /// 显式启用 Arch ECS 模块(备选方案) + /// + public static TArchitecture UseArch(this TArchitecture architecture) + where TArchitecture : IArchitecture + { + // 此方法为显式注册提供支持 + // 实际注册由 ModuleInitializer 自动完成 + return architecture; + } +} \ No newline at end of file diff --git a/GFramework.Core/ecs/systems/MovementSystem.cs b/GFramework.Ecs.Arch/systems/MovementSystem.cs similarity index 92% rename from GFramework.Core/ecs/systems/MovementSystem.cs rename to GFramework.Ecs.Arch/systems/MovementSystem.cs index 897ca8b..3f3b923 100644 --- a/GFramework.Core/ecs/systems/MovementSystem.cs +++ b/GFramework.Ecs.Arch/systems/MovementSystem.cs @@ -1,7 +1,7 @@ using Arch.Core; -using GFramework.Core.ecs.components; +using GFramework.Ecs.Arch.components; -namespace GFramework.Core.ecs.systems; +namespace GFramework.Ecs.Arch.systems; /// /// 移动系统 - 继承 ArchSystemAdapter diff --git a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj index 3a8c827..4941dcf 100644 --- a/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj +++ b/GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj @@ -1,9 +1,11 @@  + net8.0;net10.0 disable enable - net10.0;net8.0 + false + true diff --git a/GFramework.csproj b/GFramework.csproj index 09f1d65..ae91b88 100644 --- a/GFramework.csproj +++ b/GFramework.csproj @@ -47,6 +47,9 @@ + + + @@ -82,6 +85,9 @@ + + + @@ -103,6 +109,9 @@ + + + diff --git a/GFramework.sln b/GFramework.sln index 3eba55b..04b1d8f 100644 --- a/GFramework.sln +++ b/GFramework.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework ", "GFramework.csproj", "{9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework", "GFramework.csproj", "{9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.SourceGenerators", "GFramework.SourceGenerators\GFramework.SourceGenerators.csproj", "{E9D51809-0351-4B83-B85B-B5F469AAB3B8}" EndProject @@ -26,63 +26,216 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Game.Abstraction EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Core.Tests", "GFramework.Core.Tests\GFramework.Core.Tests.csproj", "{759BCD95-A9D9-4D8F-9255-A9F1B661DF74}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Ecs.Arch.Abstractions", "GFramework.Ecs.Arch.Abstractions\GFramework.Ecs.Arch.Abstractions.csproj", "{5E1488B2-6554-408D-83FB-EB2FFFABF545}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Ecs.Arch", "GFramework.Ecs.Arch\GFramework.Ecs.Arch.csproj", "{E9B49EE9-25BC-47C1-83CE-92F636B9D491}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GFramework.Ecs.Arch.Tests", "GFramework.Ecs.Arch.Tests\GFramework.Ecs.Arch.Tests.csproj", "{112CF413-4596-4AA3-B3FE-65532802FDD6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|x64.ActiveCfg = Debug|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|x64.Build.0 = Debug|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|x86.ActiveCfg = Debug|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Debug|x86.Build.0 = Debug|Any CPU {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|Any CPU.ActiveCfg = Release|Any CPU {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|Any CPU.Build.0 = Release|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x64.ActiveCfg = Release|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x64.Build.0 = Release|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x86.ActiveCfg = Release|Any CPU + {9BEDDD6C-DF8B-4E71-9C75-F44EC669ABBD}.Release|x86.Build.0 = Release|Any CPU {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x64.ActiveCfg = Debug|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x64.Build.0 = Debug|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x86.ActiveCfg = Debug|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Debug|x86.Build.0 = Debug|Any CPU {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|Any CPU.Build.0 = Release|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x64.ActiveCfg = Release|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x64.Build.0 = Release|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x86.ActiveCfg = Release|Any CPU + {E9D51809-0351-4B83-B85B-B5F469AAB3B8}.Release|x86.Build.0 = Release|Any CPU {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x64.ActiveCfg = Debug|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x64.Build.0 = Debug|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x86.ActiveCfg = Debug|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Debug|x86.Build.0 = Debug|Any CPU {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|Any CPU.ActiveCfg = Release|Any CPU {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|Any CPU.Build.0 = Release|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x64.ActiveCfg = Release|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x64.Build.0 = Release|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x86.ActiveCfg = Release|Any CPU + {84C5C3C9-5620-4924-BA04-92F813F2B70F}.Release|x86.Build.0 = Release|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|x64.Build.0 = Debug|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|x86.ActiveCfg = Debug|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Debug|x86.Build.0 = Debug|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|Any CPU.Build.0 = Release|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|x64.ActiveCfg = Release|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|x64.Build.0 = Release|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|x86.ActiveCfg = Release|Any CPU + {A6D5854D-79EA-487A-9ED9-396E6A1F8031}.Release|x86.Build.0 = Release|Any CPU {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|x64.ActiveCfg = Debug|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|x64.Build.0 = Debug|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|x86.ActiveCfg = Debug|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Debug|x86.Build.0 = Debug|Any CPU {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|Any CPU.Build.0 = Release|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|x64.ActiveCfg = Release|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|x64.Build.0 = Release|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|x86.ActiveCfg = Release|Any CPU + {FC56D81A-3A3B-4B49-B318-363DFA0D8206}.Release|x86.Build.0 = Release|Any CPU {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|x64.ActiveCfg = Debug|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|x64.Build.0 = Debug|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|x86.ActiveCfg = Debug|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Debug|x86.Build.0 = Debug|Any CPU {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|Any CPU.Build.0 = Release|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|x64.ActiveCfg = Release|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|x64.Build.0 = Release|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|x86.ActiveCfg = Release|Any CPU + {0B00816B-E8B2-4562-8C11-0C06CE761638}.Release|x86.Build.0 = Release|Any CPU {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|x64.ActiveCfg = Debug|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|x64.Build.0 = Debug|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|x86.ActiveCfg = Debug|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Debug|x86.Build.0 = Debug|Any CPU {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|Any CPU.Build.0 = Release|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|x64.ActiveCfg = Release|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|x64.Build.0 = Release|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|x86.ActiveCfg = Release|Any CPU + {C56FD287-CBC6-4C44-B3DF-103FA3660CA0}.Release|x86.Build.0 = Release|Any CPU {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|x64.ActiveCfg = Debug|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|x64.Build.0 = Debug|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|x86.ActiveCfg = Debug|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Debug|x86.Build.0 = Debug|Any CPU {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|Any CPU.Build.0 = Release|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|x64.ActiveCfg = Release|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|x64.Build.0 = Release|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|x86.ActiveCfg = Release|Any CPU + {3A1132B7-EC3B-4BB6-A752-8ADC92BC08A0}.Release|x86.Build.0 = Release|Any CPU {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|x64.ActiveCfg = Debug|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|x64.Build.0 = Debug|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|x86.ActiveCfg = Debug|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Debug|x86.Build.0 = Debug|Any CPU {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|Any CPU.Build.0 = Release|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|x64.ActiveCfg = Release|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|x64.Build.0 = Release|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|x86.ActiveCfg = Release|Any CPU + {BB047F43-6AA0-4EA0-8AE9-E6B9784D9E8E}.Release|x86.Build.0 = Release|Any CPU {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|x64.ActiveCfg = Debug|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|x64.Build.0 = Debug|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Debug|x86.Build.0 = Debug|Any CPU {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|Any CPU.Build.0 = Release|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|x64.ActiveCfg = Release|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|x64.Build.0 = Release|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|x86.ActiveCfg = Release|Any CPU + {B6511C9A-40E1-4E51-8D1F-18EAFB3C5BFC}.Release|x86.Build.0 = Release|Any CPU {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|x64.ActiveCfg = Debug|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|x64.Build.0 = Debug|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|x86.ActiveCfg = Debug|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Debug|x86.Build.0 = Debug|Any CPU {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|Any CPU.ActiveCfg = Release|Any CPU {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|Any CPU.Build.0 = Release|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|x64.ActiveCfg = Release|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|x64.Build.0 = Release|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|x86.ActiveCfg = Release|Any CPU + {31BA9F62-153A-4943-A8A0-7571FC7D5FEE}.Release|x86.Build.0 = Release|Any CPU {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|x64.ActiveCfg = Debug|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|x64.Build.0 = Debug|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|x86.ActiveCfg = Debug|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Debug|x86.Build.0 = Debug|Any CPU {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|Any CPU.ActiveCfg = Release|Any CPU {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|Any CPU.Build.0 = Release|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|x64.ActiveCfg = Release|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|x64.Build.0 = Release|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|x86.ActiveCfg = Release|Any CPU + {E20DBA4C-CEB9-4184-B614-5A99A9AE4472}.Release|x86.Build.0 = Release|Any CPU {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|x64.ActiveCfg = Debug|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|x64.Build.0 = Debug|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|x86.ActiveCfg = Debug|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Debug|x86.Build.0 = Debug|Any CPU {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|Any CPU.ActiveCfg = Release|Any CPU {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|Any CPU.Build.0 = Release|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|x64.ActiveCfg = Release|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|x64.Build.0 = Release|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|x86.ActiveCfg = Release|Any CPU + {759BCD95-A9D9-4D8F-9255-A9F1B661DF74}.Release|x86.Build.0 = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|x64.ActiveCfg = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|x64.Build.0 = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|x86.ActiveCfg = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Debug|x86.Build.0 = Debug|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|Any CPU.Build.0 = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|x64.ActiveCfg = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|x64.Build.0 = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|x86.ActiveCfg = Release|Any CPU + {5E1488B2-6554-408D-83FB-EB2FFFABF545}.Release|x86.Build.0 = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|x64.ActiveCfg = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|x64.Build.0 = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|x86.ActiveCfg = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Debug|x86.Build.0 = Debug|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|Any CPU.Build.0 = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|x64.ActiveCfg = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|x64.Build.0 = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|x86.ActiveCfg = Release|Any CPU + {E9B49EE9-25BC-47C1-83CE-92F636B9D491}.Release|x86.Build.0 = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|x64.ActiveCfg = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|x64.Build.0 = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|x86.ActiveCfg = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Debug|x86.Build.0 = Debug|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|Any CPU.Build.0 = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|x64.ActiveCfg = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|x64.Build.0 = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|x86.ActiveCfg = Release|Any CPU + {112CF413-4596-4AA3-B3FE-65532802FDD6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal