import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager"; import { UITransitionHelper } from "../utils/UITransitionHelper"; import GameRootUI from "../../Main/Common/GameRootUI"; /** * 页面过渡动画类型枚举 */ export enum PageTransitionType { NONE = "none", SLIDE_LEFT = "slide_left", SLIDE_RIGHT = "slide_right", } /** * 页面过渡动画配置接口 */ export interface PageTransitionConfig { incomingTransition: PageTransitionType; outgoingTransition: PageTransitionType; duration?: number; simultaneous?: boolean; } /** * 导航管理器 * * 负责管理游戏中的页面导航和路由,将导航逻辑从业务逻辑中分离出来 * * @author AI Chat System * @version 1.0.0 */ export class NavigationManager { private static _instance: NavigationManager; /** * 获取NavigationManager的单例实例 * * @returns {NavigationManager} 导航管理器实例 * @static */ public static get Instance(): NavigationManager { if (!this._instance) { this._instance = new NavigationManager(); } return this._instance; } private constructor() {} /** * 通用页面导航方法,支持过渡动画 * * @param {string} targetPanel - 目标面板名称 * @param {any} navigationData - 导航数据 * @param {PageTransitionConfig} transitionConfig - 过渡动画配置 * @param {any} currentPanel - 当前面板实例(可选) * @param {Function} onComplete - 完成回调(可选) * * @example * ```typescript * NavigationManager.Instance.navigateWithTransition( * "ChatPanel", * { roleId: 10001 }, * { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT }, * currentPanel * ); * ``` */ public navigateWithTransition( targetPanel: string, navigationData: any, transitionConfig: PageTransitionConfig, currentPanel?: any, onComplete?: Function ): void { if (!targetPanel) { console.warn("NavigationManager: Target panel name is required"); return; } console.log( `Navigating to ${targetPanel} with transition:`, transitionConfig ); //const correntPos = currentPanel.node.position; const duration = transitionConfig.duration || 0.1; const useTransition = transitionConfig.incomingTransition !== PageTransitionType.NONE || transitionConfig.outgoingTransition !== PageTransitionType.NONE; if (!useTransition) { ViewManager.I.openBundlesView(targetPanel, navigationData, onComplete); if ( currentPanel && currentPanel.onClose && typeof currentPanel.onClose === "function" ) { currentPanel.onClose(); //currentPanel.node.position = correntPos; } return; } ViewManager.I.openBundlesView(targetPanel, navigationData, (targetNode) => { this._executeTransition( targetNode, currentPanel, transitionConfig, duration, onComplete ); }); } /** * 执行页面过渡动画的私有方法 * * @private * @param {any} targetNode - 目标节点 * @param {any} currentPanel - 当前面板 * @param {PageTransitionConfig} config - 动画配置 * @param {number} duration - 动画时长 * @param {Function} onComplete - 完成回调 */ private _executeTransition( targetNode: any, currentPanel: any, config: PageTransitionConfig, duration: number, onComplete?: Function ): void { const executeIncomingAnimation = (callback?: Function) => { if ( config.incomingTransition === PageTransitionType.NONE || !targetNode ) { callback && callback(); return; } switch (config.incomingTransition) { case PageTransitionType.SLIDE_RIGHT: UITransitionHelper.slideInFromRight(targetNode, duration, callback); break; case PageTransitionType.SLIDE_LEFT: UITransitionHelper.slideInFromLeft(targetNode, duration, callback); break; default: callback && callback(); break; } }; const executeOutgoingAnimation = (callback?: Function) => { if ( config.outgoingTransition === PageTransitionType.NONE || !currentPanel || !currentPanel.node || !currentPanel.node.isValid ) { callback && callback(); return; } switch (config.outgoingTransition) { case PageTransitionType.SLIDE_LEFT: UITransitionHelper.slideOutToLeft( currentPanel.node, duration, callback ); break; case PageTransitionType.SLIDE_RIGHT: UITransitionHelper.slideOutToRight( currentPanel.node, duration, callback ); break; default: callback && callback(); break; } }; const closeCurrentPanel = () => { if ( currentPanel && currentPanel.onClose && typeof currentPanel.onClose === "function" ) { if (currentPanel.node.name !== "ThemePanel") currentPanel.onClose(); } onComplete && onComplete(); }; if (config.simultaneous) { let completedAnimations = 0; const animationComplete = () => { completedAnimations++; if (completedAnimations >= 2) { closeCurrentPanel(); } }; executeIncomingAnimation(animationComplete); executeOutgoingAnimation(animationComplete); } else { executeOutgoingAnimation(() => { executeIncomingAnimation(closeCurrentPanel); }); } } /** * 进入角色列表页面 * * @param {number} themeId - 主题ID,用于筛选角色 * * @example * ```typescript * NavigationManager.Instance.navigateToGirlList(1); * ``` */ public navigateToGirlList(themeId: number): void; /** * 进入角色列表页面(带过渡动画) * * @param {number} themeId - 主题ID,用于筛选角色 * @param {PageTransitionConfig} transitionConfig - 过渡动画配置 * @param {any} currentPanel - 当前面板实例(可选) * * @example * ```typescript * NavigationManager.Instance.navigateToGirlList(1, * { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.FADE }, * this * ); * ``` */ public navigateToGirlList( themeId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void; public navigateToGirlList( themeId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void { if (themeId == null || themeId < 0) { console.warn("Invalid theme ID for girl list navigation:", themeId); return; } console.log(`Navigating to girl list with theme ID: ${themeId}`); if (transitionConfig) { const navigationData = { category: themeId, withTransition: true, }; this.navigateWithTransition( "GirlListPanel", themeId, transitionConfig, currentPanel, () => { GameRootUI.I.hideDefaultView(); } ); } else { ViewManager.I.openBundlesView("GirlListPanel", themeId); } } /** * 进入聊天页面 * * @param {number} roleId - 角色ID * * @example * ```typescript * NavigationManager.Instance.navigateToChat(10001); * ``` */ public navigateToChat(roleId: number): void; /** * 进入聊天页面(带过渡动画) * * @param {number} roleId - 角色ID * @param {PageTransitionConfig} transitionConfig - 过渡动画配置 * @param {any} currentPanel - 当前面板实例(可选) * * @example * ```typescript * NavigationManager.Instance.navigateToChat(10001, * { incomingTransition: PageTransitionType.FADE, outgoingTransition: PageTransitionType.SLIDE_LEFT }, * this * ); * ``` */ public navigateToChat( roleId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void; public navigateToChat( roleId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void { if (roleId == null || roleId <= 0) { console.warn("Invalid role ID for chat navigation:", roleId); return; } GameRootUI.I.hideDefaultView(); console.log(`Navigating to chat with role ID: ${roleId}`); if (transitionConfig) { this.navigateWithTransition( "ChatPanel", roleId, transitionConfig, currentPanel ); } else { ViewManager.I.openBundlesView("ChatPanel", roleId); } } /** * 带过渡动画进入聊天页面 * 从GirlDetailPanel平滑过渡到ChatPanel * * @param {string} categoryId - 类别ID * @param {number} roleId - 角色ID * @param {any} currentPanel - 当前面板实例(GirlDetailPanel) * * @example * ```typescript * NavigationManager.Instance.navigateToChatWithTransition("1", 10001, this); * ``` */ public navigateToChatWithTransition( categoryId: string, roleId: number, currentPanel?: any ): void { if (roleId == null || roleId <= 0) { console.warn( "Invalid role ID for chat navigation with transition:", roleId ); return; } const navigationData = { categoryId: categoryId, roleId: roleId, }; const transitionConfig: PageTransitionConfig = { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT, duration: 0.3, simultaneous: true, }; this.navigateWithTransition( "ChatPanel", navigationData, transitionConfig, currentPanel ); } /** * 进入角色详情页面 * * @param {number} roleId - 角色ID * * @example * ```typescript * NavigationManager.Instance.navigateToGirlDetail(10001); * ``` */ public navigateToGirlDetail(roleId: number): void; /** * 进入角色详情页面(带过渡动画) * * @param {number} roleId - 角色ID * @param {PageTransitionConfig} transitionConfig - 过渡动画配置 * @param {any} currentPanel - 当前面板实例(可选) * * @example * ```typescript * NavigationManager.Instance.navigateToGirlDetail(10001, * { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT }, * this * ); * ``` */ public navigateToGirlDetail( roleId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void; public navigateToGirlDetail( roleId: number, transitionConfig?: PageTransitionConfig, currentPanel?: any ): void { if (roleId == null || roleId <= 0) { console.warn("Invalid role ID for detail navigation:", roleId); return; } console.log(`Navigating to girl detail with role ID: ${roleId}`); if (transitionConfig) { this.navigateWithTransition( "GirlDetailPanel", roleId, transitionConfig, currentPanel ); } else { ViewManager.I.openBundlesView("GirlDetailPanel", roleId); } } /** * 返回主界面 * * @example * ```typescript * NavigationManager.Instance.navigateToMainMenu(); * ``` */ public navigateToMainMenu(): void { console.log("Navigating to main menu"); // TODO: 实现返回主界面的逻辑 // ViewManager.I.openBundlesView("MainMenu"); } /** * 检查是否可以导航到指定页面 * * @param {string} pageName - 页面名称 * @returns {boolean} 是否可以导航 */ public canNavigateTo(pageName: string): boolean { const allowedPages = ["GirlListPanel", "ChatPanel", "GirlDetailPanel"]; return allowedPages.indexOf(pageName) >= 0; } /** * 获取当前页面的导航历史(预留功能) * * @returns {string[]} 导航历史数组 */ public getNavigationHistory(): string[] { // TODO: 实现导航历史记录功能 console.log("Navigation history feature not implemented yet"); return []; } /** * 返回上一页(预留功能) */ public goBack(): void { // TODO: 实现返回上一页功能 console.log("Go back feature not implemented yet"); } /** * 获取预设的过渡动画配置 */ public static getTransitionPresets() { return { SLIDE_LEFT_TO_RIGHT: { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT, duration: 0.1, simultaneous: true, } as PageTransitionConfig, SLIDE_RIGHT_TO_LEFT: { incomingTransition: PageTransitionType.SLIDE_LEFT, outgoingTransition: PageTransitionType.SLIDE_RIGHT, duration: 0.1, simultaneous: true, } as PageTransitionConfig, SLIDE_OVER: { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.NONE, duration: 0.1, simultaneous: true, } as PageTransitionConfig, SLIDE_UNDER: { incomingTransition: PageTransitionType.NONE, outgoingTransition: PageTransitionType.SLIDE_LEFT, duration: 0.1, simultaneous: true, } as PageTransitionConfig, }; } }