refactor(map): 重构英雄信息弹窗逻辑,移除oops.gui依赖
1. 将英雄信息弹窗从框架GUI系统改为同步实例化管理 2. 由HeroBoxComp接管弹窗的创建和销毁时机 3. 删除冗余的UIID配置和弹窗参数接口 4. 调整弹窗关闭逻辑,避免缓存节点带来的竞态问题
This commit is contained in:
@@ -30,8 +30,6 @@ export enum UIID {
|
||||
Guide2,
|
||||
Guide3,
|
||||
Guide4,
|
||||
/** 英雄信息弹窗(长按英雄盒查看次级属性与技能描述) */
|
||||
HeroMore,
|
||||
}
|
||||
|
||||
/** 打开界面方式的配置数据 */
|
||||
@@ -53,5 +51,4 @@ export var UIConfigData: { [key: number]: UIConfig } = {
|
||||
[UIID.Guide2]: { layer: LayerType.PopUp, prefab: "gui/element/guide2" },
|
||||
[UIID.Guide3]: { layer: LayerType.PopUp, prefab: "gui/element/guide3" },
|
||||
[UIID.Guide4]: { layer: LayerType.PopUp, prefab: "gui/element/guide4" },
|
||||
[UIID.HeroMore]: { layer: LayerType.PopUp, prefab: "gui/auie/more" },
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 职责:
|
||||
* 1. 同步显示一个已登场英雄的基础信息(图标 / 名称 / 等级 / AP / HP)。
|
||||
* 2. 长按英雄盒弹出信息面板(UIID.HeroMore → more.prefab),展示次级属性与技能描述。
|
||||
* 2. 长按英雄盒同步实例化信息面板(more.prefab),展示次级属性与技能描述;放开手指销毁。
|
||||
* 3. 由 MissionCardComp 实例化到 herosBoxNode 下,最多 3 个,与场上英雄一一对应。
|
||||
* 4. 英雄卖出 / 死亡后槽位保留,通过 applyEmpty() 显示为空英雄信息。
|
||||
*
|
||||
@@ -13,7 +13,7 @@
|
||||
* - HeroInfo(heroSet)—— 英雄静态配置
|
||||
*/
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Node, Sprite, Label, resources, AnimationClip, SpriteFrame, NodeEventType, EventTouch, Tween, tween, Vec3, Color } from "cc";
|
||||
import { _decorator, Node, Sprite, Label, resources, AnimationClip, SpriteFrame, NodeEventType, EventTouch, Tween, tween, Vec3, Color, Prefab, instantiate, director, find } 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 { oops } from "db://oops-framework/core/Oops";
|
||||
@@ -25,6 +25,7 @@ import { FacSet, FightSet, getLvColor } from "../common/config/GameSet";
|
||||
import { buildSkillDesc, ISkillDescSource } from "../common/config/HeroSkillDesc";
|
||||
import { MissionEconomy } from "./MissionEconomy";
|
||||
import { UIID } from "../common/config/GameUIConfig";
|
||||
import { HeroMoreCom } from "./HeroMoreCom";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -91,6 +92,10 @@ export class HeroBoxComp extends CCComp {
|
||||
@property(Label)
|
||||
private hp_plus_label: Label = null;
|
||||
|
||||
/** 英雄信息弹窗预制体(长按英雄盒时同步实例化展示,绕开 oops.gui 异步加载) */
|
||||
@property(Prefab)
|
||||
private morePrefab: Prefab = null;
|
||||
|
||||
// ======================== 运行时状态 ========================
|
||||
|
||||
/** 绑定的英雄实体 ID(0 表示空槽位) */
|
||||
@@ -102,6 +107,9 @@ export class HeroBoxComp extends CCComp {
|
||||
/** 当前显示的英雄 UUID(避免相同 UUID 重复加载动画) */
|
||||
private iconHeroUuid: number = 0;
|
||||
|
||||
/** 当前已弹出的英雄信息面板节点(null 表示未弹出) */
|
||||
private moreNode: Node | null = null;
|
||||
|
||||
/** 长按判定:当前按下触摸 ID(-1 表示无) */
|
||||
private longPressTouchId: number = -1;
|
||||
/** 长按判定:按下起点 UI 坐标 */
|
||||
@@ -115,7 +123,7 @@ export class HeroBoxComp extends CCComp {
|
||||
// ======================== 生命周期 ========================
|
||||
|
||||
onLoad() {
|
||||
// 长按英雄盒任意区域弹出信息面板(UIID.HeroMore → more.prefab);出售/升级按钮上的触摸不触发
|
||||
// 长按英雄盒任意区域实例化信息面板(more.prefab);出售/升级按钮上的触摸不触发
|
||||
this.node.on(NodeEventType.TOUCH_START, this.onBoxTouchStart, this);
|
||||
this.node.on(NodeEventType.TOUCH_MOVE, this.onBoxTouchMove, this);
|
||||
this.node.on(NodeEventType.TOUCH_END, this.onBoxTouchEnd, this);
|
||||
@@ -144,6 +152,8 @@ export class HeroBoxComp extends CCComp {
|
||||
if (this.upgrade_btn && this.upgrade_btn.isValid) {
|
||||
this.upgrade_btn.off(NodeEventType.TOUCH_END, this.onUpgradeHeroClick, this);
|
||||
}
|
||||
// 销毁时一并清理已弹出的信息面板
|
||||
this.closeMoreNode();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,14 +360,16 @@ export class HeroBoxComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/** 英雄盒抬起:取消未触发的长按判定 */
|
||||
/** 英雄盒抬起:取消未触发的长按判定;若长按已弹出信息面板则立即关闭 */
|
||||
private onBoxTouchEnd(event: EventTouch) {
|
||||
if (this.longPressTouchId < 0) return;
|
||||
if ((event.touch?.getID() ?? -1) !== this.longPressTouchId) return;
|
||||
this.cancelLongPress();
|
||||
// 直接销毁已弹出的信息面板(同步 destroy,无竞态)
|
||||
this.closeMoreNode();
|
||||
}
|
||||
|
||||
/** 英雄盒触摸被系统打断:取消长按判定 */
|
||||
/** 英雄盒触摸被系统打断:取消长按判定;若已弹窗则一并关闭 */
|
||||
private onBoxTouchCancel(event: EventTouch) {
|
||||
this.onBoxTouchEnd(event);
|
||||
}
|
||||
@@ -368,12 +380,32 @@ export class HeroBoxComp extends CCComp {
|
||||
this.unschedule(this.onLongPressFired);
|
||||
}
|
||||
|
||||
/** 长按触发:弹出英雄信息面板(more.prefab,展示次级属性与技能描述) */
|
||||
/** 长按触发:同步实例化英雄信息面板(more.prefab,展示次级属性与技能描述) */
|
||||
private onLongPressFired() {
|
||||
this.longPressTouchId = -1;
|
||||
// 不重置 longPressTouchId:保留以便 onBoxTouchEnd 能识别同一触摸并销毁弹窗
|
||||
if (!this.hasHero || !(this.model as any)?.ent) return;
|
||||
if (!this.morePrefab) {
|
||||
mLogger.warn(true, "HeroBoxComp", "onLongPressFired morePrefab 未绑定,请在编辑器拖入 more.prefab");
|
||||
return;
|
||||
}
|
||||
oops.audio.playEffect("music/button");
|
||||
oops.gui.open(UIID.HeroMore, { eid: this.eid });
|
||||
// 同步实例化:避开 oops.gui 首次异步加载窗口期,确保放开时能立即 destroy
|
||||
this.closeMoreNode();
|
||||
this.moreNode = instantiate(this.morePrefab);
|
||||
// more.prefab 是全屏遮罩弹窗,必须挂到 Canvas 根节点,避免被英雄盒父节点的 Mask 裁剪或坐标系错位
|
||||
const canvas = find("Canvas") || director.getScene()?.getChildByName("Canvas");
|
||||
(canvas ?? this.node.parent)?.addChild(this.moreNode);
|
||||
// 整体上移 100 像素(弹窗相对英雄盒偏上展示)
|
||||
this.moreNode.setPosition(this.moreNode.position.x, this.moreNode.position.y + 100, this.moreNode.position.z);
|
||||
this.moreNode.getComponent(HeroMoreCom)?.init(this.eid);
|
||||
}
|
||||
|
||||
/** 关闭并清理已弹出的英雄信息面板(同步 destroy) */
|
||||
private closeMoreNode() {
|
||||
if (this.moreNode && this.moreNode.isValid) {
|
||||
this.moreNode.destroy();
|
||||
}
|
||||
this.moreNode = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 职责:
|
||||
* 1. 展示单个英雄的次级属性(攻速/击晕/暴击/爆伤/冰冻/击退/穿透/风怒)与技能描述,
|
||||
* 展示内容由原 HeroBoxComp 分离而来,计算口径与其完全一致。
|
||||
* 2. 由 HeroBoxComp 长按英雄盒时通过 oops.gui.open(UIID.HeroMore, { eid }) 打开(oops.gui 模块)。
|
||||
* 2. 由 HeroBoxComp 长按英雄盒时同步实例化(instantiate more.prefab)并调用 init(eid)。
|
||||
* 3. 属性受 buff/光环影响实时变化,打开期间按固定间隔降频刷新;英雄死亡/被卖出自动关闭。
|
||||
* 4. 点击弹窗内任意位置(含全屏透明遮罩)关闭。
|
||||
* 4. 点击弹窗内任意位置(含全屏透明遮罩)或 HeroBoxComp 放开手指时由调用方 destroy。
|
||||
*
|
||||
* 依赖:
|
||||
* - HeroAttrsComp —— 英雄属性数据模型
|
||||
@@ -21,12 +21,6 @@ import { buildSkillDescRich } from "../common/config/HeroSkillDesc";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 英雄信息弹窗参数 */
|
||||
export interface HeroMoreParams {
|
||||
/** 英雄 ECS 实体 ID */
|
||||
eid?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* HeroMoreCom —— 英雄信息弹窗(more.prefab 根节点组件)
|
||||
*
|
||||
@@ -105,7 +99,7 @@ export class HeroMoreCom extends Component {
|
||||
// ======================== 生命周期 ========================
|
||||
|
||||
onLoad() {
|
||||
// 全屏透明遮罩为根节点子节点,点击任意处触摸事件冒泡至此 → 关闭弹窗
|
||||
// 全屏透明遮罩为根节点子节点,点击任意处触摸事件冒泡至此 → 关闭弹窗(备用交互)
|
||||
this.node.on(NodeEventType.TOUCH_END, this.onTouchEndClose, this);
|
||||
}
|
||||
|
||||
@@ -116,15 +110,13 @@ export class HeroMoreCom extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* oops.gui 添加到舞台回调(框架约定入口)。
|
||||
* @param params 见 HeroMoreParams;eid 对应实体不存在时立即关闭
|
||||
* 初始化并渲染英雄信息(由 HeroBoxComp 在 instantiate 后同步调用)。
|
||||
* @param eid 英雄 ECS 实体 ID;实体不存在时立即销毁
|
||||
*/
|
||||
onAdded(params: HeroMoreParams = {}) {
|
||||
this.isClosing = false;
|
||||
public init(eid: number) {
|
||||
this.refreshElapsed = 0;
|
||||
this.skillDescCache = "";
|
||||
|
||||
const eid = params?.eid ?? 0;
|
||||
if (!eid) {
|
||||
this.closeSelf();
|
||||
return;
|
||||
@@ -237,16 +229,18 @@ export class HeroMoreCom extends Component {
|
||||
|
||||
// ======================== 交互 ========================
|
||||
|
||||
/** 点击面板任意处(含遮罩)关闭 */
|
||||
/** 点击面板任意处(含遮罩)关闭(备用交互,主路径由 HeroBoxComp 放开手指 destroy) */
|
||||
private onTouchEndClose() {
|
||||
oops.audio.playEffect("music/button");
|
||||
this.closeSelf();
|
||||
}
|
||||
|
||||
/** 关闭弹窗(交还 oops.gui 缓存,下次打开复用节点并重新触发 onAdded) */
|
||||
/** 关闭弹窗(同步销毁节点) */
|
||||
private closeSelf() {
|
||||
if (this.isClosing) return;
|
||||
this.isClosing = true;
|
||||
oops.gui.removeByNode(this.node);
|
||||
if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user