调整布局、新增导航栏,调整页面跳转逻辑
This commit is contained in:
@@ -39,11 +39,13 @@ assets/
|
|||||||
## Key Components
|
## Key Components
|
||||||
|
|
||||||
### AI Chat System
|
### AI Chat System
|
||||||
|
|
||||||
- **ChatAIService.ts**: Handles Google Gemini API integration for chat functionality
|
- **ChatAIService.ts**: Handles Google Gemini API integration for chat functionality
|
||||||
- **ChatPanel.ts**: Main chat interface implementation
|
- **ChatPanel.ts**: Main chat interface implementation
|
||||||
- **index.ts**: Contains system prompts and character definitions
|
- **index.ts**: Contains system prompts and character definitions
|
||||||
|
|
||||||
### Platform SDKs
|
### Platform SDKs
|
||||||
|
|
||||||
- **SDKManager.ts**: Manages platform-specific SDK initialization
|
- **SDKManager.ts**: Manages platform-specific SDK initialization
|
||||||
- **wxSDK.ts**: WeChat Mini Game SDK integration
|
- **wxSDK.ts**: WeChat Mini Game SDK integration
|
||||||
- **bdSDK.ts**: Baidu SDK integration
|
- **bdSDK.ts**: Baidu SDK integration
|
||||||
@@ -51,6 +53,7 @@ assets/
|
|||||||
- **webSDK.ts**: Web platform SDK
|
- **webSDK.ts**: Web platform SDK
|
||||||
|
|
||||||
### Game Flow
|
### Game Flow
|
||||||
|
|
||||||
- **GameEntry.ts**: Game initialization and configuration
|
- **GameEntry.ts**: Game initialization and configuration
|
||||||
- **MainScene.ts**: Main menu scene
|
- **MainScene.ts**: Main menu scene
|
||||||
- **GameScene.ts**: Core game scene
|
- **GameScene.ts**: Core game scene
|
||||||
@@ -61,30 +64,37 @@ assets/
|
|||||||
Since this is a Cocos Creator project, development is primarily done through the Cocos Creator IDE. Common tasks:
|
Since this is a Cocos Creator project, development is primarily done through the Cocos Creator IDE. Common tasks:
|
||||||
|
|
||||||
### Build & Run
|
### Build & Run
|
||||||
|
|
||||||
- Open project in Cocos Creator 3.8.4
|
- Open project in Cocos Creator 3.8.4
|
||||||
- Use Creator's built-in preview: Menu → Project → Preview
|
- Use Creator's built-in preview: Menu → Project → Preview
|
||||||
- Build for platforms: Menu → Project → Build
|
- Build for platforms: Menu → Project → Build
|
||||||
|
|
||||||
### TypeScript Compilation
|
### TypeScript Compilation
|
||||||
|
|
||||||
TypeScript compilation is handled automatically by Cocos Creator. Manual compilation isn't typically needed.
|
TypeScript compilation is handled automatically by Cocos Creator. Manual compilation isn't typically needed.
|
||||||
|
|
||||||
## Important Considerations
|
## Important Considerations
|
||||||
|
|
||||||
### API Keys
|
### API Keys
|
||||||
|
|
||||||
The project contains API keys in the code (Google Gemini API). These should be moved to environment variables or a secure configuration file.
|
The project contains API keys in the code (Google Gemini API). These should be moved to environment variables or a secure configuration file.
|
||||||
|
|
||||||
### Character System
|
### Character System
|
||||||
|
|
||||||
The game uses configurable character profiles defined in `index.ts` with different personality settings (Role_1, Role_2, Role_3).
|
The game uses configurable character profiles defined in `index.ts` with different personality settings (Role_1, Role_2, Role_3).
|
||||||
|
|
||||||
### Multi-Platform Support
|
### Multi-Platform Support
|
||||||
|
|
||||||
The codebase includes platform-specific code branches. When modifying core functionality, ensure compatibility across all supported platforms (Web, WeChat, Baidu, Kuaishou).
|
The codebase includes platform-specific code branches. When modifying core functionality, ensure compatibility across all supported platforms (Web, WeChat, Baidu, Kuaishou).
|
||||||
|
|
||||||
### Asset Management
|
### Asset Management
|
||||||
|
|
||||||
- Assets are organized in bundles for dynamic loading
|
- Assets are organized in bundles for dynamic loading
|
||||||
- Resource management is handled through ResManager
|
- Resource management is handled through ResManager
|
||||||
- Audio assets are managed separately through AudioManager
|
- Audio assets are managed separately through AudioManager
|
||||||
|
|
||||||
### UI System
|
### UI System
|
||||||
|
|
||||||
- Uses Cocos Creator's UI system with custom components
|
- Uses Cocos Creator's UI system with custom components
|
||||||
- Base view class: `li_BaseView.ts`
|
- Base view class: `li_BaseView.ts`
|
||||||
- View navigation managed by ViewManager
|
- View navigation managed by ViewManager
|
||||||
@@ -95,3 +105,7 @@ The codebase includes platform-specific code branches. When modifying core funct
|
|||||||
- Component-based architecture following Cocos Creator patterns
|
- Component-based architecture following Cocos Creator patterns
|
||||||
- Singleton pattern for managers (e.g., `SDKManager.I`, `PlayerDataManager.I`)
|
- Singleton pattern for managers (e.g., `SDKManager.I`, `PlayerDataManager.I`)
|
||||||
- Event system using `li_EventManager` for decoupled communication
|
- Event system using `li_EventManager` for decoupled communication
|
||||||
|
|
||||||
|
## Plan Description
|
||||||
|
|
||||||
|
- when user using plan mode create a plan, describe this plan in chinese.
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export default class GameRootUI extends Component {
|
|||||||
let viewSP = res.getComponent(res.name);
|
let viewSP = res.getComponent(res.name);
|
||||||
viewSP && viewSP.openUIData && viewSP.openUIData(null);
|
viewSP && viewSP.openUIData && viewSP.openUIData(null);
|
||||||
|
|
||||||
this.AddUIToLayer(res, CommonConfig.UILayerGroup.Layer_ui1);
|
this.AddUIToLayer(res, CommonConfig.UILayerGroup.Layer_navigationbar);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,263 +1,257 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 公共配置文件
|
* 公共配置文件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const G_GlobalNode: string = '__GLobal_Node';
|
export const G_GlobalNode: string = "__GLobal_Node";
|
||||||
|
|
||||||
export namespace CommonConfig {
|
export namespace CommonConfig {
|
||||||
//本地保存
|
//本地保存
|
||||||
export enum StorageConfigUtil {
|
export enum StorageConfigUtil {
|
||||||
BaseData = 'li_' + 1000, // 登录相关
|
BaseData = "li_" + 1000, // 登录相关
|
||||||
Channel = 2000, //渠道相关
|
Channel = 2000, //渠道相关
|
||||||
}
|
}
|
||||||
export enum StorageConfig {
|
export enum StorageConfig {
|
||||||
SETTING_SHAKEON = StorageConfigUtil.BaseData + 1,
|
SETTING_SHAKEON = StorageConfigUtil.BaseData + 1,
|
||||||
SETTING_MUSIC = StorageConfigUtil.BaseData + 2,
|
SETTING_MUSIC = StorageConfigUtil.BaseData + 2,
|
||||||
SETTING_SOUND = StorageConfigUtil.BaseData + 3,
|
SETTING_SOUND = StorageConfigUtil.BaseData + 3,
|
||||||
GAME_CITY = StorageConfigUtil.BaseData + 4, //所在省
|
GAME_CITY = StorageConfigUtil.BaseData + 4, //所在省
|
||||||
GAME_RANK_CITY = StorageConfigUtil.BaseData + 5, //省排行数据 AI
|
GAME_RANK_CITY = StorageConfigUtil.BaseData + 5, //省排行数据 AI
|
||||||
GAME_RANK_USER = StorageConfigUtil.BaseData + 6, //玩家排行数据 AI
|
GAME_RANK_USER = StorageConfigUtil.BaseData + 6, //玩家排行数据 AI
|
||||||
GAME_RANK_CDTIME = StorageConfigUtil.BaseData + 7, //上次排行数据刷新时间戳 AI
|
GAME_RANK_CDTIME = StorageConfigUtil.BaseData + 7, //上次排行数据刷新时间戳 AI
|
||||||
GAME_SCORE = StorageConfigUtil.BaseData + 8, //玩家积分
|
GAME_SCORE = StorageConfigUtil.BaseData + 8, //玩家积分
|
||||||
GAME_SKIN_ID = StorageConfigUtil.BaseData + 9, //当前选择的皮肤id
|
GAME_SKIN_ID = StorageConfigUtil.BaseData + 9, //当前选择的皮肤id
|
||||||
GAME_PASSLV = StorageConfigUtil.BaseData + 10, //已完成关卡
|
GAME_PASSLV = StorageConfigUtil.BaseData + 10, //已完成关卡
|
||||||
DAILYCHALLENGE_PASSLV = StorageConfigUtil.BaseData + 11, //已完成每日挑战关卡
|
DAILYCHALLENGE_PASSLV = StorageConfigUtil.BaseData + 11, //已完成每日挑战关卡
|
||||||
TOOL_KAIKONG = StorageConfigUtil.BaseData + 12, //开孔工具使用过
|
TOOL_KAIKONG = StorageConfigUtil.BaseData + 12, //开孔工具使用过
|
||||||
TOOL_RENYIZHI = StorageConfigUtil.BaseData + 13, //任意指工具使用过
|
TOOL_RENYIZHI = StorageConfigUtil.BaseData + 13, //任意指工具使用过
|
||||||
TOOL_RENYIGUAN = StorageConfigUtil.BaseData + 14, //任意罐工具使用过
|
TOOL_RENYIGUAN = StorageConfigUtil.BaseData + 14, //任意罐工具使用过
|
||||||
DD_REGISTTIME = StorageConfigUtil.BaseData + 15, //注册时间字符串
|
DD_REGISTTIME = StorageConfigUtil.BaseData + 15, //注册时间字符串
|
||||||
DD_LEVELOPER = StorageConfigUtil.BaseData + 16, //进入关卡且首次进度>0时(或第一次操作)
|
DD_LEVELOPER = StorageConfigUtil.BaseData + 16, //进入关卡且首次进度>0时(或第一次操作)
|
||||||
GUIDE_MAIN = StorageConfigUtil.BaseData + 17, //主界面引导是否完成
|
GUIDE_MAIN = StorageConfigUtil.BaseData + 17, //主界面引导是否完成
|
||||||
GUIDE_TALK = StorageConfigUtil.BaseData + 18, //聊天界面引导是否完成
|
GUIDE_TALK = StorageConfigUtil.BaseData + 18, //聊天界面引导是否完成
|
||||||
LANGUAGE_SETTING = StorageConfigUtil.BaseData + 19, //语言设置
|
LANGUAGE_SETTING = StorageConfigUtil.BaseData + 19, //语言设置
|
||||||
|
|
||||||
DOUYIN_SIDEBAR = StorageConfigUtil.Channel + 1, //抖音渠道侧边栏奖励是否领取
|
DOUYIN_SIDEBAR = StorageConfigUtil.Channel + 1, //抖音渠道侧边栏奖励是否领取
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//UI层级
|
||||||
//UI层级
|
export enum UILayerGroup {
|
||||||
export enum UILayerGroup {
|
Layer_ground = 0,
|
||||||
Layer_ground = 0,
|
Layer_ui1 = 1,
|
||||||
Layer_ui1 = 1,
|
Layer_ui2 = 2,
|
||||||
Layer_ui2 = 2,
|
Layer_dialog = 3,
|
||||||
Layer_dialog = 3,
|
Layer_tips = 4,
|
||||||
Layer_tips = 4,
|
Layer_top = 5,
|
||||||
Layer_top = 5,
|
Layer_navigationbar = 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**关卡配置信息 */
|
/**关卡配置信息 */
|
||||||
export interface I_LevelConfig {
|
export interface I_LevelConfig {
|
||||||
/**是关卡场景图资源的名称,注意关卡选择界面选中关卡后展示的场景图资源也是这个 */
|
/**是关卡场景图资源的名称,注意关卡选择界面选中关卡后展示的场景图资源也是这个 */
|
||||||
bgImage: string;
|
bgImage: string;
|
||||||
/**后续进入关卡后,关卡中需要播放的音乐资源名称 */
|
/**后续进入关卡后,关卡中需要播放的音乐资源名称 */
|
||||||
bgm: string;
|
bgm: string;
|
||||||
/**在关卡中,聊天历史信息展示里,角色使用的头像,圆形 80*80 */
|
/**在关卡中,聊天历史信息展示里,角色使用的头像,圆形 80*80 */
|
||||||
characterAvatar: string;
|
characterAvatar: string;
|
||||||
/**关卡中,提示信息界面里需要展示的角色性格文本 */
|
/**关卡中,提示信息界面里需要展示的角色性格文本 */
|
||||||
characterDisposition: string;
|
characterDisposition: string;
|
||||||
/**角色聊天切换的表情立绘,这个暂时先不处理,后面我们需要和你沟通下,资源改成英文名看你怎么匹配(Ai 返回的判断还是中文的) */
|
/**角色聊天切换的表情立绘,这个暂时先不处理,后面我们需要和你沟通下,资源改成英文名看你怎么匹配(Ai 返回的判断还是中文的) */
|
||||||
characterEmojiSet: string;
|
characterEmojiSet: string;
|
||||||
/**关卡中,提示信息界面,喜好话题部分需要展示的文本信息 */
|
/**关卡中,提示信息界面,喜好话题部分需要展示的文本信息 */
|
||||||
characterFavoriteTopic: string;
|
characterFavoriteTopic: string;
|
||||||
/**角色待机资源名称 */
|
/**角色待机资源名称 */
|
||||||
characterStandbyPortrait: string;
|
characterStandbyPortrait: string;
|
||||||
/**角色默认立绘资源名称 */
|
/**角色默认立绘资源名称 */
|
||||||
characterFullLengthPortrait: string;
|
characterFullLengthPortrait: string;
|
||||||
/**关卡提示信息界面里使用的角色半身胸像 */
|
/**关卡提示信息界面里使用的角色半身胸像 */
|
||||||
characterHalfLengthPortrait: string;
|
characterHalfLengthPortrait: string;
|
||||||
/**关卡提示信息界面里,厌恶话题的展示文本信息 */
|
/**关卡提示信息界面里,厌恶话题的展示文本信息 */
|
||||||
characterHateTopic: string;
|
characterHateTopic: string;
|
||||||
/**角色名称,注意在关卡选择界面还有关卡中的聊天窗,关卡提示信息界面这几个地方都涉及展示 */
|
/**角色名称,注意在关卡选择界面还有关卡中的聊天窗,关卡提示信息界面这几个地方都涉及展示 */
|
||||||
characterName: string;
|
characterName: string;
|
||||||
/**角色职业设定信息,关卡提示信息界面里的职业部分展示 */
|
/**角色职业设定信息,关卡提示信息界面里的职业部分展示 */
|
||||||
characterRole: string;
|
characterRole: string;
|
||||||
/**关卡选择界面里展示的关卡介绍文本信息 */
|
/**关卡选择界面里展示的关卡介绍文本信息 */
|
||||||
description: string;
|
description: string;
|
||||||
/**关卡中对话得到高分后,额外向玩家展示的鼓励信息 */
|
/**关卡中对话得到高分后,额外向玩家展示的鼓励信息 */
|
||||||
encourageMessage: string;
|
encourageMessage: string;
|
||||||
/**结算图片 关卡 0 星,挑战失败的情况下在结算界面展示的 CG 资源名称 */
|
/**结算图片 关卡 0 星,挑战失败的情况下在结算界面展示的 CG 资源名称 */
|
||||||
failureCG: string;
|
failureCG: string;
|
||||||
/**结算图片 关卡 1 星,挑战成功的情况下在结算界面展示的 CG 资源名称 */
|
/**结算图片 关卡 1 星,挑战成功的情况下在结算界面展示的 CG 资源名称 */
|
||||||
oneStarCG: string;
|
oneStarCG: string;
|
||||||
/**结算图片 关卡 2 星,挑战成功的情况下在结算界面展示的 CG 资源名称 */
|
/**结算图片 关卡 2 星,挑战成功的情况下在结算界面展示的 CG 资源名称 */
|
||||||
twoStarCG: string;
|
twoStarCG: string;
|
||||||
/**结算图片 关卡 3 星,那么需要展示的 CG 资源对应的名称 */
|
/**结算图片 关卡 3 星,那么需要展示的 CG 资源对应的名称 */
|
||||||
threeStarCG: string;
|
threeStarCG: string;
|
||||||
/**关卡中,对话得分特别低的情况下,额外给出的向玩家展示的鼓励信息 */
|
/**关卡中,对话得分特别低的情况下,额外给出的向玩家展示的鼓励信息 */
|
||||||
hateMessage: string;
|
hateMessage: string;
|
||||||
/**关卡选择界面,菱形的头像资源名称 */
|
/**关卡选择界面,菱形的头像资源名称 */
|
||||||
icon: string;
|
icon: string;
|
||||||
/**唯一的关卡 id 信息 */
|
/**唯一的关卡 id 信息 */
|
||||||
id: string;
|
id: string;
|
||||||
/**关卡是否已解锁,注意锁定状态仍然能够选择关卡,关卡选择界面中的背景和立绘需要切换做展示,但是玩家不能开启游戏哈 */
|
/**关卡是否已解锁,注意锁定状态仍然能够选择关卡,关卡选择界面中的背景和立绘需要切换做展示,但是玩家不能开启游戏哈 */
|
||||||
is_unlock: boolean;
|
is_unlock: boolean;
|
||||||
/**npc名称 */
|
/**npc名称 */
|
||||||
name: string;
|
name: string;
|
||||||
/**关卡展示顺序 */
|
/**关卡展示顺序 */
|
||||||
no: number;
|
no: number;
|
||||||
/**关卡解锁需要通关的前置关卡 id 信息,对应id字段 */
|
/**关卡解锁需要通关的前置关卡 id 信息,对应id字段 */
|
||||||
preLevelId: string;
|
preLevelId: string;
|
||||||
/**进入关卡后,角色发出给到玩家的开场白信息(历史聊天记录页面中也需要显示,一定是角色发出的第一句话) */
|
/**进入关卡后,角色发出给到玩家的开场白信息(历史聊天记录页面中也需要显示,一定是角色发出的第一句话) */
|
||||||
prologueMessage: string;
|
prologueMessage: string;
|
||||||
/**玩家在关卡中,点击随机填充按钮,需要随机选取一句,在输入框中填入,注意填入后不发送,玩家可修改,最终发送的信息还是以玩家点击发送按钮时,填入的信息为主 */
|
/**玩家在关卡中,点击随机填充按钮,需要随机选取一句,在输入框中填入,注意填入后不发送,玩家可修改,最终发送的信息还是以玩家点击发送按钮时,填入的信息为主 */
|
||||||
randomInputPool: string[];
|
randomInputPool: string[];
|
||||||
/**关卡进行中的record_id,有值时要先获取一下之前的存档 */
|
/**关卡进行中的record_id,有值时要先获取一下之前的存档 */
|
||||||
record_id: string;
|
record_id: string;
|
||||||
/**关卡历史最高分 */
|
/**关卡历史最高分 */
|
||||||
score: number;
|
score: number;
|
||||||
/**关卡历史最高星级 */
|
/**关卡历史最高星级 */
|
||||||
star: number;
|
star: number;
|
||||||
/**关卡中,关卡提示信息界面里底部展示的提示信息文本,目前测试数据和关卡介绍信息一致,但后续会区分开来 */
|
/**关卡中,关卡提示信息界面里底部展示的提示信息文本,目前测试数据和关卡介绍信息一致,但后续会区分开来 */
|
||||||
tips: string;
|
tips: string;
|
||||||
/**Npc结算对话 3星时 */
|
/**Npc结算对话 3星时 */
|
||||||
threeStarSummary: string;
|
threeStarSummary: string;
|
||||||
/**Npc结算对话 2星时 */
|
/**Npc结算对话 2星时 */
|
||||||
twoStarSummary: string;
|
twoStarSummary: string;
|
||||||
/**Npc结算对话 1星时 */
|
/**Npc结算对话 1星时 */
|
||||||
oneStarSummary: string;
|
oneStarSummary: string;
|
||||||
/**Npc结算对话 0星时 */
|
/**Npc结算对话 0星时 */
|
||||||
failureSummary: string;
|
failureSummary: string;
|
||||||
/**Npc表情立绘 害羞 */
|
/**Npc表情立绘 害羞 */
|
||||||
characterShyPortrait: string;
|
characterShyPortrait: string;
|
||||||
/**Npc表情立绘 厌恶 */
|
/**Npc表情立绘 厌恶 */
|
||||||
characterHatePortrait: string;
|
characterHatePortrait: string;
|
||||||
/**Npc表情立绘 开心 */
|
/**Npc表情立绘 开心 */
|
||||||
characterHappyPortrait: string;
|
characterHappyPortrait: string;
|
||||||
/**关卡解锁类型 -1=未解锁 0=自动解锁 1=游戏通关解锁 2=手动解锁 */
|
/**关卡解锁类型 -1=未解锁 0=自动解锁 1=游戏通关解锁 2=手动解锁 */
|
||||||
unlock_type: number;
|
unlock_type: number;
|
||||||
/**私家珍藏图片列表 */
|
/**私家珍藏图片列表 */
|
||||||
photoAwards: I_ZhengCangConfig[];
|
photoAwards: I_ZhengCangConfig[];
|
||||||
/**关卡是否打过 */
|
/**关卡是否打过 */
|
||||||
is_played: boolean;
|
is_played: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**私家珍藏配置数据 */
|
/**私家珍藏配置数据 */
|
||||||
export interface I_ZhengCangConfig {
|
export interface I_ZhengCangConfig {
|
||||||
/**图片名 */
|
/**图片名 */
|
||||||
giftImgName: string;
|
giftImgName: string;
|
||||||
/**故事文本列表 */
|
/**故事文本列表 */
|
||||||
giftStory: string[];
|
giftStory: string[];
|
||||||
/**简述 */
|
/**简述 */
|
||||||
giftSummary: string;
|
giftSummary: string;
|
||||||
/**唯一id */
|
/**唯一id */
|
||||||
id: number;
|
id: number;
|
||||||
/**对应关卡id */
|
/**对应关卡id */
|
||||||
levelId: string;
|
levelId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**关卡对话数据 */
|
/**关卡对话数据 */
|
||||||
export interface I_LevelStepData {
|
export interface I_LevelStepData {
|
||||||
/**当前聊天次数 */
|
/**当前聊天次数 */
|
||||||
current_cnt: number;
|
current_cnt: number;
|
||||||
/**结束评分 */
|
/**结束评分 */
|
||||||
end_star: number;
|
end_star: number;
|
||||||
/**关卡id */
|
/**关卡id */
|
||||||
id: string;
|
id: string;
|
||||||
/**最大聊天次数 */
|
/**最大聊天次数 */
|
||||||
max_cnt: number;
|
max_cnt: number;
|
||||||
/**当前状态 0:成功 1:进行中 2:失败 3:剩余聊天次数不足 */
|
/**当前状态 0:成功 1:进行中 2:失败 3:剩余聊天次数不足 */
|
||||||
status: number;
|
status: number;
|
||||||
/**可用总聊天次数 */
|
/**可用总聊天次数 */
|
||||||
total_cnt: number;
|
total_cnt: number;
|
||||||
/**心动次数 */
|
/**心动次数 */
|
||||||
heartbeat_cnt: number;
|
heartbeat_cnt: number;
|
||||||
/**剩余可看广告次数 */
|
/**剩余可看广告次数 */
|
||||||
ad_num: number;
|
ad_num: number;
|
||||||
/**剩余可分享次数 */
|
/**剩余可分享次数 */
|
||||||
share_num: number;
|
share_num: number;
|
||||||
/**剩余可撤回次数 */
|
/**剩余可撤回次数 */
|
||||||
can_use_cancel_cnt: number;
|
can_use_cancel_cnt: number;
|
||||||
/**剩余可暴击次数 */
|
/**剩余可暴击次数 */
|
||||||
can_use_strength_cnt: number;
|
can_use_strength_cnt: number;
|
||||||
/**暴击是否生效 */
|
/**暴击是否生效 */
|
||||||
is_strength_take_effect: boolean;
|
is_strength_take_effect: boolean;
|
||||||
/**甜蜜暴击已用次数 */
|
/**甜蜜暴击已用次数 */
|
||||||
first_strength?: number;
|
first_strength?: number;
|
||||||
/**撤回已用次数 */
|
/**撤回已用次数 */
|
||||||
first_cancel?: number;
|
first_cancel?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**npc长连接中的回复 */
|
/**npc长连接中的回复 */
|
||||||
export interface I_NpcTalkBack {
|
export interface I_NpcTalkBack {
|
||||||
/**ai表情 */
|
/**ai表情 */
|
||||||
aiEmoji:string;
|
aiEmoji: string;
|
||||||
/**ai回复 */
|
/**ai回复 */
|
||||||
aiResponse:string;
|
aiResponse: string;
|
||||||
/**ai评分 */
|
/**ai评分 */
|
||||||
aiScore:number;
|
aiScore: number;
|
||||||
/**ai基础评分 */
|
/**ai基础评分 */
|
||||||
aiBaseScore:number;
|
aiBaseScore: number;
|
||||||
/**ai额外加分 */
|
/**ai额外加分 */
|
||||||
aiAdditionalScore:number;
|
aiAdditionalScore: number;
|
||||||
/**是否完成 */
|
/**是否完成 */
|
||||||
isFinished:boolean;
|
isFinished: boolean;
|
||||||
/**聊天次数 */
|
/**聊天次数 */
|
||||||
sourceCnt:number;
|
sourceCnt: number;
|
||||||
/**玩家发的文本 */
|
/**玩家发的文本 */
|
||||||
userInput: string;
|
userInput: string;
|
||||||
/**评价 -1=未生成 0=心动 1=普通 2=厌恶 */
|
/**评价 -1=未生成 0=心动 1=普通 2=厌恶 */
|
||||||
judgement: number;
|
judgement: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**对话历史记录数据 */
|
/**对话历史记录数据 */
|
||||||
export interface I_TalkRecordInfo {
|
export interface I_TalkRecordInfo {
|
||||||
/**对话内容 */
|
/**对话内容 */
|
||||||
talk: string;
|
talk: string;
|
||||||
/**是否是玩家自己 */
|
/**是否是玩家自己 */
|
||||||
isMe: boolean;
|
isMe: boolean;
|
||||||
/**评分 小于0时不显示 */
|
/**评分 小于0时不显示 */
|
||||||
score: number;
|
score: number;
|
||||||
/**基础分 */
|
/**基础分 */
|
||||||
scoreBase: number;
|
scoreBase: number;
|
||||||
/**额外加分 */
|
/**额外加分 */
|
||||||
scoreAdditional: number;
|
scoreAdditional: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**玩家信息数据 */
|
/**玩家信息数据 */
|
||||||
export interface I_UserInfo {
|
export interface I_UserInfo {
|
||||||
id: number;
|
id: number;
|
||||||
score: number;
|
score: number;
|
||||||
status: number;
|
status: number;
|
||||||
/**头像url */
|
/**头像url */
|
||||||
avatar: string;
|
avatar: string;
|
||||||
/**昵称 */
|
/**昵称 */
|
||||||
nickname: string;
|
nickname: string;
|
||||||
/**剩余进入关卡次数 */
|
/**剩余进入关卡次数 */
|
||||||
ticket: number;
|
ticket: number;
|
||||||
/**剩余可看广告次数 - 进入关卡 */
|
/**剩余可看广告次数 - 进入关卡 */
|
||||||
game_ad_num: number;
|
game_ad_num: number;
|
||||||
/**剩余可分享次数 - 进入关卡 */
|
/**剩余可分享次数 - 进入关卡 */
|
||||||
game_share_num: number;
|
game_share_num: number;
|
||||||
/**剩余可看广告次数 - 聊天 */
|
/**剩余可看广告次数 - 聊天 */
|
||||||
level_ad_num: number;
|
level_ad_num: number;
|
||||||
/**剩余可分享次数 - 聊天 */
|
/**剩余可分享次数 - 聊天 */
|
||||||
level_share_num: number;
|
level_share_num: number;
|
||||||
/**抖音侧边栏奖励是否已领取 0未领取 1已领取 */
|
/**抖音侧边栏奖励是否已领取 0未领取 1已领取 */
|
||||||
is_receive: number;
|
is_receive: number;
|
||||||
/**友盟关卡记录 */
|
/**友盟关卡记录 */
|
||||||
levels: any[];
|
levels: any[];
|
||||||
/**私家珍藏红点标记 0不显示 1显示 */
|
/**私家珍藏红点标记 0不显示 1显示 */
|
||||||
private_collection_mark: number;
|
private_collection_mark: number;
|
||||||
/**心动回忆红点标记 0不显示 1显示 */
|
/**心动回忆红点标记 0不显示 1显示 */
|
||||||
heartbeat_memories_mark: number;
|
heartbeat_memories_mark: number;
|
||||||
/**剩余可免费获取珍藏的次数 */
|
/**剩余可免费获取珍藏的次数 */
|
||||||
free_private_collection: number;
|
free_private_collection: number;
|
||||||
// [property: string]: any;
|
// [property: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**心动回忆数据 */
|
/**心动回忆数据 */
|
||||||
export interface I_HuiyiInfo {
|
export interface I_HuiyiInfo {
|
||||||
/**关卡id */
|
/**关卡id */
|
||||||
lvId: string;
|
lvId: string;
|
||||||
/**星数 */
|
/**星数 */
|
||||||
star: number;
|
star: number;
|
||||||
/**是否解锁 */
|
/**是否解锁 */
|
||||||
unlock: boolean;
|
unlock: boolean;
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,8 @@ export enum InnerMsgCode {
|
|||||||
BalanceChange, // 余额发生变化
|
BalanceChange, // 余额发生变化
|
||||||
VipExpireChange, // vip失效时间戳发生变化
|
VipExpireChange, // vip失效时间戳发生变化
|
||||||
ChatTotalCountChange, // 总聊天次数发生变化
|
ChatTotalCountChange, // 总聊天次数发生变化
|
||||||
|
|
||||||
|
Navigation_PanelSwitch, // 导航面板切换事件
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum InnerEventCode {
|
export enum InnerEventCode {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { _decorator, Camera, Component, Node } from "cc";
|
import { _decorator, Camera, Component, Node } from "cc";
|
||||||
import GameRootUI from "../Main/Common/GameRootUI";
|
import GameRootUI from "../Main/Common/GameRootUI";
|
||||||
|
import { MainController } from "../chat18x/core/MainController";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -18,8 +19,24 @@ export class MainScene extends Component {
|
|||||||
let gameRootUI = this.node.getComponent(GameRootUI);
|
let gameRootUI = this.node.getComponent(GameRootUI);
|
||||||
if (!gameRootUI) {
|
if (!gameRootUI) {
|
||||||
gameRootUI = this.node.addComponent(GameRootUI);
|
gameRootUI = this.node.addComponent(GameRootUI);
|
||||||
gameRootUI.InitByCreate(this.UIRoot, this.UILayerMod, "ThemePanel");
|
gameRootUI.InitByCreate(this.UIRoot, this.UILayerMod, "NavigationPanel");
|
||||||
}
|
}
|
||||||
GameRootUI.MainCamera = this.MainCamera;
|
GameRootUI.MainCamera = this.MainCamera;
|
||||||
|
|
||||||
|
// 初始化MainController并预加载数据
|
||||||
|
this.initMainController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化MainController并预加载数据
|
||||||
|
*/
|
||||||
|
private async initMainController(): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log("[MainScene] 开始初始化MainController");
|
||||||
|
await MainController.I.init();
|
||||||
|
console.log("[MainScene] MainController初始化完成");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainScene] MainController初始化失败:", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import { _decorator, Component, Node } from "cc";
|
||||||
|
import { ThemeService } from "../network/services/ThemeService";
|
||||||
|
import { GirlService } from "../network/services/GirlService";
|
||||||
|
import { ShopService } from "../network/services/ShopService";
|
||||||
|
import { DataManager, DataId } from "../data/DataManager";
|
||||||
|
import { ThemeData } from "../data/ThemeData";
|
||||||
|
import { GirlData } from "../data/GirlData";
|
||||||
|
import { ShopData } from "../data/ShopData";
|
||||||
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
||||||
|
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
@ccclass("MainController")
|
||||||
|
export class MainController {
|
||||||
|
private static _instance: MainController;
|
||||||
|
public static get I(): MainController {
|
||||||
|
if (!MainController._instance) {
|
||||||
|
MainController._instance = new MainController();
|
||||||
|
}
|
||||||
|
return MainController._instance;
|
||||||
|
}
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
// 数据预加载状态标记
|
||||||
|
private isThemeDataPreloaded: boolean = false;
|
||||||
|
private isDailyRecommendPreloaded: boolean = false;
|
||||||
|
private isShopListPreloaded: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化并预加载数据
|
||||||
|
*/
|
||||||
|
async init(): Promise<void> {
|
||||||
|
console.log("[MainController] 开始初始化并预加载数据");
|
||||||
|
|
||||||
|
// 并行预加载所有数据
|
||||||
|
await Promise.all([
|
||||||
|
this.preloadThemeData(),
|
||||||
|
this.preloadDailyRecommend(),
|
||||||
|
this.preloadShopList()
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log("[MainController] 数据预加载完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预加载主题数据
|
||||||
|
*/
|
||||||
|
async preloadThemeData(): Promise<boolean> {
|
||||||
|
if (this.isThemeDataPreloaded) {
|
||||||
|
console.log("[MainController] 主题数据已预加载");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log("[MainController] 开始预加载主题数据");
|
||||||
|
const reqData = {};
|
||||||
|
const res = await ThemeService.I.reqHallTheme(reqData);
|
||||||
|
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
|
// 保存数据到DataManager
|
||||||
|
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
|
||||||
|
themeData.themes = res.data;
|
||||||
|
this.isThemeDataPreloaded = true;
|
||||||
|
console.log("[MainController] 主题数据预加载成功");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("[MainController] 主题数据预加载失败:", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainController] 主题数据预加载异常:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预加载每日推荐
|
||||||
|
*/
|
||||||
|
async preloadDailyRecommend(): Promise<boolean> {
|
||||||
|
if (this.isDailyRecommendPreloaded) {
|
||||||
|
console.log("[MainController] 每日推荐数据已预加载");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log("[MainController] 开始预加载每日推荐数据");
|
||||||
|
const reqData = {};
|
||||||
|
const res = await GirlService.I.reqDailyRecommend(reqData);
|
||||||
|
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
|
// 保存数据到DataManager
|
||||||
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
|
girlData.setDailyRecommend(res.data);
|
||||||
|
this.isDailyRecommendPreloaded = true;
|
||||||
|
console.log("[MainController] 每日推荐数据预加载成功");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("[MainController] 每日推荐数据预加载失败:", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainController] 每日推荐数据预加载异常:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预加载商品列表
|
||||||
|
*/
|
||||||
|
async preloadShopList(): Promise<boolean> {
|
||||||
|
if (this.isShopListPreloaded) {
|
||||||
|
console.log("[MainController] 商品列表数据已预加载");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log("[MainController] 开始预加载商品列表数据");
|
||||||
|
const reqData = {};
|
||||||
|
const res = await ShopService.I.reqShopList(reqData);
|
||||||
|
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
|
// 保存数据到DataManager
|
||||||
|
const shopData = DataManager.I.getDataById<ShopData>(DataId.Shop);
|
||||||
|
shopData.goods = res.data;
|
||||||
|
this.isShopListPreloaded = true;
|
||||||
|
console.log("[MainController] 商品列表数据预加载成功");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("[MainController] 商品列表数据预加载失败:", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainController] 商品列表数据预加载异常:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查数据是否已预加载
|
||||||
|
*/
|
||||||
|
isDataPreloaded(): boolean {
|
||||||
|
return this.isThemeDataPreloaded && this.isDailyRecommendPreloaded && this.isShopListPreloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取预加载状态
|
||||||
|
*/
|
||||||
|
getPreloadStatus() {
|
||||||
|
return {
|
||||||
|
themeData: this.isThemeDataPreloaded,
|
||||||
|
dailyRecommend: this.isDailyRecommendPreloaded,
|
||||||
|
shopList: this.isShopListPreloaded,
|
||||||
|
allComplete: this.isDataPreloaded()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置预加载状态(用于重新加载数据)
|
||||||
|
*/
|
||||||
|
resetPreloadStatus(): void {
|
||||||
|
this.isThemeDataPreloaded = false;
|
||||||
|
this.isDailyRecommendPreloaded = false;
|
||||||
|
this.isShopListPreloaded = false;
|
||||||
|
console.log("[MainController] 预加载状态已重置");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制刷新主题数据
|
||||||
|
*/
|
||||||
|
async refreshThemeData(): Promise<boolean> {
|
||||||
|
console.log("[MainController] 开始强制刷新主题数据");
|
||||||
|
try {
|
||||||
|
const reqData = {};
|
||||||
|
const res = await ThemeService.I.reqHallTheme(reqData);
|
||||||
|
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
|
// 保存数据到DataManager
|
||||||
|
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
|
||||||
|
themeData.themes = res.data;
|
||||||
|
this.isThemeDataPreloaded = true;
|
||||||
|
console.log("[MainController] 主题数据刷新成功");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("[MainController] 主题数据刷新失败:", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainController] 主题数据刷新异常:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制刷新每日推荐数据
|
||||||
|
*/
|
||||||
|
async refreshDailyRecommend(): Promise<boolean> {
|
||||||
|
console.log("[MainController] 开始强制刷新每日推荐数据");
|
||||||
|
try {
|
||||||
|
const reqData = {};
|
||||||
|
const res = await GirlService.I.reqDailyRecommend(reqData);
|
||||||
|
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
|
// 保存数据到DataManager
|
||||||
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
|
girlData.setDailyRecommend(res.data);
|
||||||
|
this.isDailyRecommendPreloaded = true;
|
||||||
|
console.log("[MainController] 每日推荐数据刷新成功");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("[MainController] 每日推荐数据刷新失败:", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[MainController] 每日推荐数据刷新异常:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "d3917420-e17a-46f9-8864-4f4997a10ddc",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
||||||
import { UITransitionHelper } from "../utils/UITransitionHelper";
|
import { UITransitionHelper } from "../utils/UITransitionHelper";
|
||||||
import GameRootUI from "../../Main/Common/GameRootUI";
|
import GameRootUI from "../../Main/Common/GameRootUI";
|
||||||
|
import { Node } from "cc";
|
||||||
|
import li_EventManager from "../../Main/Common/li_EventManager";
|
||||||
|
import { InnerMsgCode } from "../../Main/Config/InnerMsgCode";
|
||||||
|
import { ThemePanel } from "../ui/panels/ThemePanel";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面过渡动画类型枚举
|
* 页面过渡动画类型枚举
|
||||||
@@ -11,6 +15,16 @@ export enum PageTransitionType {
|
|||||||
SLIDE_RIGHT = "slide_right",
|
SLIDE_RIGHT = "slide_right",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NavigationPanel面板类型枚举
|
||||||
|
*/
|
||||||
|
export enum PanelType {
|
||||||
|
THEME = "ThemePanel",
|
||||||
|
GIRL_DETAIL = "GirlDetailPanel",
|
||||||
|
CHAT = "ChatPanel",
|
||||||
|
SETTING = "SettingPanel",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面过渡动画配置接口
|
* 页面过渡动画配置接口
|
||||||
*/
|
*/
|
||||||
@@ -25,6 +39,7 @@ export interface PageTransitionConfig {
|
|||||||
* 导航管理器
|
* 导航管理器
|
||||||
*
|
*
|
||||||
* 负责管理游戏中的页面导航和路由,将导航逻辑从业务逻辑中分离出来
|
* 负责管理游戏中的页面导航和路由,将导航逻辑从业务逻辑中分离出来
|
||||||
|
* 统一管理NavigationPanel和其他面板的切换
|
||||||
*
|
*
|
||||||
* @author AI Chat System
|
* @author AI Chat System
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -32,6 +47,16 @@ export interface PageTransitionConfig {
|
|||||||
export class NavigationManager {
|
export class NavigationManager {
|
||||||
private static _instance: NavigationManager;
|
private static _instance: NavigationManager;
|
||||||
|
|
||||||
|
// NavigationPanel相关属性
|
||||||
|
private navigationPanel: any = null; // NavigationPanel实例引用
|
||||||
|
private currentActivePanel: PanelType = PanelType.THEME;
|
||||||
|
private panelCache: Map<PanelType, Node> = new Map(); // 面板缓存
|
||||||
|
private currentVisiblePanel: Node = null;
|
||||||
|
|
||||||
|
// 选中的角色相关信息
|
||||||
|
private selectedGirlId: number = 1; // 当前选中的角色ID
|
||||||
|
private selectedThemeId: number = 1; // 当前选中的主题ID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取NavigationManager的单例实例
|
* 获取NavigationManager的单例实例
|
||||||
*
|
*
|
||||||
@@ -45,7 +70,350 @@ export class NavigationManager {
|
|||||||
return this._instance;
|
return this._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {
|
||||||
|
// 初始化事件监听
|
||||||
|
this.initEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化事件监听
|
||||||
|
*/
|
||||||
|
private initEventListeners(): void {
|
||||||
|
// 监听导航面板切换事件
|
||||||
|
li_EventManager.I.addInnerEL(
|
||||||
|
InnerMsgCode.Navigation_PanelSwitch,
|
||||||
|
this.onNavigationEvent,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理导航事件
|
||||||
|
*/
|
||||||
|
private onNavigationEvent(panelType: PanelType): void {
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] Received navigation event for:",
|
||||||
|
panelType
|
||||||
|
);
|
||||||
|
this.switchToPanel(panelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册NavigationPanel实例
|
||||||
|
* @param panel NavigationPanel实例
|
||||||
|
*/
|
||||||
|
public registerNavigationPanel(panel: any): void {
|
||||||
|
this.navigationPanel = panel;
|
||||||
|
console.log("[NavigationManager] NavigationPanel registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一的面板切换方法
|
||||||
|
* @param panelType 目标面板类型
|
||||||
|
*/
|
||||||
|
public switchToPanel(panelType: PanelType, force: boolean = false): void {
|
||||||
|
if (this.currentActivePanel === panelType && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.navigationPanel) {
|
||||||
|
console.warn(
|
||||||
|
"[NavigationManager] NavigationPanel not registered, fallback to direct ViewManager call"
|
||||||
|
);
|
||||||
|
this.fallbackSwitchPanel(panelType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知NavigationPanel显示加载状态
|
||||||
|
this.navigationPanel.showLoading?.();
|
||||||
|
|
||||||
|
// 计算动画方向
|
||||||
|
const currentIndex = this.getPanelIndex(this.currentActivePanel);
|
||||||
|
const targetIndex = this.getPanelIndex(panelType);
|
||||||
|
const isMovingRight = currentIndex < targetIndex;
|
||||||
|
|
||||||
|
const hideDirection = isMovingRight ? "left" : "right";
|
||||||
|
const showDirection = isMovingRight ? "right" : "left";
|
||||||
|
|
||||||
|
// 隐藏当前面板(包括子页面)
|
||||||
|
this.hideCurrentPanelWithChildren(hideDirection);
|
||||||
|
|
||||||
|
// 加载并显示目标面板
|
||||||
|
this.loadOrGetPanel(panelType, (panel: Node) => {
|
||||||
|
this.currentActivePanel = panelType;
|
||||||
|
this.currentVisiblePanel = panel;
|
||||||
|
|
||||||
|
// 更新NavigationPanel按钮状态
|
||||||
|
this.navigationPanel.updateButtonStates?.(panelType);
|
||||||
|
|
||||||
|
// 显示面板
|
||||||
|
this.showPanelWithAnimation(panel, showDirection, () => {
|
||||||
|
this.navigationPanel.hideLoading?.();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取面板索引(用于动画方向计算)
|
||||||
|
*/
|
||||||
|
private getPanelIndex(panelType: PanelType): number {
|
||||||
|
switch (panelType) {
|
||||||
|
case PanelType.THEME:
|
||||||
|
return 0;
|
||||||
|
case PanelType.GIRL_DETAIL:
|
||||||
|
return 1;
|
||||||
|
case PanelType.CHAT:
|
||||||
|
return 2;
|
||||||
|
case PanelType.SETTING:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取面板名称
|
||||||
|
*/
|
||||||
|
private getPanelName(panelType: PanelType): string {
|
||||||
|
return panelType as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取面板数据
|
||||||
|
*/
|
||||||
|
private getPanelData(panelType: PanelType): any {
|
||||||
|
switch (panelType) {
|
||||||
|
case PanelType.GIRL_DETAIL:
|
||||||
|
return this.selectedGirlId; // 使用当前选中的角色ID
|
||||||
|
case PanelType.CHAT:
|
||||||
|
return { girlId: this.selectedGirlId }; // 使用当前选中的角色ID
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载或获取面板
|
||||||
|
*/
|
||||||
|
private loadOrGetPanel(
|
||||||
|
panelType: PanelType,
|
||||||
|
callback: (panel: Node) => void
|
||||||
|
) {
|
||||||
|
// 检查缓存
|
||||||
|
if (this.panelCache.has(panelType)) {
|
||||||
|
const cachedPanel = this.panelCache.get(panelType);
|
||||||
|
if (cachedPanel && cachedPanel.isValid) {
|
||||||
|
// 特殊处理:主题面板刷新(避免重复调用Show)
|
||||||
|
if (panelType === PanelType.THEME) {
|
||||||
|
const themePanel = cachedPanel.getComponent(ThemePanel);
|
||||||
|
if (themePanel) {
|
||||||
|
// 不在这里调用Show(),因为ThemePanel已经有加载状态保护
|
||||||
|
// 只在必要时调用onHide()确保子页面状态正确
|
||||||
|
if (typeof themePanel.onHide === "function") {
|
||||||
|
console.log("[NavigationManager] 确保主题面板子页面状态正确");
|
||||||
|
themePanel.onHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(cachedPanel);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.panelCache.delete(panelType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载新面板
|
||||||
|
const panelName = this.getPanelName(panelType);
|
||||||
|
const openData = this.getPanelData(panelType);
|
||||||
|
|
||||||
|
ViewManager.I.openBundlesView(panelName, openData, (panel: Node) => {
|
||||||
|
if (panel && panel.isValid) {
|
||||||
|
this.panelCache.set(panelType, panel);
|
||||||
|
callback(panel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏当前面板及其子页面
|
||||||
|
*/
|
||||||
|
private hideCurrentPanelWithChildren(direction: "left" | "right") {
|
||||||
|
if (!this.currentVisiblePanel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前是ThemePanel,需要同时处理可能的子页面(GirlListPanel)
|
||||||
|
if (this.currentActivePanel === PanelType.THEME) {
|
||||||
|
// 查找并隐藏GirlListPanel子页面
|
||||||
|
this.hideThemePanelChildren(direction);
|
||||||
|
|
||||||
|
// 隐藏ThemePanel主面板
|
||||||
|
this.hidePanelWithAnimation(this.currentVisiblePanel, direction);
|
||||||
|
} else {
|
||||||
|
// 其他面板直接隐藏
|
||||||
|
this.hidePanelWithAnimation(this.currentVisiblePanel, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏ThemePanel的子页面
|
||||||
|
*/
|
||||||
|
private hideThemePanelChildren(direction: "left" | "right") {
|
||||||
|
const themePanelNode = this.findThemePanelNode();
|
||||||
|
if (themePanelNode) {
|
||||||
|
const themePanelComponent = themePanelNode.getComponent("ThemePanel");
|
||||||
|
if (themePanelComponent) {
|
||||||
|
// 获取子页面节点
|
||||||
|
const childPanel = this.getThemePanelChildNode(themePanelComponent);
|
||||||
|
if (childPanel && childPanel.active) {
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] Hiding ThemePanel child with animation"
|
||||||
|
);
|
||||||
|
this.hidePanelWithAnimation(childPanel, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ThemePanel的子页面节点
|
||||||
|
*/
|
||||||
|
private getThemePanelChildNode(themePanelComponent: any): Node | null {
|
||||||
|
try {
|
||||||
|
// ThemePanel存储子页面在currentChildPanel属性中
|
||||||
|
if (
|
||||||
|
themePanelComponent.currentChildPanel &&
|
||||||
|
themePanelComponent.currentChildPanel.node
|
||||||
|
) {
|
||||||
|
return themePanelComponent.currentChildPanel.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有直接的引用,尝试通过ViewManager查找GirlListPanel
|
||||||
|
const viewList = (ViewManager.I as any).m_viewList;
|
||||||
|
if (viewList) {
|
||||||
|
for (let i = 0; i < viewList.length; i++) {
|
||||||
|
const view = viewList[i];
|
||||||
|
if (
|
||||||
|
view &&
|
||||||
|
view.isValid &&
|
||||||
|
view.name === "GirlListPanel" &&
|
||||||
|
view.active
|
||||||
|
) {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[NavigationManager] Error getting child panel node:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏面板动画
|
||||||
|
*/
|
||||||
|
private hidePanelWithAnimation(
|
||||||
|
panel: Node,
|
||||||
|
direction: "left" | "right",
|
||||||
|
callback?: Function
|
||||||
|
) {
|
||||||
|
if (!panel || !panel.isValid || !panel.active) {
|
||||||
|
callback && callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction === "left") {
|
||||||
|
UITransitionHelper.slideOutToLeft(panel, 0.3, () => {
|
||||||
|
panel.active = false;
|
||||||
|
callback && callback();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
UITransitionHelper.slideOutToRight(panel, 0.3, () => {
|
||||||
|
panel.active = false;
|
||||||
|
callback && callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示面板动画
|
||||||
|
*/
|
||||||
|
private showPanelWithAnimation(
|
||||||
|
panel: Node,
|
||||||
|
direction: "left" | "right",
|
||||||
|
callback?: Function
|
||||||
|
) {
|
||||||
|
if (!panel || !panel.isValid) {
|
||||||
|
callback && callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.active = true;
|
||||||
|
|
||||||
|
if (direction === "right") {
|
||||||
|
UITransitionHelper.slideInFromRight(panel, 0.3, () => {
|
||||||
|
callback && callback();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
UITransitionHelper.slideInFromLeft(panel, 0.3, () => {
|
||||||
|
callback && callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后备切换方法(当NavigationPanel未注册时)
|
||||||
|
*/
|
||||||
|
private fallbackSwitchPanel(panelType: PanelType): void {
|
||||||
|
const panelName = this.getPanelName(panelType);
|
||||||
|
const openData = this.getPanelData(panelType);
|
||||||
|
ViewManager.I.openBundlesView(panelName, openData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前激活的面板类型
|
||||||
|
*/
|
||||||
|
public getCurrentActivePanel(): PanelType {
|
||||||
|
return this.currentActivePanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置选中的角色ID
|
||||||
|
* @param girlId 角色ID
|
||||||
|
*/
|
||||||
|
public setSelectedGirlId(girlId: number): void {
|
||||||
|
this.selectedGirlId = girlId;
|
||||||
|
console.log("[NavigationManager] Selected girl ID set to:", girlId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前选中的角色ID
|
||||||
|
* @returns 当前选中的角色ID
|
||||||
|
*/
|
||||||
|
public getSelectedGirlId(): number {
|
||||||
|
return this.selectedGirlId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置选中的主题ID
|
||||||
|
* @param themeId 主题ID
|
||||||
|
*/
|
||||||
|
public setSelectedThemeId(themeId: number): void {
|
||||||
|
this.selectedThemeId = themeId;
|
||||||
|
console.log("[NavigationManager] Selected theme ID set to:", themeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前选中的主题ID
|
||||||
|
* @returns 当前选中的主题ID
|
||||||
|
*/
|
||||||
|
public getSelectedThemeId(): number {
|
||||||
|
return this.selectedThemeId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用页面导航方法,支持过渡动画
|
* 通用页面导航方法,支持过渡动画
|
||||||
@@ -89,6 +457,11 @@ export class NavigationManager {
|
|||||||
transitionConfig.outgoingTransition !== PageTransitionType.NONE;
|
transitionConfig.outgoingTransition !== PageTransitionType.NONE;
|
||||||
|
|
||||||
if (!useTransition) {
|
if (!useTransition) {
|
||||||
|
// 在没有过渡动画的情况下,也需要处理子页面逻辑
|
||||||
|
if (targetPanel && targetPanel !== "GirlListPanel") {
|
||||||
|
this.handleThemePanelChildPanelsOnNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
ViewManager.I.openBundlesView(targetPanel, navigationData, onComplete);
|
ViewManager.I.openBundlesView(targetPanel, navigationData, onComplete);
|
||||||
if (
|
if (
|
||||||
currentPanel &&
|
currentPanel &&
|
||||||
@@ -129,6 +502,7 @@ export class NavigationManager {
|
|||||||
duration: number,
|
duration: number,
|
||||||
onComplete?: Function
|
onComplete?: Function
|
||||||
): void {
|
): void {
|
||||||
|
const targetPanelName = targetNode ? targetNode.name : null;
|
||||||
const executeIncomingAnimation = (callback?: Function) => {
|
const executeIncomingAnimation = (callback?: Function) => {
|
||||||
if (
|
if (
|
||||||
config.incomingTransition === PageTransitionType.NONE ||
|
config.incomingTransition === PageTransitionType.NONE ||
|
||||||
@@ -191,8 +565,27 @@ export class NavigationManager {
|
|||||||
currentPanel.onClose &&
|
currentPanel.onClose &&
|
||||||
typeof currentPanel.onClose === "function"
|
typeof currentPanel.onClose === "function"
|
||||||
) {
|
) {
|
||||||
if (currentPanel.node.name !== "ThemePanel") currentPanel.onClose();
|
if (currentPanel.node.name !== "ThemePanel") {
|
||||||
|
currentPanel.onClose();
|
||||||
|
} else {
|
||||||
|
// 如果当前面板是 ThemePanel,检查是否需要关闭子页面
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] ThemePanel detected, checking for child panels"
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
currentPanel.closeChildPanel &&
|
||||||
|
typeof currentPanel.closeChildPanel === "function"
|
||||||
|
) {
|
||||||
|
currentPanel.closeChildPanel();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查目标面板是否会导致需要隐藏 ThemePanel 的子页面
|
||||||
|
if (targetPanelName && targetPanelName !== "GirlListPanel") {
|
||||||
|
this.handleThemePanelChildPanelsOnNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
onComplete && onComplete();
|
onComplete && onComplete();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -215,7 +608,7 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 进入角色列表页面
|
* 进入角色列表页面(作为 ThemePanel 的子页面)
|
||||||
*
|
*
|
||||||
* @param {number} themeId - 主题ID,用于筛选角色
|
* @param {number} themeId - 主题ID,用于筛选角色
|
||||||
*
|
*
|
||||||
@@ -224,55 +617,180 @@ export class NavigationManager {
|
|||||||
* NavigationManager.Instance.navigateToGirlList(1);
|
* NavigationManager.Instance.navigateToGirlList(1);
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
public navigateToGirlList(themeId: number): void;
|
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) {
|
if (themeId == null || themeId < 0) {
|
||||||
console.warn("Invalid theme ID for girl list navigation:", themeId);
|
console.warn("Invalid theme ID for girl list navigation:", themeId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Navigating to girl list with theme ID: ${themeId}`);
|
// 更新选中的主题ID
|
||||||
|
this.setSelectedThemeId(themeId);
|
||||||
|
|
||||||
if (transitionConfig) {
|
console.log(
|
||||||
const navigationData = {
|
`[NavigationManager] Navigating to girl list with theme ID: ${themeId}`
|
||||||
category: themeId,
|
);
|
||||||
withTransition: true,
|
|
||||||
};
|
// 先检查是否已有GirlListPanel存在
|
||||||
this.navigateWithTransition(
|
const existingGirlListPanel = this.findExistingGirlListPanel();
|
||||||
|
|
||||||
|
if (existingGirlListPanel) {
|
||||||
|
// 如果面板已存在,重新显示并刷新数据
|
||||||
|
console.log("[NavigationManager] Reactivating existing GirlListPanel");
|
||||||
|
this.reactivateGirlListPanel(existingGirlListPanel, themeId);
|
||||||
|
} else {
|
||||||
|
// 如果面板不存在,创建新的
|
||||||
|
console.log("[NavigationManager] Creating new GirlListPanel");
|
||||||
|
ViewManager.I.openBundlesView(
|
||||||
"GirlListPanel",
|
"GirlListPanel",
|
||||||
themeId,
|
{
|
||||||
transitionConfig,
|
themeId: themeId,
|
||||||
currentPanel,
|
parentPanel: "ThemePanel", // 标记父页面
|
||||||
() => {
|
},
|
||||||
GameRootUI.I.hideDefaultView();
|
(girlListPanelNode) => {
|
||||||
|
// 获取 ThemePanel 实例并设置子页面关系
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] GirlListPanel opened, setting up parent-child relationship"
|
||||||
|
);
|
||||||
|
this.setupParentChildRelationship(girlListPanelNode);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
ViewManager.I.openBundlesView("GirlListPanel", themeId);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找已存在的GirlListPanel
|
||||||
|
*/
|
||||||
|
private findExistingGirlListPanel(): any {
|
||||||
|
try {
|
||||||
|
const viewList = (ViewManager.I as any).m_viewList;
|
||||||
|
if (viewList) {
|
||||||
|
for (let i = 0; i < viewList.length; i++) {
|
||||||
|
const view = viewList[i];
|
||||||
|
if (view && view.isValid && view.name === "GirlListPanel") {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[NavigationManager] Error finding existing GirlListPanel:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新激活已存在的GirlListPanel
|
||||||
|
*/
|
||||||
|
private reactivateGirlListPanel(panelNode: any, themeId: number): void {
|
||||||
|
try {
|
||||||
|
// 重新激活面板
|
||||||
|
panelNode.active = true;
|
||||||
|
|
||||||
|
// 获取面板组件并刷新数据
|
||||||
|
const girlListComponent = panelNode.getComponent("GirlListPanel");
|
||||||
|
if (girlListComponent) {
|
||||||
|
// 如果有刷新方法,调用它来更新主题数据
|
||||||
|
if (typeof girlListComponent.refreshWithTheme === "function") {
|
||||||
|
girlListComponent.refreshWithTheme(themeId);
|
||||||
|
} else if (typeof girlListComponent.Show === "function") {
|
||||||
|
girlListComponent.Show(themeId);
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] GirlListPanel reactivated with theme:",
|
||||||
|
themeId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新建立父子关系
|
||||||
|
this.setupParentChildRelationship(panelNode);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[NavigationManager] Error reactivating GirlListPanel:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 建立父子页面关系的私有方法
|
||||||
|
* @private
|
||||||
|
* @param girlListPanelNode GirlListPanel 节点
|
||||||
|
*/
|
||||||
|
private setupParentChildRelationship(girlListPanelNode: any): void {
|
||||||
|
try {
|
||||||
|
// 查找 ThemePanel 实例
|
||||||
|
const themePanelNode = this.findThemePanelNode();
|
||||||
|
if (themePanelNode) {
|
||||||
|
const themePanelComponent = themePanelNode.getComponent("ThemePanel");
|
||||||
|
const girlListPanelComponent =
|
||||||
|
girlListPanelNode.getComponent("GirlListPanel");
|
||||||
|
|
||||||
|
if (themePanelComponent && girlListPanelComponent) {
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] Setting up parent-child relationship"
|
||||||
|
);
|
||||||
|
themePanelComponent.setChildPanel(girlListPanelComponent);
|
||||||
|
} else {
|
||||||
|
console.warn("[NavigationManager] Failed to get panel components");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("[NavigationManager] ThemePanel not found");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[NavigationManager] Error setting up parent-child relationship:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找 ThemePanel 节点的私有方法
|
||||||
|
* @private
|
||||||
|
* @returns ThemePanel 节点或 null
|
||||||
|
*/
|
||||||
|
private findThemePanelNode(): any {
|
||||||
|
console.log("[NavigationManager] Finding ThemePanel node...");
|
||||||
|
try {
|
||||||
|
// 通过 ViewManager 的视图列表查找 ThemePanel
|
||||||
|
const viewList = (ViewManager.I as any).m_viewList;
|
||||||
|
if (viewList) {
|
||||||
|
for (let i = 0; i < viewList.length; i++) {
|
||||||
|
const view = viewList[i];
|
||||||
|
if (view && view.isValid && view.name === "ThemePanel") {
|
||||||
|
console.log("[NavigationManager] Found ThemePanel node");
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[NavigationManager] ThemePanel not found in view list");
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[NavigationManager] Error finding ThemePanel:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理导航时 ThemePanel 子页面的隐藏逻辑
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private handleThemePanelChildPanelsOnNavigation(): void {
|
||||||
|
console.log(
|
||||||
|
"[NavigationManager] Handling ThemePanel child panels on navigation"
|
||||||
|
);
|
||||||
|
|
||||||
|
const themePanelNode = this.findThemePanelNode();
|
||||||
|
if (themePanelNode) {
|
||||||
|
const themePanelComponent = themePanelNode.getComponent("ThemePanel");
|
||||||
|
if (themePanelComponent && themePanelComponent.closeChildPanel) {
|
||||||
|
console.log("[NavigationManager] Closing ThemePanel child panels");
|
||||||
|
themePanelComponent.closeChildPanel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +834,11 @@ export class NavigationManager {
|
|||||||
console.warn("Invalid role ID for chat navigation:", roleId);
|
console.warn("Invalid role ID for chat navigation:", roleId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GameRootUI.I.hideDefaultView();
|
|
||||||
|
// 更新选中的角色ID
|
||||||
|
this.setSelectedGirlId(roleId);
|
||||||
|
|
||||||
|
// NavigationPanel 始终显示,不需要隐藏 DefaultView
|
||||||
console.log(`Navigating to chat with role ID: ${roleId}`);
|
console.log(`Navigating to chat with role ID: ${roleId}`);
|
||||||
|
|
||||||
if (transitionConfig) {
|
if (transitionConfig) {
|
||||||
@@ -357,6 +879,12 @@ export class NavigationManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新选中的角色ID和主题ID
|
||||||
|
this.setSelectedGirlId(roleId);
|
||||||
|
if (categoryId != null) {
|
||||||
|
this.setSelectedThemeId(parseInt(categoryId));
|
||||||
|
}
|
||||||
|
|
||||||
const navigationData = {
|
const navigationData = {
|
||||||
categoryId: categoryId,
|
categoryId: categoryId,
|
||||||
roleId: roleId,
|
roleId: roleId,
|
||||||
@@ -418,6 +946,9 @@ export class NavigationManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新选中的角色ID
|
||||||
|
this.setSelectedGirlId(roleId);
|
||||||
|
|
||||||
console.log(`Navigating to girl detail with role ID: ${roleId}`);
|
console.log(`Navigating to girl detail with role ID: ${roleId}`);
|
||||||
|
|
||||||
if (transitionConfig) {
|
if (transitionConfig) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import { PayToTalkSubpanel } from "./PayToTalkSubpanel";
|
|||||||
import { DataId, DataManager } from "../../data/DataManager";
|
import { DataId, DataManager } from "../../data/DataManager";
|
||||||
import { GirlData } from "../../data/GirlData";
|
import { GirlData } from "../../data/GirlData";
|
||||||
import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer";
|
import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer";
|
||||||
import { NavigationManager } from "../../manager/NavigationManager";
|
import { NavigationManager, PanelType } from "../../manager/NavigationManager";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass("ChatPanel")
|
@ccclass("ChatPanel")
|
||||||
@@ -79,22 +79,79 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
this.girlName.string = LanguageUtils.getText(this.nameKey);
|
this.girlName.string = LanguageUtils.getText(this.nameKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
openUIDataCT(data) {
|
targetSize;
|
||||||
const newRoleId =
|
videoAreaPos;
|
||||||
typeof data === "object" && data.roleId !== undefined
|
onLoadCT() {
|
||||||
? data.roleId
|
Utils.parseNode(this.node, this._nodeTab);
|
||||||
: data;
|
|
||||||
|
// 获取 videoArea 的尺寸和位置
|
||||||
|
this.targetSize = this.videoArea.contentSize;
|
||||||
|
this.videoAreaPos = new Vec3(540, 1170, 0);
|
||||||
|
|
||||||
|
this.register();
|
||||||
|
//this.refresh();
|
||||||
|
this.payToTalkPanel.node.active = false;
|
||||||
|
|
||||||
|
// 检查 SceneBgVideoLayer 是否可用
|
||||||
|
if (!this.videoLayer) {
|
||||||
|
console.error("ChatPanel: SceneBgVideoLayer.handle 未初始化");
|
||||||
|
} else {
|
||||||
|
console.log("ChatPanel: 成功获取 SceneBgVideoLayer 实例");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register() {
|
||||||
|
Utils.addInnerEL(
|
||||||
|
InnerMsgCode.LanguageChange,
|
||||||
|
this,
|
||||||
|
this.onLanguageChangeCallback
|
||||||
|
);
|
||||||
|
|
||||||
|
Utils.addInnerEL(
|
||||||
|
InnerMsgCode.Chat_EmotionInitialized,
|
||||||
|
this,
|
||||||
|
this.onEmotionInitialized
|
||||||
|
);
|
||||||
|
|
||||||
|
Utils.addInnerEL(
|
||||||
|
InnerMsgCode.ChatTotalCountChange,
|
||||||
|
this,
|
||||||
|
this.onChatCountChange
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy(): void {
|
||||||
|
Utils.removeInnerEL(
|
||||||
|
InnerMsgCode.LanguageChange,
|
||||||
|
this,
|
||||||
|
this.onLanguageChangeCallback
|
||||||
|
);
|
||||||
|
Utils.removeInnerEL(
|
||||||
|
InnerMsgCode.ChatTotalCountChange,
|
||||||
|
this,
|
||||||
|
this.onChatCountChange
|
||||||
|
);
|
||||||
|
Utils.removeInnerEL(
|
||||||
|
InnerMsgCode.Chat_EmotionInitialized,
|
||||||
|
this,
|
||||||
|
this.onEmotionInitialized
|
||||||
|
);
|
||||||
|
|
||||||
|
// 解绑ChatController(不销毁,因为它是单例)
|
||||||
|
if (this.chatController) {
|
||||||
|
this.chatController.unbindView();
|
||||||
|
this.chatController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh() {
|
||||||
|
const newRoleId = NavigationManager.Instance.getSelectedGirlId();
|
||||||
|
|
||||||
// 检查是否是切换角色
|
// 检查是否是切换角色
|
||||||
const isRoleSwitch = this.id && this.id !== newRoleId;
|
const isRoleSwitch = this.id && this.id !== newRoleId;
|
||||||
|
|
||||||
this.id = newRoleId;
|
this.id = newRoleId;
|
||||||
this.categoryId = data.categoryId;
|
this.categoryId =
|
||||||
// 如果标记了需要滑入动画,则执行动画
|
NavigationManager.Instance.getSelectedThemeId().toString();
|
||||||
// 延迟一帧执行动画,确保节点已正确加载到场景中
|
|
||||||
this.scheduleOnce(() => {
|
|
||||||
UITransitionHelper.slideInFromRight(this.node, 0.3);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
// 获取ChatController单例并绑定当前Panel
|
// 获取ChatController单例并绑定当前Panel
|
||||||
this.chatController = ChatController.Instance;
|
this.chatController = ChatController.Instance;
|
||||||
@@ -119,83 +176,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
this.chatController.initialize(this.categoryId, this.id);
|
this.chatController.initialize(this.categoryId, this.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
targetSize;
|
|
||||||
videoAreaPos;
|
|
||||||
onLoadCT() {
|
|
||||||
Utils.parseNode(this.node, this._nodeTab);
|
|
||||||
|
|
||||||
// 获取 videoArea 的尺寸和位置
|
|
||||||
this.targetSize = this.videoArea.contentSize;
|
|
||||||
this.videoAreaPos = new Vec3(540, 1170, 0);
|
|
||||||
|
|
||||||
this.register();
|
|
||||||
this.refresh();
|
|
||||||
this.payToTalkPanel.node.active = false;
|
|
||||||
|
|
||||||
// 检查 SceneBgVideoLayer 是否可用
|
|
||||||
if (!this.videoLayer) {
|
|
||||||
console.error("ChatPanel: SceneBgVideoLayer.handle 未初始化");
|
|
||||||
} else {
|
|
||||||
console.log("ChatPanel: 成功获取 SceneBgVideoLayer 实例");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register() {
|
|
||||||
Utils.addInnerEL(
|
|
||||||
InnerMsgCode.Chat_DialogRefresh,
|
|
||||||
this,
|
|
||||||
this.onDialogUpdate
|
|
||||||
);
|
|
||||||
|
|
||||||
Utils.addInnerEL(
|
|
||||||
InnerMsgCode.LanguageChange,
|
|
||||||
this,
|
|
||||||
this.onLanguageChangeCallback
|
|
||||||
);
|
|
||||||
|
|
||||||
Utils.addInnerEL(
|
|
||||||
InnerMsgCode.Chat_EmotionInitialized,
|
|
||||||
this,
|
|
||||||
this.onEmotionInitialized
|
|
||||||
);
|
|
||||||
|
|
||||||
Utils.addInnerEL(
|
|
||||||
InnerMsgCode.ChatTotalCountChange,
|
|
||||||
this,
|
|
||||||
this.onChatCountChange
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDestroy(): void {
|
|
||||||
Utils.removeInnerEL(
|
|
||||||
InnerMsgCode.Chat_DialogRefresh,
|
|
||||||
this,
|
|
||||||
this.onDialogUpdate
|
|
||||||
);
|
|
||||||
Utils.removeInnerEL(
|
|
||||||
InnerMsgCode.LanguageChange,
|
|
||||||
this,
|
|
||||||
this.onLanguageChangeCallback
|
|
||||||
);
|
|
||||||
Utils.removeInnerEL(
|
|
||||||
InnerMsgCode.ChatTotalCountChange,
|
|
||||||
this,
|
|
||||||
this.onChatCountChange
|
|
||||||
);
|
|
||||||
Utils.removeInnerEL(
|
|
||||||
InnerMsgCode.Chat_EmotionInitialized,
|
|
||||||
this,
|
|
||||||
this.onEmotionInitialized
|
|
||||||
);
|
|
||||||
|
|
||||||
// 解绑ChatController(不销毁,因为它是单例)
|
|
||||||
if (this.chatController) {
|
|
||||||
this.chatController.unbindView();
|
|
||||||
this.chatController = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refresh() {
|
|
||||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
|
|
||||||
this.nameKey = girlData.getGrilName(this.categoryId, this.id);
|
this.nameKey = girlData.getGrilName(this.categoryId, this.id);
|
||||||
@@ -372,6 +353,8 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
}
|
}
|
||||||
protected onEnable(): void {
|
protected onEnable(): void {
|
||||||
if (!this.manager) this.manager = DialogManager.getInstance();
|
if (!this.manager) this.manager = DialogManager.getInstance();
|
||||||
|
|
||||||
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async OnClickSend() {
|
public async OnClickSend() {
|
||||||
@@ -465,11 +448,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
|
|
||||||
returnBtn() {
|
returnBtn() {
|
||||||
// Navigate back to GirlDetailPanel with current girlId using smooth transition
|
// Navigate back to GirlDetailPanel with current girlId using smooth transition
|
||||||
NavigationManager.Instance.navigateToGirlDetail(
|
NavigationManager.Instance.switchToPanel(PanelType.GIRL_DETAIL);
|
||||||
this.id,
|
|
||||||
NavigationManager.getTransitionPresets().SLIDE_RIGHT_TO_LEFT,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
onClickRecord() {
|
onClickRecord() {
|
||||||
ViewManager.I.openBundlesView("RecordPanel", this.id);
|
ViewManager.I.openBundlesView("RecordPanel", this.id);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
|
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
|
||||||
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
||||||
import { DetailImageItem } from "../../uiitems/DetailImageItem";
|
import { DetailImageItem } from "../../uiitems/DetailImageItem";
|
||||||
import { NavigationManager } from "../../manager/NavigationManager";
|
import { NavigationManager, PanelType } from "../../manager/NavigationManager";
|
||||||
import { ConfigManager } from "../../manager/ConfigManager";
|
import { ConfigManager } from "../../manager/ConfigManager";
|
||||||
import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
||||||
import Utils from "../../../Main/Common/Utils";
|
import Utils from "../../../Main/Common/Utils";
|
||||||
@@ -71,36 +71,16 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
@property(Node)
|
@property(Node)
|
||||||
imgsLayout: Node;
|
imgsLayout: Node;
|
||||||
|
|
||||||
openUIDataCT(data) {
|
|
||||||
this.id = data;
|
|
||||||
}
|
|
||||||
videoAreaPos;
|
videoAreaPos;
|
||||||
|
|
||||||
|
protected onEnable(): void {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
onLoadCT() {
|
onLoadCT() {
|
||||||
super.onLoadCT();
|
super.onLoadCT();
|
||||||
this.imgItemInst.node.active = false;
|
|
||||||
this.videoAreaPos = new Vec3(540, 1384);
|
|
||||||
|
|
||||||
const pos = new Vec3(
|
//this.refresh();
|
||||||
this.descContent.position.x,
|
|
||||||
this.descContent.position.y,
|
|
||||||
this.descContent.position.z
|
|
||||||
);
|
|
||||||
this.descContent.position = new Vec3(pos.x, pos.y - 1000, pos.z);
|
|
||||||
//this.node.scale = Vec3.ZERO;
|
|
||||||
tween(this.descContent)
|
|
||||||
.to(0.3, { position: pos }, { easing: "quadOut" })
|
|
||||||
.start();
|
|
||||||
|
|
||||||
// 检查 SceneBgVideoLayer 是否可用
|
|
||||||
if (!this.videoLayer) {
|
|
||||||
console.error("GirlDetailPanel: SceneBgVideoLayer.handle 未初始化");
|
|
||||||
} else {
|
|
||||||
console.log("GirlDetailPanel: 成功获取 SceneBgVideoLayer 实例");
|
|
||||||
// 初始化视频显示位置
|
|
||||||
//this.initVideoPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refresh(this.id);
|
|
||||||
|
|
||||||
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => {
|
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => {
|
||||||
this.girlName.string = LanguageUtils.getText(this.nameKey);
|
this.girlName.string = LanguageUtils.getText(this.nameKey);
|
||||||
@@ -153,7 +133,32 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
tagKey: string;
|
tagKey: string;
|
||||||
descKey: string;
|
descKey: string;
|
||||||
category: number;
|
category: number;
|
||||||
async refresh(index: number) {
|
async refresh() {
|
||||||
|
this.id = NavigationManager.Instance.getSelectedGirlId();
|
||||||
|
|
||||||
|
this.imgItemInst.node.active = false;
|
||||||
|
this.videoAreaPos = new Vec3(540, 1384);
|
||||||
|
|
||||||
|
const pos = new Vec3(
|
||||||
|
this.descContent.position.x,
|
||||||
|
this.descContent.position.y,
|
||||||
|
this.descContent.position.z
|
||||||
|
);
|
||||||
|
this.descContent.position = new Vec3(pos.x, pos.y - 1000, pos.z);
|
||||||
|
//this.node.scale = Vec3.ZERO;
|
||||||
|
tween(this.descContent)
|
||||||
|
.to(0.3, { position: pos }, { easing: "quadOut" })
|
||||||
|
.start();
|
||||||
|
|
||||||
|
// 检查 SceneBgVideoLayer 是否可用
|
||||||
|
if (!this.videoLayer) {
|
||||||
|
console.error("GirlDetailPanel: SceneBgVideoLayer.handle 未初始化");
|
||||||
|
} else {
|
||||||
|
console.log("GirlDetailPanel: 成功获取 SceneBgVideoLayer 实例");
|
||||||
|
// 初始化视频显示位置
|
||||||
|
//this.initVideoPosition();
|
||||||
|
}
|
||||||
|
|
||||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
this.category = girlData.getGrilCategoryById(this.id);
|
this.category = girlData.getGrilCategoryById(this.id);
|
||||||
// 请求详细数据
|
// 请求详细数据
|
||||||
@@ -305,18 +310,11 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
|
|
||||||
OnClickChatBtn() {
|
OnClickChatBtn() {
|
||||||
// 使用带过渡动画的导航方法
|
// 使用带过渡动画的导航方法
|
||||||
NavigationManager.Instance.navigateToChatWithTransition(
|
NavigationManager.Instance.switchToPanel(PanelType.CHAT);
|
||||||
this.category.toString(),
|
|
||||||
this.id,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
// 注意:不在这里直接调用onClose,而是在动画完成后由NavigationManager调用
|
|
||||||
}
|
}
|
||||||
|
|
||||||
returnBtn() {
|
returnBtn() {
|
||||||
this.onClose();
|
NavigationManager.Instance.switchToPanel(PanelType.THEME);
|
||||||
NavigationManager.Instance.navigateToGirlList(this.category);
|
|
||||||
//ViewManager.I.openBundlesView("GirlListPanel");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { GirlData } from "../../data/GirlData";
|
|||||||
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
||||||
import GameRootUI from "../../../Main/Common/GameRootUI";
|
import GameRootUI from "../../../Main/Common/GameRootUI";
|
||||||
import { UITransitionHelper } from "../../utils/UITransitionHelper";
|
import { UITransitionHelper } from "../../utils/UITransitionHelper";
|
||||||
|
import { NavigationManager, PanelType } from "../../manager/NavigationManager";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -23,14 +24,19 @@ export class GirlListPanel extends li_BaseView {
|
|||||||
cache: GirlListItem[] = [];
|
cache: GirlListItem[] = [];
|
||||||
|
|
||||||
category: number;
|
category: number;
|
||||||
openUIDataCT(data) {
|
private parentPanelName: string = null;
|
||||||
// 支持新的数据格式:既可以是单纯的数字,也可以是包含过渡动画信息的对象
|
|
||||||
this.category =
|
|
||||||
typeof data === "object" && data.category !== undefined
|
|
||||||
? data.category
|
|
||||||
: data;
|
|
||||||
|
|
||||||
const withAnimation = typeof data === "object" && data.withTransition;
|
openUIDataCT(data) {
|
||||||
|
console.log("[GirlListPanel] openUIDataCT called with data:", data);
|
||||||
|
|
||||||
|
// 支持新的数据格式:既可以是单纯的数字,也可以是包含主题ID和父页面信息的对象
|
||||||
|
if (typeof data === "object") {
|
||||||
|
this.category = data.themeId;
|
||||||
|
this.parentPanelName = data.parentPanel;
|
||||||
|
console.log("[GirlListPanel] Set parent panel:", this.parentPanelName);
|
||||||
|
} else {
|
||||||
|
this.category = data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onLoadCT() {
|
onLoadCT() {
|
||||||
Utils.parseNode(this.node, this._nodeTab);
|
Utils.parseNode(this.node, this._nodeTab);
|
||||||
@@ -76,37 +82,7 @@ export class GirlListPanel extends li_BaseView {
|
|||||||
GButton.BandClick(this._nodeTab.ReturnBtn, this.Return, this);
|
GButton.BandClick(this._nodeTab.ReturnBtn, this.Return, this);
|
||||||
}
|
}
|
||||||
Return() {
|
Return() {
|
||||||
console.log("GirlListPanel: Return button clicked");
|
// 直接关闭,不需要动画
|
||||||
|
this.node.active = false;
|
||||||
// 执行同步的过渡动画:GirlListPanel向右滑出,ThemePanel从左滑入
|
|
||||||
const duration = 0.1;
|
|
||||||
let animationsCompleted = 0;
|
|
||||||
const totalAnimations = 2;
|
|
||||||
|
|
||||||
const onAnimationComplete = (source: string) => {
|
|
||||||
console.log(`GirlListPanel: Animation completed from ${source}`);
|
|
||||||
animationsCompleted++;
|
|
||||||
console.log(
|
|
||||||
`GirlListPanel: ${animationsCompleted}/${totalAnimations} animations completed`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (animationsCompleted >= totalAnimations) {
|
|
||||||
console.log("GirlListPanel: All animations completed, closing panel");
|
|
||||||
// 所有动画完成后关闭当前面板
|
|
||||||
this.onClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1. GirlListPanel向右滑出
|
|
||||||
console.log("GirlListPanel: Starting slideOutToRight animation");
|
|
||||||
UITransitionHelper.slideOutToRight(this.node, duration, () =>
|
|
||||||
onAnimationComplete("slideOutToRight")
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. ThemePanel从左侧滑入
|
|
||||||
console.log("GirlListPanel: Starting ThemePanel slide_left animation");
|
|
||||||
GameRootUI.I.showDefaultViewWithTransition("slide_left", duration, () =>
|
|
||||||
onAnimationComplete("ThemePanel_slide_left")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
import { _decorator, Component, Label, Node } from "cc";
|
||||||
|
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
|
||||||
|
import Utils from "db://assets/Scripts/Main/Common/Utils";
|
||||||
|
import { GButton } from "db://assets/Scripts/Main/Common/GButton";
|
||||||
|
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
||||||
|
import {
|
||||||
|
NavigationManager,
|
||||||
|
PageTransitionType,
|
||||||
|
PanelType,
|
||||||
|
} from "../../manager/NavigationManager";
|
||||||
|
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
||||||
|
import GameRootUI from "../../../Main/Common/GameRootUI";
|
||||||
|
import { UITransitionHelper } from "../../utils/UITransitionHelper";
|
||||||
|
import { ThemePanel } from "./ThemePanel";
|
||||||
|
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
@ccclass("NavigationPanel")
|
||||||
|
export class NavigationPanel extends li_BaseView {
|
||||||
|
private _nodeTab: any = {};
|
||||||
|
private currentActivePanel: PanelType = PanelType.THEME;
|
||||||
|
|
||||||
|
private themeBtn: Node;
|
||||||
|
private girlDetailBtn: Node;
|
||||||
|
private chatBtn: Node;
|
||||||
|
private settingBtn: Node;
|
||||||
|
|
||||||
|
private loadingView: Node;
|
||||||
|
|
||||||
|
onLoadCT() {
|
||||||
|
Utils.parseNode(this.node, this._nodeTab);
|
||||||
|
|
||||||
|
this.themeBtn = this._nodeTab.themeBtn;
|
||||||
|
this.girlDetailBtn = this._nodeTab.girlDetailBtn;
|
||||||
|
this.chatBtn = this._nodeTab.chatBtn;
|
||||||
|
this.settingBtn = this._nodeTab.settingBtn;
|
||||||
|
this.loadingView = this._nodeTab.loadingView;
|
||||||
|
|
||||||
|
this.hideLoading();
|
||||||
|
|
||||||
|
// 注册到NavigationManager
|
||||||
|
NavigationManager.Instance.registerNavigationPanel(this);
|
||||||
|
|
||||||
|
this.registerListener();
|
||||||
|
this.updateButtonStates(PanelType.THEME);
|
||||||
|
|
||||||
|
// 初次打开时通过NavigationManager切换到主题面板
|
||||||
|
this.initializeFirstPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerListener() {
|
||||||
|
// 所有按钮点击都通过NavigationManager处理
|
||||||
|
GButton.BandClick(
|
||||||
|
this.themeBtn,
|
||||||
|
() => NavigationManager.Instance.switchToPanel(PanelType.THEME),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
GButton.BandClick(
|
||||||
|
this.girlDetailBtn,
|
||||||
|
() => NavigationManager.Instance.switchToPanel(PanelType.GIRL_DETAIL),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
GButton.BandClick(
|
||||||
|
this.chatBtn,
|
||||||
|
() => NavigationManager.Instance.switchToPanel(PanelType.CHAT),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
GButton.BandClick(
|
||||||
|
this.settingBtn,
|
||||||
|
() => NavigationManager.Instance.switchToPanel(PanelType.SETTING),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新按钮状态(公开方法,供NavigationManager调用)
|
||||||
|
* @param activePanel 当前激活的面板类型
|
||||||
|
*/
|
||||||
|
public updateButtonStates(activePanel: PanelType) {
|
||||||
|
this.currentActivePanel = activePanel;
|
||||||
|
this._nodeTab.CurrentPanel.getComponent(Label).string =
|
||||||
|
this.currentActivePanel;
|
||||||
|
this.refreshButtonVisuals();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新按钮的视觉状态
|
||||||
|
*/
|
||||||
|
private refreshButtonVisuals() {
|
||||||
|
// TODO: 实现按钮状态更新的视觉效果
|
||||||
|
// 根据 currentActivePanel 更新按钮的选中状态
|
||||||
|
console.log(
|
||||||
|
"[NavigationPanel] Button states updated for:",
|
||||||
|
this.currentActivePanel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeFirstPanel() {
|
||||||
|
// 初次打开时通过NavigationManager切换到主题面板
|
||||||
|
NavigationManager.Instance.switchToPanel(PanelType.THEME, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public showPanel() {
|
||||||
|
this.node.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public hidePanel() {
|
||||||
|
this.node.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示加载状态(公开方法,供NavigationManager调用)
|
||||||
|
*/
|
||||||
|
public showLoading() {
|
||||||
|
if (this.loadingView) {
|
||||||
|
this.loadingView.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏加载状态(公开方法,供NavigationManager调用)
|
||||||
|
*/
|
||||||
|
public hideLoading() {
|
||||||
|
if (this.loadingView) {
|
||||||
|
this.loadingView.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy(): void {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "58d92549-54a9-4f98-94af-5c0c3ac2f853",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -78,7 +78,7 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
this._nodeTab.ReturnBtn,
|
this._nodeTab.ReturnBtn,
|
||||||
() => {
|
() => {
|
||||||
this.onClose();
|
this.onClose();
|
||||||
GameRootUI.I.showDefaultView();
|
// NavigationPanel 始终显示,不需要显示 DefaultView
|
||||||
},
|
},
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ export class RecordPanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onEnable(): void {
|
protected onEnable(): void {
|
||||||
GameRootUI.I.hideDefaultView();
|
// NavigationPanel 始终显示,不需要隐藏 DefaultView
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import Utils from "db://assets/Scripts/Main/Common/Utils";
|
|||||||
import { GButton } from "db://assets/Scripts/Main/Common/GButton";
|
import { GButton } from "db://assets/Scripts/Main/Common/GButton";
|
||||||
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
||||||
import { ThemeItem } from "../../uiitems/ThemeItem";
|
import { ThemeItem } from "../../uiitems/ThemeItem";
|
||||||
import { NavigationManager, PageTransitionType } from "../../manager/NavigationManager";
|
import {
|
||||||
|
NavigationManager,
|
||||||
|
PageTransitionType,
|
||||||
|
PanelType,
|
||||||
|
} from "../../manager/NavigationManager";
|
||||||
import { GirlListItem } from "../../uiitems/GirlListItem";
|
import { GirlListItem } from "../../uiitems/GirlListItem";
|
||||||
import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
||||||
import { ViewManager } from "../../../Main/Manager/ViewManager";
|
import { ViewManager } from "../../../Main/Manager/ViewManager";
|
||||||
@@ -29,6 +33,7 @@ import { AccountData } from "../../data/AccountData";
|
|||||||
import { ShopData } from "../../data/ShopData";
|
import { ShopData } from "../../data/ShopData";
|
||||||
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
||||||
import GameRootUI from "../../../Main/Common/GameRootUI";
|
import GameRootUI from "../../../Main/Common/GameRootUI";
|
||||||
|
import { MainController } from "../../core/MainController";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -38,7 +43,7 @@ export class ThemePanel extends li_BaseView {
|
|||||||
|
|
||||||
coinNum: Label;
|
coinNum: Label;
|
||||||
uid: Label;
|
uid: Label;
|
||||||
itemInst: GirlListItem;
|
itemInst: ThemeItem;
|
||||||
content: Node;
|
content: Node;
|
||||||
private vipLeftTime: Label;
|
private vipLeftTime: Label;
|
||||||
recId: number;
|
recId: number;
|
||||||
@@ -47,6 +52,14 @@ export class ThemePanel extends li_BaseView {
|
|||||||
|
|
||||||
cache: ThemeItem[] = [];
|
cache: ThemeItem[] = [];
|
||||||
|
|
||||||
|
// 子页面管理
|
||||||
|
private currentChildPanel: any = null;
|
||||||
|
|
||||||
|
// 加载状态保护
|
||||||
|
private isLoading: boolean = false;
|
||||||
|
private loadingPromise: Promise<void> | null = null;
|
||||||
|
private abortController: AbortController | null = null;
|
||||||
|
|
||||||
onLoadCT() {
|
onLoadCT() {
|
||||||
Utils.parseNode(this.node, this._nodeTab);
|
Utils.parseNode(this.node, this._nodeTab);
|
||||||
|
|
||||||
@@ -65,67 +78,206 @@ export class ThemePanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rectNameKey: string;
|
rectNameKey: string;
|
||||||
async Show() {
|
async Show(forceRefresh: boolean = false) {
|
||||||
this._nodeTab.loadingRec.active = true;
|
// 防止重复加载
|
||||||
//some temp data
|
if (this.isLoading) {
|
||||||
this.refreshCoinNum();
|
console.log("[ThemePanel] 已在加载中,等待当前加载完成");
|
||||||
this.refreshVipExpire();
|
if (this.loadingPromise) {
|
||||||
const accountData = DataManager.I.getDataById<AccountData>(DataId.Account);
|
await this.loadingPromise;
|
||||||
this.uid.string = "uid: " + accountData.accId;
|
}
|
||||||
this.recId = 1;
|
return;
|
||||||
if (this.cache) {
|
}
|
||||||
for (let i = this.cache.length - 1; i >= 0; i--) {
|
|
||||||
this.cache[i].node.destroy();
|
this.isLoading = true;
|
||||||
|
this.loadingPromise = this._showInternal(forceRefresh);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.loadingPromise;
|
||||||
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.loadingPromise = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _showInternal(forceRefresh: boolean = false) {
|
||||||
|
// 创建新的AbortController用于取消操作
|
||||||
|
this.abortController = new AbortController();
|
||||||
|
const signal = this.abortController.signal;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._nodeTab.loadingRec.active = true;
|
||||||
|
//some temp data
|
||||||
|
this.refreshCoinNum();
|
||||||
|
this.refreshVipExpire();
|
||||||
|
const accountData = DataManager.I.getDataById<AccountData>(
|
||||||
|
DataId.Account
|
||||||
|
);
|
||||||
|
this.uid.string = "uid: " + accountData.accId;
|
||||||
|
this.recId = 1;
|
||||||
|
|
||||||
|
// 检查是否已被取消
|
||||||
|
if (signal.aborted) {
|
||||||
|
throw new Error("Operation was aborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理旧的cache节点(每次都清理,解决内存泄漏问题)
|
||||||
|
this.clearCache();
|
||||||
|
|
||||||
|
// 如果需要强制刷新,先刷新数据
|
||||||
|
if (forceRefresh) {
|
||||||
|
console.log("[ThemePanel] 开始强制刷新数据");
|
||||||
|
await Promise.all([
|
||||||
|
MainController.I.refreshThemeData(),
|
||||||
|
MainController.I.refreshDailyRecommend(),
|
||||||
|
]);
|
||||||
|
console.log("[ThemePanel] 数据刷新完成");
|
||||||
|
|
||||||
|
// 再次检查是否已被取消
|
||||||
|
if (signal.aborted) {
|
||||||
|
throw new Error("Operation was aborted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先使用MainController中预加载的数据
|
||||||
|
const preloadStatus = MainController.I.getPreloadStatus();
|
||||||
|
console.log("[ThemePanel] 预加载状态:", preloadStatus);
|
||||||
|
|
||||||
|
// 处理主题数据
|
||||||
|
await this.handleThemeData(preloadStatus.themeData);
|
||||||
|
|
||||||
|
// 检查是否已被取消
|
||||||
|
if (signal.aborted) {
|
||||||
|
throw new Error("Operation was aborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理每日推荐数据
|
||||||
|
await this.handleDailyRecommendData(preloadStatus.dailyRecommend);
|
||||||
|
|
||||||
|
// 检查是否已被取消
|
||||||
|
if (signal.aborted) {
|
||||||
|
throw new Error("Operation was aborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
this._nodeTab.loadingRec.active = false;
|
||||||
|
|
||||||
|
// 处理商品列表数据
|
||||||
|
await this.handleShopListData(preloadStatus.shopList);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[ThemePanel] Show操作出错:", error);
|
||||||
|
this._nodeTab.loadingRec.active = false;
|
||||||
|
|
||||||
|
// 如果不是取消操作导致的错误,可以考虑显示错误提示
|
||||||
|
if (error.message !== "Operation was aborted") {
|
||||||
|
// 这里可以添加错误提示逻辑
|
||||||
|
console.error("[ThemePanel] 数据加载失败,请稍后重试");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.abortController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理主题数据
|
||||||
|
*/
|
||||||
|
private async handleThemeData(isPreloaded: boolean): Promise<void> {
|
||||||
|
if (isPreloaded) {
|
||||||
|
console.log("[ThemePanel] 使用预加载的主题数据");
|
||||||
|
// 直接使用预加载的数据渲染界面
|
||||||
|
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
|
||||||
|
if (themeData && themeData.themes) {
|
||||||
|
this.renderThemeData(themeData);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 请求主题数据
|
|
||||||
|
// 如果没有预加载数据,则请求数据
|
||||||
|
console.log("[ThemePanel] 请求主题数据");
|
||||||
const reqData = {};
|
const reqData = {};
|
||||||
let res = await ThemeService.I.reqHallTheme(reqData);
|
let res = await ThemeService.I.reqHallTheme(reqData);
|
||||||
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
// 保存数据
|
// 保存数据
|
||||||
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
|
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
|
||||||
themeData.themes = res.data;
|
themeData.themes = res.data;
|
||||||
// 根据数据,刷新界面
|
this.renderThemeData(themeData);
|
||||||
const themeIds = themeData.themeIds;
|
}
|
||||||
for (let id of themeIds) {
|
}
|
||||||
let newNode = instantiate(this.itemInst.node);
|
|
||||||
let item = newNode.getComponent(ThemeItem);
|
/**
|
||||||
item.refresh(id, this);
|
* 渲染主题数据
|
||||||
newNode.active = true;
|
*/
|
||||||
this.cache.push(item);
|
private renderThemeData(themeData: ThemeData): void {
|
||||||
this.content.addChild(newNode);
|
const themeIds = themeData.themeIds;
|
||||||
|
for (let id of themeIds) {
|
||||||
|
let newNode = instantiate(this.itemInst.node);
|
||||||
|
let item = newNode.getComponent(ThemeItem);
|
||||||
|
item.refresh(id, this);
|
||||||
|
newNode.active = true;
|
||||||
|
this.cache.push(item);
|
||||||
|
this.content.addChild(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理每日推荐数据
|
||||||
|
*/
|
||||||
|
private async handleDailyRecommendData(isPreloaded: boolean): Promise<void> {
|
||||||
|
if (isPreloaded) {
|
||||||
|
console.log("[ThemePanel] 使用预加载的每日推荐数据");
|
||||||
|
// 直接使用预加载的数据渲染界面
|
||||||
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
|
if (girlData) {
|
||||||
|
this.renderDailyRecommendData(girlData);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求每日推荐
|
// 如果没有预加载数据,则请求数据
|
||||||
const reqData2 = {};
|
console.log("[ThemePanel] 请求每日推荐数据");
|
||||||
let res2 = await GirlService.I.reqDailyRecommend(reqData2);
|
const reqData = {};
|
||||||
if (res2 && res2.code === proto.cs.EnmRetCode.SUCCESS) {
|
let res = await GirlService.I.reqDailyRecommend(reqData);
|
||||||
|
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
girlData.setDailyRecommend(res2.data);
|
girlData.setDailyRecommend(res.data);
|
||||||
// 根据数据,刷新界面
|
this.renderDailyRecommendData(girlData);
|
||||||
this.recId = girlData.getRecommendGirlId();
|
|
||||||
this.rectNameKey = girlData.getRecommendGrilName();
|
|
||||||
let avatarPath = girlData.getRecommendGrilAvatar();
|
|
||||||
this.recName.string = LanguageUtils.getText(this.rectNameKey);
|
|
||||||
ResManager.I.changeBundleSpriteFrame(
|
|
||||||
this.recSprite,
|
|
||||||
avatarPath,
|
|
||||||
"Girls",
|
|
||||||
() => {
|
|
||||||
let sizeTran = this.recSprite.node.parent.getComponent(UITransform);
|
|
||||||
Utils.adjustBgPixelRatioToSize(
|
|
||||||
sizeTran.contentSize,
|
|
||||||
this.recSprite.node,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this._nodeTab.loadingRec.active = false;
|
}
|
||||||
|
|
||||||
// 获取商品列表,提前把数据拿下来
|
/**
|
||||||
this.reqShopList();
|
* 渲染每日推荐数据
|
||||||
|
*/
|
||||||
|
private renderDailyRecommendData(girlData: GirlData): void {
|
||||||
|
this.recId = girlData.getRecommendGirlId();
|
||||||
|
this.rectNameKey = girlData.getRecommendGrilName();
|
||||||
|
let avatarPath = girlData.getRecommendGrilAvatar();
|
||||||
|
this.recName.string = LanguageUtils.getText(this.rectNameKey);
|
||||||
|
ResManager.I.changeBundleSpriteFrame(
|
||||||
|
this.recSprite,
|
||||||
|
avatarPath,
|
||||||
|
"Girls",
|
||||||
|
() => {
|
||||||
|
let sizeTran = this.recSprite.node.parent.getComponent(UITransform);
|
||||||
|
Utils.adjustBgPixelRatioToSize(
|
||||||
|
sizeTran.contentSize,
|
||||||
|
this.recSprite.node,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理商品列表数据
|
||||||
|
*/
|
||||||
|
private async handleShopListData(isPreloaded: boolean): Promise<void> {
|
||||||
|
if (isPreloaded) {
|
||||||
|
console.log("[ThemePanel] 商品列表数据已预加载");
|
||||||
|
// 数据已经在DataManager中,不需要额外处理
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有预加载数据,则请求数据
|
||||||
|
console.log("[ThemePanel] 请求商品列表数据");
|
||||||
|
await this.reqShopList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerListener() {
|
private registerListener() {
|
||||||
@@ -136,15 +288,13 @@ export class ThemePanel extends li_BaseView {
|
|||||||
|
|
||||||
GButton.BandClick(this._nodeTab.ShopPanelEntry, this.enterShop, this);
|
GButton.BandClick(this._nodeTab.ShopPanelEntry, this.enterShop, this);
|
||||||
|
|
||||||
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => {
|
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, this.onLanguageChange);
|
||||||
this.recName.string = LanguageUtils.getText(this.rectNameKey);
|
Utils.addInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
||||||
});
|
Utils.addInnerEL(
|
||||||
Utils.addInnerEL(InnerMsgCode.BalanceChange, this, () => {
|
InnerMsgCode.VipExpireChange,
|
||||||
this.refreshCoinNum();
|
this,
|
||||||
});
|
this.onVipExpireChange
|
||||||
Utils.addInnerEL(InnerMsgCode.VipExpireChange, this, () => {
|
);
|
||||||
this.refreshVipExpire();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enterShop() {
|
enterShop() {
|
||||||
@@ -165,9 +315,11 @@ export class ThemePanel extends li_BaseView {
|
|||||||
this.recId
|
this.recId
|
||||||
) == 0;
|
) == 0;
|
||||||
if (isRelease || isFree) {
|
if (isRelease || isFree) {
|
||||||
const transitionConfig = NavigationManager.getTransitionPresets().SLIDE_LEFT_TO_RIGHT;
|
NavigationManager.Instance.setSelectedGirlId(this.recId);
|
||||||
NavigationManager.Instance.navigateToGirlDetail(this.recId, transitionConfig, this);
|
NavigationManager.Instance.setSelectedThemeId(
|
||||||
GameRootUI.I.hideDefaultView();
|
girlData.getGrilCategoryById(this.recId)
|
||||||
|
);
|
||||||
|
NavigationManager.Instance.switchToPanel(PanelType.GIRL_DETAIL);
|
||||||
} else {
|
} else {
|
||||||
//未解锁
|
//未解锁
|
||||||
ViewManager.I.openBundlesPopupView("GirlListPopupPanel", {
|
ViewManager.I.openBundlesPopupView("GirlListPopupPanel", {
|
||||||
@@ -179,7 +331,8 @@ export class ThemePanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openSetting() {
|
openSetting() {
|
||||||
ViewManager.I.openBundlesView("SettingPanel");
|
// 通过NavigationManager切换到设置面板,保持动画和状态同步
|
||||||
|
NavigationManager.Instance.switchToPanel(PanelType.SETTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
openMsgBox() {
|
openMsgBox() {
|
||||||
@@ -216,11 +369,107 @@ export class ThemePanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy(): void {
|
/**
|
||||||
Utils.removeInnerEL(InnerMsgCode.LanguageChange, this, () => {
|
* 清理缓存节点
|
||||||
this.recName.string = LanguageUtils.getText(this.rectNameKey);
|
*/
|
||||||
});
|
private clearCache(): void {
|
||||||
Utils.removeInnerEL(InnerMsgCode.BalanceChange, this, () => {});
|
if (this.cache && this.cache.length > 0) {
|
||||||
Utils.removeInnerEL(InnerMsgCode.VipExpireChange, this, () => {});
|
console.log(`[ThemePanel] 清理 ${this.cache.length} 个缓存节点`);
|
||||||
|
for (let i = this.cache.length - 1; i >= 0; i--) {
|
||||||
|
if (this.cache[i] && this.cache[i].node && this.cache[i].node.isValid) {
|
||||||
|
this.cache[i].node.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cache = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置子页面
|
||||||
|
* @param panel 子页面实例
|
||||||
|
*/
|
||||||
|
public setChildPanel(panel: any): void {
|
||||||
|
console.log("[ThemePanel] Setting child panel:", panel);
|
||||||
|
// 先关闭旧的子页面
|
||||||
|
this.closeChildPanel();
|
||||||
|
this.currentChildPanel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭子页面
|
||||||
|
*/
|
||||||
|
public closeChildPanel(): void {
|
||||||
|
if (this.currentChildPanel) {
|
||||||
|
console.log("[ThemePanel] Closing child panel");
|
||||||
|
if (this.currentChildPanel.onClose) {
|
||||||
|
this.currentChildPanel.onClose();
|
||||||
|
} else if (this.currentChildPanel.destroy) {
|
||||||
|
this.currentChildPanel.destroy();
|
||||||
|
}
|
||||||
|
this.currentChildPanel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面被隐藏时调用
|
||||||
|
*/
|
||||||
|
public onHide(): void {
|
||||||
|
console.log("[ThemePanel] onHide called");
|
||||||
|
this.closeChildPanel();
|
||||||
|
this.cancelCurrentOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消当前操作
|
||||||
|
*/
|
||||||
|
private cancelCurrentOperation(): void {
|
||||||
|
if (this.abortController) {
|
||||||
|
console.log("[ThemePanel] 取消当前操作");
|
||||||
|
this.abortController.abort();
|
||||||
|
this.abortController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy(): void {
|
||||||
|
console.log("[ThemePanel] onDestroy called");
|
||||||
|
|
||||||
|
// 取消当前操作
|
||||||
|
this.cancelCurrentOperation();
|
||||||
|
|
||||||
|
// 关闭子页面
|
||||||
|
this.closeChildPanel();
|
||||||
|
|
||||||
|
// 清理缓存
|
||||||
|
this.clearCache();
|
||||||
|
|
||||||
|
// 重置加载状态
|
||||||
|
this.isLoading = false;
|
||||||
|
this.loadingPromise = null;
|
||||||
|
|
||||||
|
// 移除事件监听器(修复回调函数引用问题)
|
||||||
|
Utils.removeInnerEL(
|
||||||
|
InnerMsgCode.LanguageChange,
|
||||||
|
this,
|
||||||
|
this.onLanguageChange
|
||||||
|
);
|
||||||
|
Utils.removeInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
||||||
|
Utils.removeInnerEL(
|
||||||
|
InnerMsgCode.VipExpireChange,
|
||||||
|
this,
|
||||||
|
this.onVipExpireChange
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件回调函数(避免匿名函数导致的内存泄漏)
|
||||||
|
private onLanguageChange = () => {
|
||||||
|
this.recName.string = LanguageUtils.getText(this.rectNameKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
private onBalanceChange = () => {
|
||||||
|
this.refreshCoinNum();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onVipExpireChange = () => {
|
||||||
|
this.refreshVipExpire();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,9 @@ export class DetailImageItem extends Component {
|
|||||||
resId: number;
|
resId: number;
|
||||||
type: proto.cs.EnmResType;
|
type: proto.cs.EnmResType;
|
||||||
|
|
||||||
test_resID: Node;
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
GButton.BandClick(this.node, this.onClickThis, this);
|
GButton.BandClick(this.node, this.onClickThis, this);
|
||||||
this.uitransform = this.node.getComponent(UITransform);
|
this.uitransform = this.node.getComponent(UITransform);
|
||||||
this.test_resID.active = false;
|
|
||||||
}
|
}
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
onClickThis() {
|
onClickThis() {
|
||||||
@@ -146,10 +144,6 @@ export class DetailImageItem extends Component {
|
|||||||
//this.question.active = true; // 显示问号,表示加载中
|
//this.question.active = true; // 显示问号,表示加载中
|
||||||
|
|
||||||
this.loading.active = true;
|
this.loading.active = true;
|
||||||
this.test_resID = this.node.getChildByName("resID");
|
|
||||||
|
|
||||||
this.test_resID.getComponent(Label).string =
|
|
||||||
this.girlId.toString() + this.resId;
|
|
||||||
|
|
||||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||||
let imgPath = "";
|
let imgPath = "";
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { Config18x } from "db://assets/Scripts/Main/Config/Config18x";
|
|||||||
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
||||||
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
||||||
import Utils from "db://assets/Scripts/Main/Common/Utils";
|
import Utils from "db://assets/Scripts/Main/Common/Utils";
|
||||||
import { NavigationManager } from "../manager/NavigationManager";
|
import { NavigationManager, PanelType } from "../manager/NavigationManager";
|
||||||
import { PriceType } from "../../schema/schema";
|
import { PriceType } from "../../schema/schema";
|
||||||
import LanguageUtils from "../../Main/Common/LanguageUtils";
|
import LanguageUtils from "../../Main/Common/LanguageUtils";
|
||||||
import { InnerMsgCode } from "../../Main/Config/InnerMsgCode";
|
import { InnerMsgCode } from "../../Main/Config/InnerMsgCode";
|
||||||
@@ -134,10 +134,7 @@ export class GirlListItem extends Component {
|
|||||||
// this.price.node.active = priceType == PriceType.pay;
|
// this.price.node.active = priceType == PriceType.pay;
|
||||||
// this.freeNode.active = priceType == PriceType.free;
|
// this.freeNode.active = priceType == PriceType.free;
|
||||||
//this.tryNode.active = priceType == PriceType.first_time_free;
|
//this.tryNode.active = priceType == PriceType.first_time_free;
|
||||||
let avatarPath = girlData.getGrilAvatar(
|
let avatarPath = girlData.getGrilAvatar(this.category.toString(), this.id);
|
||||||
this.category.toString(),
|
|
||||||
this.id
|
|
||||||
);
|
|
||||||
this.loading.active = true;
|
this.loading.active = true;
|
||||||
|
|
||||||
//listAvatarPath = listAvatarPath.replace("Avatar", "avatar"); //临时
|
//listAvatarPath = listAvatarPath.replace("Avatar", "avatar"); //临时
|
||||||
@@ -182,8 +179,11 @@ export class GirlListItem extends Component {
|
|||||||
// 是否已经解锁
|
// 是否已经解锁
|
||||||
const isRelease = girlData.getIsRelease(this.category.toString(), this.id);
|
const isRelease = girlData.getIsRelease(this.category.toString(), this.id);
|
||||||
if (isRelease) {
|
if (isRelease) {
|
||||||
NavigationManager.Instance.navigateToGirlDetail(this.id);
|
// 先设置选中的角色ID
|
||||||
ViewManager.I.closeView(this.baseNode);
|
NavigationManager.Instance.setSelectedGirlId(this.id);
|
||||||
|
|
||||||
|
// 通过switchToPanel切换到角色详情面板,保持动画和状态同步
|
||||||
|
NavigationManager.Instance.switchToPanel(PanelType.GIRL_DETAIL);
|
||||||
} else {
|
} else {
|
||||||
//未解锁
|
//未解锁
|
||||||
ViewManager.I.openBundlesPopupView("GirlListPopupPanel", {
|
ViewManager.I.openBundlesPopupView("GirlListPopupPanel", {
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ export class ThemeItem extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用预设的过渡动画配置
|
console.log("[ThemeItem] Opening GirlListPanel for category:", this.category);
|
||||||
const transitionConfig = NavigationManager.getTransitionPresets().SLIDE_LEFT_TO_RIGHT;
|
// 不使用过渡动画,直接打开
|
||||||
NavigationManager.Instance.navigateToGirlList(this.category, transitionConfig, this.parentPanel);
|
NavigationManager.Instance.navigateToGirlList(this.category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const { ccclass, property } = _decorator;
|
|||||||
@ccclass("UITransitionHelper")
|
@ccclass("UITransitionHelper")
|
||||||
export class UITransitionHelper {
|
export class UITransitionHelper {
|
||||||
/**
|
/**
|
||||||
* 让节点从右侧滑入到原位置
|
* 让节点从右侧滑入到屏幕中心
|
||||||
*
|
*
|
||||||
* @param {Node} node - 要执行动画的节点
|
* @param {Node} node - 要执行动画的节点
|
||||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||||
@@ -21,7 +21,7 @@ export class UITransitionHelper {
|
|||||||
*/
|
*/
|
||||||
public static slideInFromRight(
|
public static slideInFromRight(
|
||||||
node: Node,
|
node: Node,
|
||||||
duration: number = 0.1,
|
duration: number = 0.3,
|
||||||
callback?: Function
|
callback?: Function
|
||||||
): void {
|
): void {
|
||||||
if (!node || !node.isValid) {
|
if (!node || !node.isValid) {
|
||||||
@@ -30,18 +30,18 @@ export class UITransitionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const screenWidth = view.getVisibleSize().width;
|
const screenWidth = view.getVisibleSize().width;
|
||||||
const originalPosition = node.getPosition();
|
const targetPosition = new Vec3(0, 0, 0);
|
||||||
|
|
||||||
// 设置初始位置为屏幕右侧外
|
// 设置初始位置为屏幕右侧外
|
||||||
node.setPosition(screenWidth, originalPosition.y, originalPosition.z);
|
node.setPosition(screenWidth, 0, 0);
|
||||||
|
|
||||||
// 执行滑入动画
|
// 执行滑入动画到屏幕中心
|
||||||
tween(node)
|
tween(node)
|
||||||
.to(
|
.to(
|
||||||
duration,
|
duration,
|
||||||
{ position: originalPosition },
|
{ position: targetPosition },
|
||||||
{
|
{
|
||||||
easing: "linear",
|
easing: "cubicOut",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.call(() => {
|
.call(() => {
|
||||||
@@ -61,7 +61,7 @@ export class UITransitionHelper {
|
|||||||
*/
|
*/
|
||||||
public static slideOutToLeft(
|
public static slideOutToLeft(
|
||||||
node: Node,
|
node: Node,
|
||||||
duration: number = 0.1,
|
duration: number = 0.3,
|
||||||
callback?: Function
|
callback?: Function
|
||||||
): void {
|
): void {
|
||||||
if (!node || !node.isValid) {
|
if (!node || !node.isValid) {
|
||||||
@@ -83,7 +83,7 @@ export class UITransitionHelper {
|
|||||||
duration,
|
duration,
|
||||||
{ position: targetPosition },
|
{ position: targetPosition },
|
||||||
{
|
{
|
||||||
easing: "linear",
|
easing: "cubicOut",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.call(() => {
|
.call(() => {
|
||||||
@@ -95,7 +95,7 @@ export class UITransitionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让节点从左侧滑入到原位置
|
* 让节点从左侧滑入到屏幕中心
|
||||||
*
|
*
|
||||||
* @param {Node} node - 要执行动画的节点
|
* @param {Node} node - 要执行动画的节点
|
||||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||||
@@ -103,7 +103,7 @@ export class UITransitionHelper {
|
|||||||
*/
|
*/
|
||||||
public static slideInFromLeft(
|
public static slideInFromLeft(
|
||||||
node: Node,
|
node: Node,
|
||||||
duration: number = 0.1,
|
duration: number = 0.3,
|
||||||
callback?: Function
|
callback?: Function
|
||||||
): void {
|
): void {
|
||||||
if (!node || !node.isValid) {
|
if (!node || !node.isValid) {
|
||||||
@@ -112,18 +112,18 @@ export class UITransitionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const screenWidth = view.getVisibleSize().width;
|
const screenWidth = view.getVisibleSize().width;
|
||||||
const originalPosition = node.getPosition();
|
const targetPosition = new Vec3(0, 0, 0);
|
||||||
|
|
||||||
// 设置初始位置为屏幕左侧外
|
// 设置初始位置为屏幕左侧外
|
||||||
node.setPosition(-screenWidth, originalPosition.y, originalPosition.z);
|
node.setPosition(-screenWidth, 0, 0);
|
||||||
|
|
||||||
// 执行滑入动画
|
// 执行滑入动画到屏幕中心
|
||||||
tween(node)
|
tween(node)
|
||||||
.to(
|
.to(
|
||||||
duration,
|
duration,
|
||||||
{ position: originalPosition },
|
{ position: targetPosition },
|
||||||
{
|
{
|
||||||
easing: "linear",
|
easing: "cubicOut",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.call(() => {
|
.call(() => {
|
||||||
@@ -143,7 +143,7 @@ export class UITransitionHelper {
|
|||||||
*/
|
*/
|
||||||
public static slideOutToRight(
|
public static slideOutToRight(
|
||||||
node: Node,
|
node: Node,
|
||||||
duration: number = 0.1,
|
duration: number = 0.3,
|
||||||
callback?: Function
|
callback?: Function
|
||||||
): void {
|
): void {
|
||||||
if (!node || !node.isValid) {
|
if (!node || !node.isValid) {
|
||||||
@@ -165,7 +165,7 @@ export class UITransitionHelper {
|
|||||||
duration,
|
duration,
|
||||||
{ position: targetPosition },
|
{ position: targetPosition },
|
||||||
{
|
{
|
||||||
easing: "linear",
|
easing: "cubicOut",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.call(() => {
|
.call(() => {
|
||||||
|
|||||||
@@ -24,21 +24,21 @@
|
|||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
|
||||||
"__id__": 250
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 252
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__id__": 254
|
"__id__": 254
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 256
|
"__id__": 256
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 258
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 260
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 258
|
"__id__": 262
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
@@ -87,18 +87,18 @@
|
|||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
|
||||||
"__id__": 243
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 245
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__id__": 247
|
"__id__": 247
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 249
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 251
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 249
|
"__id__": 253
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
@@ -4847,23 +4847,23 @@
|
|||||||
"__id__": 215
|
"__id__": 215
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 226
|
"__id__": 230
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
|
||||||
"__id__": 236
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 238
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__id__": 240
|
"__id__": 240
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 242
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 244
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 242
|
"__id__": 246
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
@@ -4902,29 +4902,80 @@
|
|||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 214
|
"__id__": 214
|
||||||
},
|
},
|
||||||
|
"_children": [
|
||||||
|
{
|
||||||
|
"__id__": 216
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 222
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 224
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 227
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 229
|
||||||
|
},
|
||||||
|
"_lpos": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": -461.576,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_lrot": {
|
||||||
|
"__type__": "cc.Quat",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0,
|
||||||
|
"w": 1
|
||||||
|
},
|
||||||
|
"_lscale": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"_mobility": 0,
|
||||||
|
"_layer": 33554432,
|
||||||
|
"_euler": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "ReturnBtn-001",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"__editorExtras__": {},
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 215
|
||||||
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 216
|
"__id__": 217
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 218
|
"__id__": 219
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 220
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 223
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 225
|
"__id__": 221
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
"x": -501.576,
|
"x": 0,
|
||||||
"y": -28,
|
"y": 0,
|
||||||
"z": 0
|
"z": 0
|
||||||
},
|
},
|
||||||
"_lrot": {
|
"_lrot": {
|
||||||
@@ -4956,11 +5007,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 215
|
"__id__": 216
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 217
|
"__id__": 218
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
@@ -4969,14 +5020,14 @@
|
|||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0,
|
"x": 0.5,
|
||||||
"y": 0
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.CompPrefabInfo",
|
"__type__": "cc.CompPrefabInfo",
|
||||||
"fileId": "e3DPaLU6tFXaqz8O6OhQu4"
|
"fileId": "77E3QqK6FDnqFZXpMsO08C"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Sprite",
|
||||||
@@ -4984,11 +5035,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 215
|
"__id__": 216
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 219
|
"__id__": 220
|
||||||
},
|
},
|
||||||
"_customMaterial": null,
|
"_customMaterial": null,
|
||||||
"_srcBlendFactor": 2,
|
"_srcBlendFactor": 2,
|
||||||
@@ -5021,7 +5072,48 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.CompPrefabInfo",
|
"__type__": "cc.CompPrefabInfo",
|
||||||
"fileId": "131aSg7zxBsY4wDl+1ujCV"
|
"fileId": "15k1EffxNH2KONVjTgyIXN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__id__": 0
|
||||||
|
},
|
||||||
|
"fileId": "9aCRghG1lBCa+25qEAugAS",
|
||||||
|
"instance": null,
|
||||||
|
"targetOverrides": null,
|
||||||
|
"nestedPrefabInstanceRoots": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.UITransform",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"__editorExtras__": {},
|
||||||
|
"node": {
|
||||||
|
"__id__": 215
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"__prefab": {
|
||||||
|
"__id__": 223
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 100,
|
||||||
|
"height": 100
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.CompPrefabInfo",
|
||||||
|
"fileId": "e3DPaLU6tFXaqz8O6OhQu4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Button",
|
"__type__": "cc.Button",
|
||||||
@@ -5033,11 +5125,11 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 221
|
"__id__": 225
|
||||||
},
|
},
|
||||||
"clickEvents": [
|
"clickEvents": [
|
||||||
{
|
{
|
||||||
"__id__": 222
|
"__id__": 226
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_interactable": true,
|
"_interactable": true,
|
||||||
@@ -5092,7 +5184,7 @@
|
|||||||
},
|
},
|
||||||
"component": "",
|
"component": "",
|
||||||
"_componentId": "ecf27717xFOIo8F0ultYqJq",
|
"_componentId": "ecf27717xFOIo8F0ultYqJq",
|
||||||
"handler": "close",
|
"handler": "Return",
|
||||||
"customEventData": ""
|
"customEventData": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -5105,11 +5197,11 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 224
|
"__id__": 228
|
||||||
},
|
},
|
||||||
"_alignFlags": 10,
|
"_alignFlags": 10,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
"_left": 38.42399999999998,
|
"_left": 28.423999999999978,
|
||||||
"_right": 0,
|
"_right": 0,
|
||||||
"_top": 55.16199999999981,
|
"_top": 55.16199999999981,
|
||||||
"_bottom": 30,
|
"_bottom": 30,
|
||||||
@@ -5155,21 +5247,21 @@
|
|||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
|
||||||
"__id__": 227
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 229
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__id__": 231
|
"__id__": 231
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 233
|
"__id__": 233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 235
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 237
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 235
|
"__id__": 239
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
@@ -5206,11 +5298,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 226
|
"__id__": 230
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 228
|
"__id__": 232
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
@@ -5234,11 +5326,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 226
|
"__id__": 230
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 230
|
"__id__": 234
|
||||||
},
|
},
|
||||||
"_customMaterial": null,
|
"_customMaterial": null,
|
||||||
"_srcBlendFactor": 2,
|
"_srcBlendFactor": 2,
|
||||||
@@ -5305,11 +5397,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 226
|
"__id__": 230
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 232
|
"__id__": 236
|
||||||
},
|
},
|
||||||
"_alignFlags": 18,
|
"_alignFlags": 18,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
@@ -5341,11 +5433,11 @@
|
|||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 226
|
"__id__": 230
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 234
|
"__id__": 238
|
||||||
},
|
},
|
||||||
"languageKey": "girllistpanel.title",
|
"languageKey": "girllistpanel.title",
|
||||||
"defaultText": "",
|
"defaultText": "",
|
||||||
@@ -5379,7 +5471,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 237
|
"__id__": 241
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
@@ -5407,7 +5499,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 239
|
"__id__": 243
|
||||||
},
|
},
|
||||||
"_customMaterial": null,
|
"_customMaterial": null,
|
||||||
"_srcBlendFactor": 2,
|
"_srcBlendFactor": 2,
|
||||||
@@ -5452,7 +5544,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 241
|
"__id__": 245
|
||||||
},
|
},
|
||||||
"_alignFlags": 41,
|
"_alignFlags": 41,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
@@ -5501,7 +5593,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 244
|
"__id__": 248
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
@@ -5529,7 +5621,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 246
|
"__id__": 250
|
||||||
},
|
},
|
||||||
"_customMaterial": null,
|
"_customMaterial": null,
|
||||||
"_srcBlendFactor": 2,
|
"_srcBlendFactor": 2,
|
||||||
@@ -5574,7 +5666,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 248
|
"__id__": 252
|
||||||
},
|
},
|
||||||
"_alignFlags": 45,
|
"_alignFlags": 45,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
@@ -5623,7 +5715,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 251
|
"__id__": 255
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
@@ -5651,7 +5743,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 253
|
"__id__": 257
|
||||||
},
|
},
|
||||||
"_alignFlags": 45,
|
"_alignFlags": 45,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
@@ -5687,7 +5779,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 255
|
"__id__": 259
|
||||||
},
|
},
|
||||||
"m_rootNode": null,
|
"m_rootNode": null,
|
||||||
"_id": ""
|
"_id": ""
|
||||||
@@ -5706,7 +5798,7 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 257
|
"__id__": 261
|
||||||
},
|
},
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.50",
|
||||||
|
"importer": "prefab",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "071b7a07-4a74-4a39-962b-ccbab803a523",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {
|
||||||
|
"syncNodeName": "NavigationPanel"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user