/** * @file TalentsComp.ts * @description 天赋图鉴页组件(UI 视图层) * * 职责: * 1. 展示当前所有天赋卡(技能卡)的图鉴。 * 2. 从 CardPoolList 获取所有的 type=Skill 卡牌。 * 3. 兼容旧的 `@ecs.register('Talents')` 资源引用。 * * 依赖: * - CardPoolList(CardSet)—— 获取技能卡配置 * - TalentItemComp —— 单条天赋图鉴项视图 */ import { _decorator, instantiate, Node, Prefab, UITransform } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { mLogger } from "../common/Logger"; import { CardPoolList, CardType, CardConfig } from "../common/config/CardSet"; import { TalentItemComp } from "./TalentItemComp"; const { ccclass, property } = _decorator; /** TalentsComp —— 天赋图鉴信息页组件 */ @ccclass('TalentsComp') @ecs.register('Talents', false) export class TalentsComp extends CCComp { @property({ type: Node, tooltip: "天赋技能列表容器" }) talents_content: Node = null!; @property({ type: Prefab, tooltip: "单条天赋项预制" }) prefab_talent_item: Prefab = null!; /** 调试日志开关 */ debugMode: boolean = false; /** 首次实例化缓存 */ private rendered: boolean = false; /** 缓存的稳定配置顺序,避免重复渲染时列表抖动 */ private cachedConfigs: CardConfig[] = []; protected onEnable(): void { this.refreshUI(); } /** 重新拉取最新数据并刷新所有子项 */ public refreshUI(): void { if (!this.talents_content || !this.prefab_talent_item) return; // 第一次:实例化所有子节点 if (!this.rendered) { // 获取所有天赋(技能卡)并按 wave 和 uuid 排序 this.cachedConfigs = CardPoolList.filter(card => card.type === CardType.Skill) .sort((a, b) => { const waveA = a.wave || 1; const waveB = b.wave || 1; if (waveA !== waveB) return waveA - waveB; return a.uuid - b.uuid; }); this.cachedConfigs.forEach((cfg) => { const itemNode = instantiate(this.prefab_talent_item); this.talents_content.addChild(itemNode); const comp = itemNode.getComponent(TalentItemComp); if (comp) { comp.updateItem(cfg); } }); this.rendered = true; // 动态调整容器高度 // 默认底高 1000,每行 3 个天赋信息卡,每张卡高 270,行间距 15 const totalCount = this.cachedConfigs.length; const rows = Math.ceil(totalCount / 3); const contentHeight = Math.max(1000, rows * 270 + (rows > 0 ? (rows - 1) * 15 : 0+50)); const uiTransform = this.talents_content.getComponent(UITransform); if (uiTransform) { uiTransform.height = contentHeight; } } else { // 如果已渲染,则仅更新数据(图鉴一般不会变动,这里做个兜底更新) this.cachedConfigs.forEach((cfg, index) => { const child = this.talents_content.children[index]; if (!child) return; const comp = child.getComponent(TalentItemComp); if (!comp) return; comp.updateItem(cfg); }); } } /** ECS 组件移除时销毁节点 */ reset() { this.rendered = false; this.cachedConfigs = []; this.node.destroy(); } protected onDestroy(): void { super.onDestroy(); mLogger.log(this.debugMode, 'TalentsComp', "释放界面"); } }