mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
refactor(scene): 重构场景路由系统并迁移资源注册接口
- 将场景路由基类从同步改为异步实现,支持场景栈管理 - 添加场景行为接口定义及相关的进入参数接口 - 实现场景的压入、弹出、替换和清空等栈操作功能 - 迁移UI资源注册接口到资产模块下 - 移除缓存淘汰策略枚举并更新UI切换阶段命名空间引用 - 优化日志记录器创建方式和统一命名空间规范
This commit is contained in:
parent
d0e7a9fb9b
commit
65d56d0696
@ -1,7 +1,7 @@
|
||||
using GFramework.Core.Abstractions.registries;
|
||||
using GFramework.Core.Abstractions.utility;
|
||||
|
||||
namespace GFramework.Game.Abstractions.ui;
|
||||
namespace GFramework.Game.Abstractions.asset;
|
||||
|
||||
/// <summary>
|
||||
/// 资源注册表接口,用于管理指定类型T的资源注册和查找
|
||||
@ -1,17 +0,0 @@
|
||||
namespace GFramework.Game.Abstractions.enums;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存淘汰策略枚举
|
||||
/// </summary>
|
||||
public enum CacheEvictionPolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// 最近最少使用
|
||||
/// </summary>
|
||||
Lru,
|
||||
|
||||
/// <summary>
|
||||
/// 最少使用频率
|
||||
/// </summary>
|
||||
Lfu
|
||||
}
|
||||
@ -4,7 +4,7 @@ namespace GFramework.Game.Abstractions.enums;
|
||||
/// UI切换阶段枚举,定义UI切换过程中的不同阶段
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum UITransitionPhases
|
||||
public enum UiTransitionPhases
|
||||
{
|
||||
/// <summary>
|
||||
/// UI切换前阶段,在此阶段执行的Handler可以阻塞UI切换流程
|
||||
|
||||
64
GFramework.Game.Abstractions/scene/IScene.cs
Normal file
64
GFramework.Game.Abstractions/scene/IScene.cs
Normal file
@ -0,0 +1,64 @@
|
||||
// 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.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 场景接口,定义了场景生命周期管理的核心方法。
|
||||
/// 实现此接口的类需要处理场景从加载到卸载的完整生命周期。
|
||||
/// </summary>
|
||||
public interface IScene
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步加载场景所需资源。
|
||||
/// 在场景正式进入前调用,负责预加载场景所需的各类资源。
|
||||
/// </summary>
|
||||
/// <param name="param">场景进入参数,可能包含初始化数据或上下文信息。</param>
|
||||
/// <returns>表示加载操作完成的ValueTask。</returns>
|
||||
ValueTask OnLoadAsync(ISceneEnterParam? param);
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景正式进入逻辑。
|
||||
/// 在资源加载完成后调用,启动场景的主要运行逻辑。
|
||||
/// </summary>
|
||||
/// <returns>表示进入操作完成的ValueTask。</returns>
|
||||
ValueTask OnEnterAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景暂停逻辑。
|
||||
/// 当场景被其他场景覆盖或失去焦点时调用。
|
||||
/// </summary>
|
||||
/// <returns>表示暂停操作完成的ValueTask。</returns>
|
||||
ValueTask OnPauseAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景恢复逻辑。
|
||||
/// 当场景重新获得焦点或从暂停状态恢复时调用。
|
||||
/// </summary>
|
||||
/// <returns>表示恢复操作完成的ValueTask。</returns>
|
||||
ValueTask OnResumeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景退出逻辑。
|
||||
/// 在场景即将被替换或关闭时调用,执行清理工作。
|
||||
/// </summary>
|
||||
/// <returns>表示退出操作完成的ValueTask。</returns>
|
||||
ValueTask OnExitAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载场景资源。
|
||||
/// 在场景完全退出后调用,释放占用的内存和资源。
|
||||
/// </summary>
|
||||
/// <returns>表示卸载操作完成的ValueTask。</returns>
|
||||
ValueTask OnUnloadAsync();
|
||||
}
|
||||
88
GFramework.Game.Abstractions/scene/ISceneBehavior.cs
Normal file
88
GFramework.Game.Abstractions/scene/ISceneBehavior.cs
Normal file
@ -0,0 +1,88 @@
|
||||
// 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.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 场景行为接口,定义了场景生命周期管理的标准方法。
|
||||
/// 实现此接口的类需要处理场景的加载、激活、暂停、恢复和卸载等核心操作。
|
||||
/// </summary>
|
||||
public interface ISceneBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取场景的唯一标识符。
|
||||
/// 用于区分不同的场景实例。
|
||||
/// </summary>
|
||||
string Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取场景是否已加载完成的状态。
|
||||
/// true表示场景资源已加载,false表示未加载或正在加载中。
|
||||
/// </summary>
|
||||
bool IsLoaded { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取场景是否处于活跃运行状态。
|
||||
/// true表示场景正在前台运行,false表示场景已暂停或未激活。
|
||||
/// </summary>
|
||||
bool IsActive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取场景是否正在进行切换操作。
|
||||
/// true表示场景正在加载、卸载或过渡中,false表示场景状态稳定。
|
||||
/// </summary>
|
||||
bool IsTransitioning { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载场景所需资源。
|
||||
/// 在场景正式进入前调用,负责预加载场景所需的各类资源。
|
||||
/// </summary>
|
||||
/// <param name="param">场景进入参数,可能包含初始化数据或上下文信息。</param>
|
||||
/// <returns>表示加载操作完成的ValueTask。</returns>
|
||||
ValueTask OnLoadAsync(ISceneEnterParam? param);
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景正式进入逻辑。
|
||||
/// 在资源加载完成后调用,启动场景的主要运行逻辑。
|
||||
/// </summary>
|
||||
/// <returns>表示进入操作完成的ValueTask。</returns>
|
||||
ValueTask OnEnterAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景暂停逻辑。
|
||||
/// 当场景被其他场景覆盖或失去焦点时调用。
|
||||
/// </summary>
|
||||
/// <returns>表示暂停操作完成的ValueTask。</returns>
|
||||
ValueTask OnPauseAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景恢复逻辑。
|
||||
/// 当场景重新获得焦点或从暂停状态恢复时调用。
|
||||
/// </summary>
|
||||
/// <returns>表示恢复操作完成的ValueTask。</returns>
|
||||
ValueTask OnResumeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步处理场景退出逻辑。
|
||||
/// 在场景即将被替换或关闭时调用,执行清理工作。
|
||||
/// </summary>
|
||||
/// <returns>表示退出操作完成的ValueTask。</returns>
|
||||
ValueTask OnExitAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载场景资源。
|
||||
/// 在场景完全退出后调用,释放占用的内存和资源。
|
||||
/// </summary>
|
||||
/// <returns>表示卸载操作完成的ValueTask。</returns>
|
||||
ValueTask OnUnloadAsync();
|
||||
}
|
||||
27
GFramework.Game.Abstractions/scene/ISceneBehaviorProvider.cs
Normal file
27
GFramework.Game.Abstractions/scene/ISceneBehaviorProvider.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 场景行为提供者接口,用于获取场景行为实例。
|
||||
/// 实现此接口的类负责创建和提供具体的场景行为对象。
|
||||
/// </summary>
|
||||
public interface ISceneBehaviorProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取场景行为实例。
|
||||
/// </summary>
|
||||
/// <returns>场景行为对象,包含场景的具体实现逻辑。</returns>
|
||||
ISceneBehavior GetScene();
|
||||
}
|
||||
20
GFramework.Game.Abstractions/scene/ISceneEnterParam.cs
Normal file
20
GFramework.Game.Abstractions/scene/ISceneEnterParam.cs
Normal file
@ -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.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 场景进入参数接口
|
||||
/// 该接口用于定义场景跳转时传递的参数数据结构
|
||||
/// </summary>
|
||||
public interface ISceneEnterParam;
|
||||
30
GFramework.Game.Abstractions/scene/ISceneFactory.cs
Normal file
30
GFramework.Game.Abstractions/scene/ISceneFactory.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
using GFramework.Core.Abstractions.utility;
|
||||
|
||||
namespace GFramework.Game.Abstractions.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 场景工厂接口,继承自上下文工具接口。
|
||||
/// 负责根据场景键值创建对应的场景行为实例,是场景管理系统的核心工厂模式实现。
|
||||
/// </summary>
|
||||
public interface ISceneFactory : IContextUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据指定的场景键值创建场景行为实例。
|
||||
/// </summary>
|
||||
/// <param name="sceneKy">场景的唯一标识符键值。</param>
|
||||
/// <returns>创建的场景行为对象,如果无法创建则返回null。</returns>
|
||||
ISceneBehavior Create(string sceneKy);
|
||||
}
|
||||
@ -14,18 +14,74 @@
|
||||
namespace GFramework.Game.Abstractions.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 定义场景根接口,用于管理场景的加载和卸载操作。
|
||||
/// 场景根接口,定义了场景管理系统的核心功能。
|
||||
/// 负责管理场景的生命周期、场景栈操作以及场景间的切换控制。
|
||||
/// </summary>
|
||||
public interface ISceneRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// 替换当前场景为指定键对应的场景。
|
||||
/// 获取当前活动的场景行为对象。
|
||||
/// 返回null表示当前没有活动场景。
|
||||
/// </summary>
|
||||
/// <param name="key">场景的唯一标识符,用于定位要加载的场景。</param>
|
||||
void Replace(string key);
|
||||
ISceneBehavior? Current { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 卸载当前场景。
|
||||
/// 获取所有已加载场景的行为对象列表。
|
||||
/// 列表采用栈式结构,索引0为栈底场景,最后一个元素为当前活动场景。
|
||||
/// </summary>
|
||||
void Unload();
|
||||
IReadOnlyList<ISceneBehavior> Stack { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取场景系统是否正在进行切换操作。
|
||||
/// true表示正在执行场景加载、卸载或切换,false表示系统空闲。
|
||||
/// </summary>
|
||||
bool IsTransitioning { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步替换当前场景,清空整个场景栈并加载新场景。
|
||||
/// 此操作会卸载所有现有场景,然后加载指定的新场景。
|
||||
/// </summary>
|
||||
/// <param name="key">要加载的场景唯一标识符。</param>
|
||||
/// <param name="param">可选的场景进入参数,用于传递初始化数据。</param>
|
||||
/// <returns>表示替换操作完成的ValueTask。</returns>
|
||||
ValueTask ReplaceAsync(string key, ISceneEnterParam? param = null);
|
||||
|
||||
/// <summary>
|
||||
/// 异步压入新场景到场景栈顶部。
|
||||
/// 当前场景会被暂停,新场景成为活动场景。
|
||||
/// </summary>
|
||||
/// <param name="key">要加载的场景唯一标识符。</param>
|
||||
/// <param name="param">可选的场景进入参数,用于传递初始化数据。</param>
|
||||
/// <returns>表示压入操作完成的ValueTask。</returns>
|
||||
ValueTask PushAsync(string key, ISceneEnterParam? param = null);
|
||||
|
||||
/// <summary>
|
||||
/// 异步弹出当前场景并恢复下一个场景。
|
||||
/// 当前场景会被卸载,栈中的下一个场景变为活动场景。
|
||||
/// </summary>
|
||||
/// <returns>表示弹出操作完成的ValueTask。</returns>
|
||||
ValueTask PopAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步清空所有已加载的场景。
|
||||
/// 卸载场景栈中的所有场景,使系统回到无场景状态。
|
||||
/// </summary>
|
||||
/// <returns>表示清空操作完成的ValueTask。</returns>
|
||||
ValueTask ClearAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载指定场景并返回场景行为实例。
|
||||
/// 此方法仅加载场景资源但不激活场景,通常用于预加载或后台加载场景。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">要加载的场景唯一标识符。</param>
|
||||
/// <returns>表示加载操作完成的ValueTask,包含加载成功的场景行为对象。</returns>
|
||||
ValueTask<ISceneBehavior> LoadAsync(string sceneKey);
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载指定的场景行为实例。
|
||||
/// 释放场景占用的资源并从系统中移除该场景实例。
|
||||
/// </summary>
|
||||
/// <param name="scene">要卸载的场景行为实例。</param>
|
||||
/// <returns>表示卸载操作完成的ValueTask。</returns>
|
||||
ValueTask UnloadAsync(ISceneBehavior scene);
|
||||
}
|
||||
@ -16,30 +16,82 @@ using GFramework.Core.Abstractions.system;
|
||||
namespace GFramework.Game.Abstractions.scene;
|
||||
|
||||
/// <summary>
|
||||
/// 定义场景路由接口,用于管理场景的切换、卸载以及根节点绑定。
|
||||
/// 场景路由接口,继承自系统接口。
|
||||
/// 负责管理场景的导航、切换、生命周期控制以及与场景根节点的绑定操作。
|
||||
/// 提供完整的场景栈管理和路由功能。
|
||||
/// </summary>
|
||||
public interface ISceneRouter : ISystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前场景的唯一标识符(键)。
|
||||
/// 获取当前活动的场景行为对象。
|
||||
/// 返回null表示当前没有活动场景。
|
||||
/// </summary>
|
||||
ISceneBehavior? Current { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前活动场景的唯一标识键值。
|
||||
/// 返回null表示当前没有活动场景。
|
||||
/// </summary>
|
||||
/// <value>当前场景的键,如果未加载任何场景则返回 null。</value>
|
||||
string? CurrentKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 替换当前场景为指定键对应的场景。
|
||||
/// 获取场景行为对象的只读列表,表示当前的场景栈结构。
|
||||
/// 列表中第一个元素为栈底场景,最后一个元素为当前活动场景。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">目标场景的唯一标识符(键)。</param>
|
||||
void Replace(string sceneKey);
|
||||
IReadOnlyList<ISceneBehavior> Stack { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 卸载当前场景。
|
||||
/// 获取场景路由器是否正在进行场景切换操作。
|
||||
/// true表示正在执行场景加载、卸载或切换,false表示系统空闲。
|
||||
/// </summary>
|
||||
void Unload();
|
||||
bool IsTransitioning { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 将指定的场景根节点与当前路由进行绑定。
|
||||
/// 绑定场景根节点,建立路由与场景管理器的连接。
|
||||
/// </summary>
|
||||
/// <param name="root">需要绑定的场景根节点。</param>
|
||||
/// <param name="root">要绑定的场景根节点实例。</param>
|
||||
void BindRoot(ISceneRoot root);
|
||||
|
||||
/// <summary>
|
||||
/// 异步替换当前所有场景,清空整个场景栈并加载新的场景。
|
||||
/// 此操作会卸载所有现有场景,然后加载指定的新场景。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">要加载的场景唯一标识符。</param>
|
||||
/// <param name="param">可选的场景进入参数,用于传递初始化数据。</param>
|
||||
/// <returns>表示替换操作完成的ValueTask。</returns>
|
||||
ValueTask ReplaceAsync(
|
||||
string sceneKey,
|
||||
ISceneEnterParam? param = null);
|
||||
|
||||
/// <summary>
|
||||
/// 异步压入新场景到场景栈顶部。
|
||||
/// 当前场景会被暂停,新场景成为活动场景。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">要加载的场景唯一标识符。</param>
|
||||
/// <param name="param">可选的场景进入参数,用于传递初始化数据。</param>
|
||||
/// <returns>表示压入操作完成的ValueTask。</returns>
|
||||
ValueTask PushAsync(
|
||||
string sceneKey,
|
||||
ISceneEnterParam? param = null);
|
||||
|
||||
/// <summary>
|
||||
/// 异步弹出当前场景并恢复栈中的下一个场景。
|
||||
/// 当前场景会被卸载,栈中的下一个场景变为活动场景。
|
||||
/// </summary>
|
||||
/// <returns>表示弹出操作完成的ValueTask。</returns>
|
||||
ValueTask PopAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步清空所有已加载的场景。
|
||||
/// 卸载场景栈中的所有场景,使系统回到无场景状态。
|
||||
/// </summary>
|
||||
/// <returns>表示清空操作完成的ValueTask。</returns>
|
||||
ValueTask ClearAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定场景是否存在于当前场景栈中。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">要检查的场景唯一标识符。</param>
|
||||
/// <returns>true表示场景在栈中存在,false表示不存在。</returns>
|
||||
bool Contains(string sceneKey);
|
||||
}
|
||||
@ -16,7 +16,7 @@ public interface IUiTransitionHandler
|
||||
/// 处理器适用的阶段,默认为所有阶段
|
||||
/// 可以使用Flags枚举指定多个阶段
|
||||
/// </summary>
|
||||
UITransitionPhases Phases { get; }
|
||||
UiTransitionPhases Phases { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否应该处理当前事件
|
||||
@ -25,7 +25,7 @@ public interface IUiTransitionHandler
|
||||
/// <param name="event">UI切换事件</param>
|
||||
/// <param name="phases">当前阶段</param>
|
||||
/// <returns>是否处理</returns>
|
||||
bool ShouldHandle(UiTransitionEvent @event, UITransitionPhases phases);
|
||||
bool ShouldHandle(UiTransitionEvent @event, UiTransitionPhases phases);
|
||||
|
||||
/// <summary>
|
||||
/// 处理UI切换事件
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026 GeWuYou
|
||||
// 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
|
||||
@ -11,6 +11,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using GFramework.Core.Abstractions.logging;
|
||||
using GFramework.Core.logging;
|
||||
using GFramework.Core.system;
|
||||
using GFramework.Game.Abstractions.scene;
|
||||
|
||||
@ -23,70 +25,174 @@ namespace GFramework.Game.scene;
|
||||
public abstract class SceneRouterBase
|
||||
: AbstractSystem, ISceneRouter
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前绑定的场景根节点。
|
||||
/// </summary>
|
||||
private static readonly ILogger Log =
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(SceneRouterBase));
|
||||
|
||||
private readonly Stack<ISceneBehavior> _stack = new();
|
||||
private readonly SemaphoreSlim _transitionLock = new(1, 1);
|
||||
|
||||
protected ISceneRoot? Root;
|
||||
|
||||
/// <summary>
|
||||
/// 当前激活场景的键值。
|
||||
/// </summary>
|
||||
public string? CurrentKey { get; private set; }
|
||||
public ISceneBehavior? Current => _stack.Count > 0 ? _stack.Peek() : null;
|
||||
|
||||
public string? CurrentKey => Current?.Key;
|
||||
|
||||
public IReadOnlyList<ISceneBehavior> Stack =>
|
||||
_stack.Reverse().ToList();
|
||||
|
||||
public bool IsTransitioning { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定场景根节点。
|
||||
/// </summary>
|
||||
/// <param name="root">要绑定的场景根节点。</param>
|
||||
public void BindRoot(ISceneRoot root)
|
||||
{
|
||||
Root = root;
|
||||
Log.Debug("Bind Scene Root: {0}", root.GetType().Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 替换当前场景为指定键值的新场景。
|
||||
/// 在替换前后会调用相应的虚方法以支持扩展逻辑。
|
||||
/// </summary>
|
||||
/// <param name="sceneKey">目标场景的键值。</param>
|
||||
public void Replace(string sceneKey)
|
||||
#region Replace
|
||||
|
||||
public async ValueTask ReplaceAsync(
|
||||
string sceneKey,
|
||||
ISceneEnterParam? param = null)
|
||||
{
|
||||
// 调用替换前的钩子方法
|
||||
OnBeforeReplace(sceneKey);
|
||||
await _transitionLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
IsTransitioning = true;
|
||||
|
||||
// 执行场景替换操作
|
||||
Root!.Replace(sceneKey);
|
||||
Log.Debug("Replace Scene: {0}", sceneKey);
|
||||
|
||||
// 更新当前场景键值
|
||||
CurrentKey = sceneKey;
|
||||
|
||||
// 调用替换后的钩子方法
|
||||
OnAfterReplace(sceneKey);
|
||||
await ClearInternalAsync();
|
||||
await PushInternalAsync(sceneKey, param);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTransitioning = false;
|
||||
_transitionLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载当前场景,并将当前场景键值置为空。
|
||||
/// </summary>
|
||||
public void Unload()
|
||||
#endregion
|
||||
|
||||
#region Query
|
||||
|
||||
public bool Contains(string sceneKey)
|
||||
{
|
||||
// 执行场景卸载操作
|
||||
Root!.Unload();
|
||||
|
||||
// 清空当前场景键值
|
||||
CurrentKey = null;
|
||||
return _stack.Any(s => s.Key == sceneKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 场景替换前的虚方法,可在子类中重写以实现自定义逻辑。
|
||||
/// </summary>
|
||||
/// <param name="key">即将被替换的场景键值。</param>
|
||||
protected virtual void OnBeforeReplace(string key)
|
||||
#endregion
|
||||
|
||||
#region Push
|
||||
|
||||
public async ValueTask PushAsync(
|
||||
string sceneKey,
|
||||
ISceneEnterParam? param = null)
|
||||
{
|
||||
await _transitionLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
IsTransitioning = true;
|
||||
await PushInternalAsync(sceneKey, param);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTransitioning = false;
|
||||
_transitionLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 场景替换后的虚方法,可在子类中重写以实现自定义逻辑。
|
||||
/// </summary>
|
||||
/// <param name="key">已替换的场景键值。</param>
|
||||
protected virtual void OnAfterReplace(string key)
|
||||
private async ValueTask PushInternalAsync(
|
||||
string sceneKey,
|
||||
ISceneEnterParam? param)
|
||||
{
|
||||
if (Contains(sceneKey))
|
||||
{
|
||||
Log.Warn("Scene already in stack: {0}", sceneKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var scene = await Root!.LoadAsync(sceneKey);
|
||||
|
||||
if (_stack.Count > 0)
|
||||
{
|
||||
var current = _stack.Peek();
|
||||
await current.OnPauseAsync();
|
||||
}
|
||||
|
||||
_stack.Push(scene);
|
||||
|
||||
await scene.OnEnterAsync(param);
|
||||
await scene.OnShowAsync();
|
||||
|
||||
Log.Debug("Push Scene: {0}, stackCount={1}",
|
||||
sceneKey, _stack.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Pop
|
||||
|
||||
public async ValueTask PopAsync()
|
||||
{
|
||||
await _transitionLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
IsTransitioning = true;
|
||||
await PopInternalAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTransitioning = false;
|
||||
_transitionLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask PopInternalAsync()
|
||||
{
|
||||
if (_stack.Count == 0)
|
||||
return;
|
||||
|
||||
var top = _stack.Pop();
|
||||
|
||||
await top.OnExitAsync();
|
||||
await Root!.UnloadAsync(top);
|
||||
|
||||
if (_stack.Count > 0)
|
||||
{
|
||||
var next = _stack.Peek();
|
||||
await next.OnResumeAsync();
|
||||
await next.OnShowAsync();
|
||||
}
|
||||
|
||||
Log.Debug("Pop Scene, stackCount={0}", _stack.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clear
|
||||
|
||||
public async ValueTask ClearAsync()
|
||||
{
|
||||
await _transitionLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
IsTransitioning = true;
|
||||
await ClearInternalAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTransitioning = false;
|
||||
_transitionLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask ClearInternalAsync()
|
||||
{
|
||||
while (_stack.Count > 0)
|
||||
{
|
||||
await PopInternalAsync();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -12,7 +12,7 @@ namespace GFramework.Game.ui;
|
||||
/// </summary>
|
||||
public abstract class UiRouterBase : AbstractSystem, IUiRouter
|
||||
{
|
||||
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger("UiRouterBase");
|
||||
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger(nameof(UiRouterBase));
|
||||
|
||||
/// <summary>
|
||||
/// 路由守卫列表
|
||||
@ -519,7 +519,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
|
||||
private void BeforeChange(UiTransitionEvent @event)
|
||||
{
|
||||
Log.Debug("BeforeChange phases started: {0}", @event.TransitionType);
|
||||
_pipeline.ExecuteAsync(@event, UITransitionPhases.BeforeChange).GetAwaiter().GetResult();
|
||||
_pipeline.ExecuteAsync(@event, UiTransitionPhases.BeforeChange).GetAwaiter().GetResult();
|
||||
Log.Debug("BeforeChange phases completed: {0}", @event.TransitionType);
|
||||
}
|
||||
|
||||
@ -530,7 +530,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
|
||||
{
|
||||
try
|
||||
{
|
||||
await _pipeline.ExecuteAsync(@event, UITransitionPhases.AfterChange).ConfigureAwait(false);
|
||||
await _pipeline.ExecuteAsync(@event, UiTransitionPhases.AfterChange).ConfigureAwait(false);
|
||||
Log.Debug("AfterChange phases completed: {0}", @event.TransitionType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@ -62,7 +62,7 @@ public class UiTransitionPipeline
|
||||
/// <returns>异步任务</returns>
|
||||
public async Task ExecuteAsync(
|
||||
UiTransitionEvent @event,
|
||||
UITransitionPhases phases,
|
||||
UiTransitionPhases phases,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
@ -102,7 +102,7 @@ public class UiTransitionPipeline
|
||||
|
||||
private List<IUiTransitionHandler> FilterAndSortHandlers(
|
||||
UiTransitionEvent @event,
|
||||
UITransitionPhases phases)
|
||||
UiTransitionPhases phases)
|
||||
{
|
||||
return _handlers
|
||||
.Where(h => h.Phases.HasFlag(phases) && h.ShouldHandle(@event, phases))
|
||||
|
||||
@ -13,7 +13,7 @@ public sealed class LoggingTransitionHandler : UiTransitionHandlerBase
|
||||
/// <summary>
|
||||
/// 日志记录器实例,用于记录UI切换相关信息
|
||||
/// </summary>
|
||||
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger("LoggingTransitionHandler");
|
||||
private static readonly ILogger Log = LoggerFactoryResolver.Provider.CreateLogger(nameof(LoggingTransitionHandler));
|
||||
|
||||
/// <summary>
|
||||
/// 获取处理器优先级,数值越大优先级越高
|
||||
@ -23,7 +23,7 @@ public sealed class LoggingTransitionHandler : UiTransitionHandlerBase
|
||||
/// <summary>
|
||||
/// 获取处理器处理的UI切换阶段,处理所有阶段
|
||||
/// </summary>
|
||||
public override UITransitionPhases Phases => UITransitionPhases.All;
|
||||
public override UiTransitionPhases Phases => UiTransitionPhases.All;
|
||||
|
||||
/// <summary>
|
||||
/// 处理UI切换事件的异步方法
|
||||
|
||||
@ -11,7 +11,7 @@ public abstract class UiTransitionHandlerBase : IUiTransitionHandler
|
||||
/// <summary>
|
||||
/// 处理器适用的阶段,默认为所有阶段
|
||||
/// </summary>
|
||||
public virtual UITransitionPhases Phases => UITransitionPhases.All;
|
||||
public virtual UiTransitionPhases Phases => UiTransitionPhases.All;
|
||||
|
||||
/// <summary>
|
||||
/// 优先级,需要在子类中实现
|
||||
@ -21,7 +21,7 @@ public abstract class UiTransitionHandlerBase : IUiTransitionHandler
|
||||
/// <summary>
|
||||
/// 判断是否应该处理当前事件,默认返回true
|
||||
/// </summary>
|
||||
public virtual bool ShouldHandle(UiTransitionEvent @event, UITransitionPhases phases)
|
||||
public virtual bool ShouldHandle(UiTransitionEvent @event, UiTransitionPhases phases)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using GFramework.Game.Abstractions.ui;
|
||||
using GFramework.Game.Abstractions.asset;
|
||||
using Godot;
|
||||
|
||||
namespace GFramework.Godot.scene;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using GFramework.Game.Abstractions.ui;
|
||||
using GFramework.Game.Abstractions.asset;
|
||||
using Godot;
|
||||
|
||||
namespace GFramework.Godot.ui;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user