import { _decorator, Animation, AnimationClip, Button, Event, Label, Node, NodeEventType, Sprite, resources } 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 { HeroInfo, HeroList } from "../common/config/heroSet"; import { IType, SkillSet } from "../common/config/SkillSet"; import { oops } from "db://oops-framework/core/Oops"; import { mLogger } from "../common/Logger"; const {property, ccclass } = _decorator; /** 视图层对象 */ @ccclass('HListComp') @ecs.register('HListComp', false) export class HListComp extends CCComp { @property(Node) hero_icon=null! @property(Node) phero_icon=null! @property(Node) nhero_icon=null! @property(Node) ap_node=null! @property(Node) hp_node=null! @property(Node) info_node=null! @property(Node) name_node=null! @property(Node) pre_btn=null! @property(Node) next_btn=null! huuid:number=null! private currentIndex: number = 0; private iconVisualTokens: Map = new Map(); debugMode: boolean = false; onLoad() { this.pre_btn?.on(NodeEventType.TOUCH_END, this.onPreClick, this); this.next_btn?.on(NodeEventType.TOUCH_END, this.onNextClick, this); } start() { if (HeroList && HeroList.length > 0) { this.currentIndex = 0; this.updateHeroView(); } } private onPreClick() { if (!HeroList || HeroList.length === 0) return; this.currentIndex = (this.currentIndex - 1 + HeroList.length) % HeroList.length; this.updateHeroView(); } private onNextClick() { if (!HeroList || HeroList.length === 0) return; this.currentIndex = (this.currentIndex + 1) % HeroList.length; this.updateHeroView(); } private updateHeroView() { this.huuid = HeroList[this.currentIndex]; const hero = HeroInfo[this.huuid]; if (!hero) return; // 获取前后英雄的 uuid const preIndex = (this.currentIndex - 1 + HeroList.length) % HeroList.length; const nextIndex = (this.currentIndex + 1) % HeroList.length; const pUuid = HeroList[preIndex]; const nUuid = HeroList[nextIndex]; // 更新基础属性标签 this.setLabelText(this.name_node, hero.name); this.setLabelText(this.ap_node, `攻击力: ${hero.ap}`); this.setLabelText(this.hp_node, `生命值: ${hero.hp}`); // 更新动画 this.updateHeroAnimation(this.hero_icon, this.huuid); this.updateHeroAnimation(this.phero_icon, pUuid); this.updateHeroAnimation(this.nhero_icon, nUuid); // 更新技能列表 this.updateSkillInfo(hero); } private setLabelText(node: Node, text: string) { if (!node) return; const label = node.getComponent(Label) || node.getComponentInChildren(Label); if (label) { label.string = text; } } private updateHeroAnimation(node: Node, uuid: number) { if (!node) return; const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite); if (sprite) sprite.spriteFrame = null; const hero = HeroInfo[uuid]; if (!hero) return; const anim = node.getComponent(Animation) || node.addComponent(Animation); this.clearAnimationClips(anim); let token = (this.iconVisualTokens.get(node) || 0) + 1; this.iconVisualTokens.set(node, token); const path = `game/heros/hero/${hero.path}/idle`; resources.load(path, AnimationClip, (err, clip) => { if (err || !clip) { mLogger.log(this.debugMode, "HListComp", `load hero animation failed ${uuid}`, err); return; } if (token !== this.iconVisualTokens.get(node)) { return; } this.clearAnimationClips(anim); anim.addClip(clip); anim.play("idle"); }); } private clearAnimationClips(anim: Animation) { const clips = anim.clips; if (clips && clips.length > 0) { for (let i = clips.length - 1; i >= 0; i--) { const clip = clips[i]; if (clip) anim.removeClip(clip, true); } } } private findNodeByName(root: Node, name: string): Node | null { if (!root) return null; if (root.name === name) return root; for (let i = 0; i < root.children.length; i++) { const res = this.findNodeByName(root.children[i], name); if (res) return res; } return null; } private updateSkillInfo(hero: any) { if (!this.info_node) return; const skills = Object.values(hero.skills || {}); for (let i = 1; i <= 5; i++) { let line = this.findNodeByName(this.info_node, `Line${i}`) || this.findNodeByName(this.info_node, `line${i}`); if (!line) continue; const skill: any = skills[i - 1]; if (skill) { line.active = true; const skillId = skill.uuid; const config = SkillSet[skillId]; const text = config ? `${config.name} Lv.${skill.lv} CD:${skill.cd}s ${config.info}` : `未知技能 CD:${skill.cd}s`; const noteNode = this.findNodeByName(line, "note"); const label = noteNode?.getComponent(Label) || noteNode?.getComponentInChildren(Label) || line.getComponentInChildren(Label); if (label) { label.string = text; } this.updateLineTypeIcon(line, config?.IType); } else { line.active = false; } } } private updateLineTypeIcon(line: Node, iType?: IType) { const meleeNode = this.findNodeByName(line, "Melee"); const remoteNode = this.findNodeByName(line, "remote"); const supportNode = this.findNodeByName(line, "support"); if (meleeNode) meleeNode.active = iType === IType.Melee; if (remoteNode) remoteNode.active = iType === IType.remote; if (supportNode) supportNode.active = iType === IType.support; } /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { this.node.destroy(); } }