refactor(ui): 重构英雄信息面板组件,提取通用逻辑
- 将 HInfoComp 重构为独立组件,封装标签查找与数据绑定逻辑 - 在 MissionCardComp 中使用 HInfoComp 替代直接操作 Label 组件 - 移除冗余的 findNodeByPath 和 resolvePanelLabel 方法 - 通过 isModelAlive 方法统一检查模型有效性
This commit is contained in:
@@ -190,7 +190,7 @@
|
|||||||
"_fillStart": 0,
|
"_fillStart": 0,
|
||||||
"_fillRange": 0,
|
"_fillRange": 0,
|
||||||
"_isTrimmedMode": true,
|
"_isTrimmedMode": true,
|
||||||
"_useGrayscale": false,
|
"_useGrayscale": true,
|
||||||
"_atlas": {
|
"_atlas": {
|
||||||
"__uuid__": "6165ffc9-a838-4a33-b569-bdbaaab0e6b4",
|
"__uuid__": "6165ffc9-a838-4a33-b569-bdbaaab0e6b4",
|
||||||
"__expectedType__": "cc.SpriteAtlas"
|
"__expectedType__": "cc.SpriteAtlas"
|
||||||
|
|||||||
@@ -1,20 +1,66 @@
|
|||||||
import { mLogger } from "../common/Logger";
|
import { _decorator, Label, Node } from "cc";
|
||||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources } from "cc";
|
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
|
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass } = _decorator;
|
||||||
|
|
||||||
/** 视图层对象 */
|
/** 视图层对象 */
|
||||||
@ccclass('HInfoComp')
|
@ccclass('HInfoComp')
|
||||||
@ecs.register('HInfoComp', false)
|
@ecs.register('HInfoComp', false)
|
||||||
export class HInfoComp extends CCComp {
|
export class HInfoComp extends CCComp {
|
||||||
private debugMode: boolean = true;
|
private eid: number = 0;
|
||||||
/** 锁定态图标节点(显示时表示本槽位锁定) */
|
private model: HeroAttrsComp | null = null;
|
||||||
|
private apLabel: Label | null = null;
|
||||||
|
private hpLabel: Label | null = null;
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this.cacheLabels();
|
||||||
|
}
|
||||||
|
|
||||||
|
bindData(eid: number, model: HeroAttrsComp) {
|
||||||
|
this.eid = eid;
|
||||||
|
this.model = model;
|
||||||
|
this.cacheLabels();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
if (!this.model) return;
|
||||||
|
if (this.apLabel) {
|
||||||
|
this.apLabel.string = `${Math.max(0, Math.floor(this.model.ap ?? 0))}`;
|
||||||
|
}
|
||||||
|
if (this.hpLabel) {
|
||||||
|
this.hpLabel.string = `${Math.max(0, Math.floor(this.model.hp_max ?? 0))}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isModelAlive(): boolean {
|
||||||
|
return !!(this.model as any)?.ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private cacheLabels() {
|
||||||
|
if (!this.apLabel) {
|
||||||
|
this.apLabel = this.findLabelByPath(["ap", "val"]);
|
||||||
|
}
|
||||||
|
if (!this.hpLabel) {
|
||||||
|
this.hpLabel = this.findLabelByPath(["hp", "val"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private findLabelByPath(path: string[]): Label | null {
|
||||||
|
let current: Node | null = this.node;
|
||||||
|
for (let i = 0; i < path.length; i++) {
|
||||||
|
current = current?.getChildByName(path[i]) ?? null;
|
||||||
|
if (!current) return null;
|
||||||
|
}
|
||||||
|
return current.getComponent(Label) || current.getComponentInChildren(Label);
|
||||||
|
}
|
||||||
|
|
||||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||||
reset() {
|
reset() {
|
||||||
|
this.model = null;
|
||||||
|
this.eid = 0;
|
||||||
this.node.destroy();
|
this.node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { smc } from "../common/SingletonModuleComp";
|
|||||||
import { CardComp } from "./CardComp";
|
import { CardComp } from "./CardComp";
|
||||||
import { oops } from "db://oops-framework/core/Oops";
|
import { oops } from "db://oops-framework/core/Oops";
|
||||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||||
|
import { HInfoComp } from "./HInfoComp";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -54,8 +55,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
private heroInfoItems: Map<number, {
|
private heroInfoItems: Map<number, {
|
||||||
node: Node,
|
node: Node,
|
||||||
model: HeroAttrsComp,
|
model: HeroAttrsComp,
|
||||||
apLabel: Label | null,
|
comp: HInfoComp
|
||||||
hpLabel: Label | null
|
|
||||||
}> = new Map();
|
}> = new Map();
|
||||||
onLoad() {
|
onLoad() {
|
||||||
/** 绑定事件 -> 缓存子控制器 -> 初始化UI状态 */
|
/** 绑定事件 -> 缓存子控制器 -> 初始化UI状态 */
|
||||||
@@ -372,18 +372,24 @@ export class MissionCardComp extends CCComp {
|
|||||||
const current = this.heroInfoItems.get(eid);
|
const current = this.heroInfoItems.get(eid);
|
||||||
if (current) {
|
if (current) {
|
||||||
current.model = model;
|
current.model = model;
|
||||||
|
current.comp.bindData(eid, model);
|
||||||
this.updateHeroInfoPanel(current);
|
this.updateHeroInfoPanel(current);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const node = instantiate(this.hero_info_prefab);
|
const node = instantiate(this.hero_info_prefab);
|
||||||
node.parent = this.hero_info_node;
|
node.parent = this.hero_info_node;
|
||||||
node.active = true;
|
node.active = true;
|
||||||
|
const comp = node.getComponent(HInfoComp);
|
||||||
|
if (!comp) {
|
||||||
|
node.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const item = {
|
const item = {
|
||||||
node,
|
node,
|
||||||
model,
|
model,
|
||||||
apLabel: this.resolvePanelLabel(node, [["ap", "val"]]),
|
comp
|
||||||
hpLabel: this.resolvePanelLabel(node, [["hp", "val"]])
|
|
||||||
};
|
};
|
||||||
|
comp.bindData(eid, model);
|
||||||
this.heroInfoItems.set(eid, item);
|
this.heroInfoItems.set(eid, item);
|
||||||
this.relayoutHeroInfoPanels();
|
this.relayoutHeroInfoPanels();
|
||||||
this.updateHeroInfoPanel(item);
|
this.updateHeroInfoPanel(item);
|
||||||
@@ -396,8 +402,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
removeKeys.push(eid);
|
removeKeys.push(eid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ent = (item.model as any)?.ent;
|
if (!item.comp.isModelAlive()) {
|
||||||
if (!ent) {
|
|
||||||
if (item.node.isValid) item.node.destroy();
|
if (item.node.isValid) item.node.destroy();
|
||||||
removeKeys.push(eid);
|
removeKeys.push(eid);
|
||||||
return;
|
return;
|
||||||
@@ -415,11 +420,9 @@ export class MissionCardComp extends CCComp {
|
|||||||
private updateHeroInfoPanel(item: {
|
private updateHeroInfoPanel(item: {
|
||||||
node: Node,
|
node: Node,
|
||||||
model: HeroAttrsComp,
|
model: HeroAttrsComp,
|
||||||
apLabel: Label | null,
|
comp: HInfoComp
|
||||||
hpLabel: Label | null
|
|
||||||
}) {
|
}) {
|
||||||
if (item.apLabel) item.apLabel.string = `${Math.max(0, Math.floor(item.model.ap ?? 0))}`;
|
item.comp.refresh();
|
||||||
if (item.hpLabel) item.hpLabel.string = `${Math.max(0, Math.floor(item.model.hp_max ?? 0))}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private relayoutHeroInfoPanels() {
|
private relayoutHeroInfoPanels() {
|
||||||
@@ -448,25 +451,6 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.heroInfoSyncTimer = 0;
|
this.heroInfoSyncTimer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolvePanelLabel(root: Node, paths: string[][]): Label | null {
|
|
||||||
for (let i = 0; i < paths.length; i++) {
|
|
||||||
const node = this.findNodeByPath(root, paths[i]);
|
|
||||||
if (!node) continue;
|
|
||||||
const label = node.getComponent(Label) || node.getComponentInChildren(Label);
|
|
||||||
if (label) return label;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private findNodeByPath(root: Node, path: string[]): Node | null {
|
|
||||||
let current: Node | null = root;
|
|
||||||
for (let i = 0; i < path.length; i++) {
|
|
||||||
current = current?.getChildByName(path[i]) ?? null;
|
|
||||||
if (!current) return null;
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||||
reset() {
|
reset() {
|
||||||
this.clearHeroInfoPanels();
|
this.clearHeroInfoPanels();
|
||||||
|
|||||||
Reference in New Issue
Block a user