You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/script/ui/BattleWeaponDesc1/UIBattleWeaponDesc1.ts

637 lines
25 KiB

//*********************
// create by 流云
// time: Sat Sep 05 2026
// desc: 战斗内点击 type=1 单字 — 详情弹窗
//*********************
import {
_decorator,
EventTouch,
instantiate,
Label,
Node,
Prefab,
sp,
Sprite,
Tween,
UITransform,
UIOpacity,
UIRenderer,
Vec3,
} from 'cc';
import { type IPopAnimConfig, type IPopAnimSession } from '../../../mx/module/ui/popAnim';
import { GEvent } from '../../../mx/module/event/GEvent';
import { Auto_BattleWeaponDesc1 } from './Auto_BattleWeaponDesc1';
import type { TileEntitySnapshot, TowerRuntimeSnapshot } from '../../battle/combat/TowerQueryTypes';
import { TowerQueryService } from '../../battle/combat/TowerQueryService';
import { getBattleBuffDigitStatHost } from '../../battle/combat/BattleBuffDigitStatHost';
import { deriveTowerSetupStats, TowerStatDisplay } from '../../battle/combat/TowerStatResolver';
import { bagToolPrefabName, isBagToolTextType } from 'db://assets/mx/module/merge';
import { heroNormalSkillId, textIconName } from '../../battle/config/BattleHeroTable';
import { applyGlyphSpineSkin } from '../../battle/view/GlyphSpineSkin';
import { TextGrid } from '../../battle/view/TextGrid';
import { PEACH_TREE_WEAPON2_ID } from '../../battle/bag/BagPrepConfig';
import { WeaponComposeConfigProvider } from '../../battle/bag/WeaponComposeConfigProvider';
import { BATTLE_HERO_BUFF_PATH } from '../../battle/res/BattleHeroResCollector';
import { GBundle, GPath } from '../../game/ConfigRes';
import { TableNames } from '../../game/ConfigTableData';
import { BattleBuffFunctionType } from '../../manager/battleBuff/BattleBuffTypes';
import { ensureSpineSkeletonDataRuntime } from 'db://assets/mx/module/lang/spineRuntimePatch';
const { ccclass } = _decorator;
/** 单字详情弹窗入参 */
export interface BattleWeaponDesc1PanelData {
entity: TileEntitySnapshot;
runtime?: TowerRuntimeSnapshot | null;
/** 蟠桃树(weapon2Id=102) */
isPeachTree?: boolean;
/** 功能符 / 倍率卡 / 属性卡(名称+描述,无攻击数值) */
isBagItem?: boolean;
/** 敌方阵营(预留;单字详情暂与己方同形) */
enemyCamp?: boolean;
weaponWorldPos?: { x: number; y: number; z?: number };
gridStep?: number;
trySwitchAtUiPos?: (uiPos: { x: number; y: number }) => boolean;
}
/** 功能符 type → 详情描述(Text 表无 desc 字段) */
const BAG_TOOL_DESC: { [type: number]: string } = {
10: '拖到己方数字上,数字等级+1(最高14级)。可丢进垃圾桶回收。',
11: '拖到己方数字上,数字等级+2(最高14级)。可丢进垃圾桶回收。',
12: '拖到己方数字上,随机转换五行属性(不会保持当前属性)。可丢进垃圾桶回收。',
13: '拖到敌方大于1级的数字上,等级-1。可丢进垃圾桶回收。',
};
const LOG = '[UIBattleWeaponDesc1]';
/** 图鉴内隐藏 textGrid 子节点 */
const GLYPH_HIDE_CHILDREN = ['select', 'redSelect', 'canUpEff', 'trail1', 'trail2', 'trail3'];
/** ui_node 内字形缩放 */
const GLYPH_SCALE = 0.85;
@ccclass('UIBattleWeaponDesc1')
export class UIBattleWeaponDesc1 extends Auto_BattleWeaponDesc1 {
private static readonly PANEL_GAP_GRIDS = 1.7;
private _popupBody: Node | null = null;
/** 递增时取消尚未完成的关窗销毁 */
private _panelLifeGen = 0;
/** ui_node 下挂的字形节点 */
private _glyphNode: Node | null = null;
/** 字形是否来自 res 对象池(功能符/产卡) */
private _glyphFromPool = false;
/** 普通字攻击数值区 */
private _uiAtkNode: Node | null = null;
/** 蟠桃树信息区 */
private _uiPeachNode: Node | null = null;
/** 蟠桃树技能描述(ui_peachNode/lb_skillDesc) */
private _lbPeachSkillDesc: Label | null = null;
/** GEvent 监听是否已绑定 */
private _geventBound = false;
onLoad(): void {
super.onLoad();
this._popupBody = this.node.getChildByName('弹窗主体');
this._bindStatNodes();
}
/** 绑定 ui_atkNode / ui_peachNode 及子 Label(Auto 路径可能未随 prefab 更新) */
private _bindStatNodes(): void {
const body = this._popupBody ?? this.node.getChildByName('弹窗主体');
if (!body?.isValid) return;
this._uiAtkNode = body.getChildByName('ui_atkNode');
if (this.ui_campNode?.isValid) this.ui_campNode.active = false;
const atk = this._uiAtkNode;
if (atk?.isValid) {
this.lb_attck = atk.getChildByName('lb_attck')?.getComponent(Label) ?? this.lb_attck;
this.lb_attckSpeed = atk.getChildByName('lb_attckSpeed')?.getComponent(Label) ?? this.lb_attckSpeed;
}
this._uiPeachNode = body.getChildByName('ui_peachNode');
const peach = this._uiPeachNode ?? this.ui_peachNode;
if (peach?.isValid) {
this.ui_peachNode = peach;
this.lb_time = peach.getChildByName('lb_time')?.getComponent(Label) ?? this.lb_time;
this._lbPeachSkillDesc = peach.getChildByName('lb_peachSkillDesc')?.getComponent(Label)
?? this._lbPeachSkillDesc
?? null;
}
}
onEnable(): void {
super.onEnable();
this.ui_bgMask?.on(Node.EventType.TOUCH_END, this.click_ui_bgMask, this);
this._bindLiveRefresh();
}
onDisable(): void {
if (this.ui_bgMask?.isValid) {
this.ui_bgMask.off(Node.EventType.TOUCH_END, this.click_ui_bgMask, this);
}
this._unbindLiveRefresh();
this.unschedule(this._deferredRefreshDynamic);
this._clearGlyphNode();
super.onDisable();
}
/** 订阅棋盘变更,实时刷新攻击力/攻速 */
private _bindLiveRefresh(): void {
if (this._geventBound) return;
GEvent.Ins.on(GEvent.UpdateBestPlace, this._onLiveDataDirty, this);
this._geventBound = true;
}
/** 取消实时刷新订阅 */
private _unbindLiveRefresh(): void {
if (!this._geventBound) return;
GEvent.Ins.off(GEvent.UpdateBestPlace, this._onLiveDataDirty, this);
this._geventBound = false;
}
/** 棋盘/攻速符变化后刷新攻击力/攻速 */
private _onLiveDataDirty = (): void => {
this.unschedule(this._deferredRefreshDynamic);
this.scheduleOnce(this._deferredRefreshDynamic, 0);
};
/** 帧末刷新,确保攻速符 modifier 写入后再读 */
private _deferredRefreshDynamic = (): void => {
this._refreshDynamicFromLive();
};
/** 仅刷新攻击力/攻速 */
private _refreshDynamicFromLive(): void {
if (!this.node?.isValid || !this.node.active) return;
const data = this.prema as BattleWeaponDesc1PanelData | null;
if (!data?.entity?.tile) return;
const tile = data.entity.tile;
if (data.isBagItem || this._isBagItemEntity(data.entity)) return;
if (data.isPeachTree || this._isPeachText(tile)) return;
const w1 = this._resolveHero(data.entity);
const runtime = this._resolveLiveRuntime(data.runtime ?? null, data.entity);
data.runtime = runtime;
const stats = this._resolveLiveStats(runtime, data.entity);
const level = runtime?.level ?? data.entity.level;
this._refreshAtkLabels(w1, level, stats);
}
onInit(): void {
this._panelLifeGen++;
this._ensurePanelVisible();
this._bindLiveRefresh();
const data = this.prema as BattleWeaponDesc1PanelData | null;
if (!data?.entity?.tile) {
this._clearLabels();
this._clearGlyphNode();
return;
}
this._bindStatNodes();
const { entity } = data;
const tile = entity.tile;
const isBagItem = !!data.isBagItem || this._isBagItemEntity(entity);
if (isBagItem) {
this._refreshBagItemPanel(entity);
this._applyPanelPosition(data);
return;
}
const isPeachText = !!data.isPeachTree || this._isPeachText(tile);
const w1 = this._resolveHero(entity);
const runtime = this._resolveLiveRuntime(data.runtime ?? null, entity);
data.runtime = runtime;
const stats = this._resolveLiveStats(runtime, entity);
const level = runtime?.level ?? entity.level;
const ht = Math.floor(Number(w1?.herotype) || 0);
const levelLimit = entity.tower?.levelLimit
?? (ht >= 1 && ht <= 5 ? WeaponComposeConfigProvider.instance.getElementMaxLevel(ht) : level);
this._refreshGlyph(tile);
this._refreshCommonLabels(w1, level, levelLimit);
this._refreshStatPanel(isPeachText);
if (isPeachText) {
this._refreshPeachLabels(w1, level);
} else {
this._refreshAtkLabels(w1, level, stats);
}
this._applyPanelPosition(data);
}
destroyPanel(tweenType = 1) {
return new Promise((resolve) => {
const lifeGen = this._panelLifeGen;
const finish = () => {
if (lifeGen !== this._panelLifeGen) {
resolve(true);
return;
}
this.prepareDestroyForRender();
if (this.node.isValid) {
this.node.destroy();
}
resolve(true);
this.notifyPanelClose();
};
if (tweenType === 2 || tweenType === 3) {
gg.ui.popAnim.playClose(this.node, this._resolvePopSession(), tweenType, finish);
return;
}
finish();
});
}
click_ui_bgMask(event?: EventTouch): void {
const uiPos = event?.getUILocation();
const trySwitch = (this.prema as BattleWeaponDesc1PanelData | null)?.trySwitchAtUiPos;
if (uiPos && trySwitch?.(uiPos)) {
return;
}
this.close(2);
}
/** ui_node:textGrid 预制体按 Text.icon 播 skin 待机(含蟠桃树) */
private _refreshGlyph(tile: ITableText): void {
if (!this.ui_node?.isValid) return;
this._clearGlyphNode();
const prefab = gg.res.getRes<Prefab>('textGrid', GPath.Prefab, GBundle.BattleGame, Prefab);
if (!prefab) {
console.log('[UIBattleWeaponDesc1] textGrid 预制体缺失', tile.id);
this.ui_node.active = false;
return;
}
const gridNode = instantiate(prefab);
gridNode.parent = this.ui_node;
gridNode.setPosition(0, 0, 0);
gridNode.setScale(GLYPH_SCALE, GLYPH_SCALE, 1);
this._glyphNode = gridNode;
this.ui_node.active = true;
for (let i = 0; i < GLYPH_HIDE_CHILDREN.length; i++) {
const child = gridNode.getChildByName(GLYPH_HIDE_CHILDREN[i]);
if (child) child.active = false;
}
const textGrid = gridNode.getComponent(TextGrid);
if (textGrid) textGrid.enabled = false;
const iconName = textIconName(tile);
if (!iconName) {
console.log('[UIBattleWeaponDesc1] 字形名为空', tile.id);
this.ui_node.active = false;
return;
}
const skinNode = gridNode.getChildByName('skin');
if (skinNode) skinNode.active = true;
const sk = skinNode?.getComponent(sp.Skeleton) ?? skinNode?.getComponentInChildren(sp.Skeleton);
if (!sk?.isValid) {
console.log('[UIBattleWeaponDesc1] 字形 Spine 缺失', iconName);
return;
}
sk.enabled = true;
if (!applyGlyphSpineSkin(sk, iconName)) {
console.log('[UIBattleWeaponDesc1] 字形皮肤未能应用', iconName);
}
if (sk.skeletonData) ensureSpineSkeletonDataRuntime(sk.skeletonData);
if (sk.skeletonData?.getRuntimeData?.(true)?.findAnimation?.('待机')) {
sk.setAnimation(0, '待机', true);
}
}
private _clearGlyphNode(): void {
const held = this._glyphNode;
this._glyphNode = null;
if (held?.isValid) {
if (this._glyphFromPool) {
gg.res.putNode(held);
} else {
held.destroy();
}
}
this._glyphFromPool = false;
if (this.ui_node?.isValid) {
this.ui_node.removeAllChildren();
}
}
/** 蟠桃树字(Text.id=102) */
private _isPeachText(tile: ITableText): boolean {
return Math.floor(Number(tile.id) || 0) === PEACH_TREE_WEAPON2_ID;
}
/**
* 是否功能符 / 产卡。
* @param entity 字块快照
*/
private _isBagItemEntity(entity: TileEntitySnapshot): boolean {
if (Math.floor(Number(entity.battleCardKind) || 0) > 0) return true;
const tileType = Math.floor(Number(entity.tileType) || Number(entity.tile?.type) || 0);
return isBagToolTextType(tileType);
}
/**
* 功能符 / 产卡:图标 + 名称 + 描述(复用蟠桃信息区,隐藏等级与 CD)。
* @param entity 字块快照
*/
private _refreshBagItemPanel(entity: TileEntitySnapshot): void {
const info = this._resolveBagItemInfo(entity);
if (this.lb_name) this.lb_name.string = info.name ? gg.lang.get(info.name) : '';
if (this.lb_level) this.lb_level.string = '';
if (this.lb_lvMax) this.lb_lvMax.string = '';
if (this._uiAtkNode?.isValid) this._uiAtkNode.active = false;
if (this.ui_campNode?.isValid) this.ui_campNode.active = false;
const peachPanel = this._uiPeachNode ?? this.ui_peachNode;
if (peachPanel?.isValid) peachPanel.active = true;
if (this.lb_time) this.lb_time.string = '';
if (this._lbPeachSkillDesc) {
this._lbPeachSkillDesc.string = info.desc ? gg.lang.get(info.desc) : '';
}
this._refreshBagItemGlyph(info.prefabName);
}
/**
* 解析道具展示名、描述、buff 预制体名。
* @param entity 字块快照
*/
private _resolveBagItemInfo(entity: TileEntitySnapshot): { name: string; desc: string; prefabName: string } {
const cardKind = Math.floor(Number(entity.battleCardKind) || 0);
if (cardKind > 0) {
const ft = cardKind === 1 ? BattleBuffFunctionType.MultiplierCard : BattleBuffFunctionType.AttrCard;
const row = this._battleBuffByFunctionType(ft);
const fallbackName = cardKind === 1 ? '倍率卡' : '属性卡';
return {
name: row?.name ? String(row.name) : fallbackName,
desc: row?.desc ? String(row.desc) : '',
prefabName: fallbackName,
};
}
const tileType = Math.floor(Number(entity.tileType) || Number(entity.tile?.type) || 0);
const prefabName = bagToolPrefabName(tileType) ?? '';
const desc = BAG_TOOL_DESC[tileType] ?? '';
if (!prefabName) {
console.log(LOG, '功能符预制体名缺失', tileType, entity.tile?.id);
}
if (!desc) {
console.log(LOG, '功能符描述缺失', tileType, entity.tile?.id);
}
return { name: prefabName, desc, prefabName };
}
/**
* 按 functiontype 取首条 Battlebuff(产卡说明)。
* @param ft Battlebuff.functiontype
*/
private _battleBuffByFunctionType(ft: BattleBuffFunctionType): ITableBattlebuff | null {
const list = gg.data.table.getTableList<ITableBattlebuff>(TableNames.Battlebuff) ?? [];
for (let i = 0; i < list.length; i++) {
if (Number(list[i].functiontype) === ft) return list[i];
}
console.log(LOG, 'Battlebuff 缺失 functiontype=', ft);
return null;
}
/**
* ui_node 挂载 battleHero/prefab/buff 预制体。
* @param prefabName 预制体名
*/
private _refreshBagItemGlyph(prefabName: string): void {
if (!this.ui_node?.isValid) return;
this._clearGlyphNode();
if (!prefabName) {
this.ui_node.active = false;
return;
}
let node: Node | null = null;
try {
node = gg.res.getNode(BATTLE_HERO_BUFF_PATH, prefabName, GBundle.BattleHero);
} catch (e) {
console.log(LOG, '产卡/功能符预制体加载异常', prefabName, String(e));
this.ui_node.active = false;
return;
}
if (!node?.isValid) {
console.log(LOG, '产卡/功能符预制体缺失', prefabName);
this.ui_node.active = false;
return;
}
node.parent = this.ui_node;
node.setPosition(0, 0, 0);
node.setScale(GLYPH_SCALE, GLYPH_SCALE, 1);
node.active = true;
this._glyphNode = node;
this._glyphFromPool = true;
this.ui_node.active = true;
}
/** 解析 Hero 行(部署快照缺失时按 weapon1Id / 蟠桃 id 兜底) */
private _resolveHero(entity: TileEntitySnapshot): ITableHero | null {
const fromTower = entity.tower?.config ?? null;
if (fromTower) return fromTower;
const heroId = entity.weapon1Id > 0 ? entity.weapon1Id : 0;
if (heroId > 0) {
return gg.data.table.getTableData<ITableHero>(TableNames.Hero, heroId) ?? null;
}
if (this._isPeachText(entity.tile)) {
return gg.data.table.getTableData<ITableHero>(TableNames.Hero, PEACH_TREE_WEAPON2_ID) ?? null;
}
return null;
}
/** 切换普通攻击区 / 蟠桃树信息区 */
private _refreshStatPanel(isPeachText: boolean): void {
if (this._uiAtkNode?.isValid) this._uiAtkNode.active = !isPeachText;
if (this.ui_campNode?.isValid) this.ui_campNode.active = false;
const peachPanel = this._uiPeachNode ?? this.ui_peachNode;
if (peachPanel?.isValid) peachPanel.active = isPeachText;
}
private _refreshCommonLabels(w1: ITableHero | null, level: number, levelLimit: number): void {
if (!w1) {
if (this.lb_name) this.lb_name.string = '';
if (this.lb_level) this.lb_level.string = '';
if (this.lb_lvMax) this.lb_lvMax.string = '';
return;
}
if (this.lb_name) {
this.lb_name.string = gg.lang.get(w1.name);
}
if (this.lb_level) {
this.lb_level.string = `Lv.${level}`;
}
if (this.lb_lvMax) {
this.lb_lvMax.string = `满级${levelLimit}级`;
}
}
/** 普通字:攻击力 / 攻速(ui_atkNode) */
private _refreshAtkLabels(
w1: ITableHero | null,
level: number,
stats: TowerRuntimeSnapshot['stats'] | undefined,
): void {
if (!w1) {
if (this.lb_attck) this.lb_attck.string = '';
if (this.lb_attckSpeed) this.lb_attckSpeed.string = '';
return;
}
const setup = deriveTowerSetupStats(w1, level);
const attack = stats?.attack ?? setup.attack;
const attackSpeed = stats?.attackSpeed ?? setup.attackSpeed;
if (this.lb_attck) {
this.lb_attck.string = TowerStatDisplay.oneDecimal(attack);
}
if (this.lb_attckSpeed) {
this.lb_attckSpeed.string = TowerStatDisplay.attackSpeed(attackSpeed);
}
}
/** 蟠桃树:产桃 CD / 技能描述(ui_peachNode) */
private _refreshPeachLabels(w1: ITableHero | null, level: number): void {
if (!w1) {
this._clearPeachLabels();
return;
}
const skillId = heroNormalSkillId(w1, level);
const skill = skillId > 0
? gg.data.table.getTableData<ITableSkill>(TableNames.Skill, skillId)
: null;
if (skillId > 0 && !skill) {
console.log(LOG, 'Skill 缺失', skillId, w1.id, level);
}
const cdSec = skill && Number(skill.cd) > 0 ? Number(skill.cd) : 0;
if (skill && !(cdSec > 0)) {
console.log(LOG, '蟠桃产桃 CD 无效', skill.id, skill.cd);
}
if (this.lb_time) {
this.lb_time.string = cdSec > 0 ? `${TowerStatDisplay.attackSpeed(cdSec)}秒` : '';
}
if (this._lbPeachSkillDesc) {
this._lbPeachSkillDesc.string = skill ? gg.lang.get(skill.desc) : '';
}
}
private _clearPeachLabels(): void {
if (this.lb_time) this.lb_time.string = '';
if (this._lbPeachSkillDesc) this._lbPeachSkillDesc.string = '';
}
private _clearLabels(): void {
if (this.lb_name) this.lb_name.string = '';
if (this.lb_level) this.lb_level.string = '';
if (this.lb_lvMax) this.lb_lvMax.string = '';
if (this.lb_attck) this.lb_attck.string = '';
if (this.lb_attckSpeed) this.lb_attckSpeed.string = '';
this._clearPeachLabels();
if (this._uiAtkNode?.isValid) this._uiAtkNode.active = false;
if (this.ui_campNode?.isValid) this.ui_campNode.active = false;
const peachPanel = this._uiPeachNode ?? this.ui_peachNode;
if (peachPanel?.isValid) peachPanel.active = false;
}
/** 已部署则重读 ECS 最终数值(含攻速符 aspd_add) */
private _resolveLiveRuntime(runtime: TowerRuntimeSnapshot | null, entity: TileEntitySnapshot): TowerRuntimeSnapshot | null {
let live = runtime;
const battle = gg.game.CurentBattle;
const session = battle?.session ?? null;
const entityId = live?.entityId ?? 0;
if (entityId > 0 && session) {
live = TowerQueryService.instance.getRuntimeSnapshot(session, entityId) ?? live;
return live;
}
if (entity.location?.kind === 'map' && session) {
live = TowerQueryService.instance.getRuntimeByGridIndex(entity.location.gridIndex, session, null) ?? live;
}
return live;
}
/** 优先 ECS 最终攻速/攻击;未部署才回落配表快照(叠 101~104) */
private _resolveLiveStats(runtime: TowerRuntimeSnapshot | null, entity: TileEntitySnapshot): TowerRuntimeSnapshot['stats'] | undefined {
const battle = gg.game.CurentBattle;
const session = battle?.session ?? null;
const pid = battle?.localPlayerId ?? gg.game.localPlayer?.playerId ?? 0;
const entityId = runtime?.entityId ?? 0;
if (entityId > 0 && session) {
getBattleBuffDigitStatHost().refreshEntity(session, entityId, pid);
const live = TowerQueryService.instance.readLiveStats(session, entityId);
if (live) return live;
}
const base = runtime?.stats ?? entity.tower?.stats;
if (!base) return undefined;
const w1 = entity.weapon1Id > 0 ? entity.weapon1Id : (entity.tower?.config?.id ?? 0);
const level = runtime?.level ?? entity.level;
if (!(w1 > 0)) return base;
return getBattleBuffDigitStatHost().previewOntoStats(base, w1, level, pid);
}
private _applyPanelPosition(data: BattleWeaponDesc1PanelData | null): void {
const weaponWorld = data?.weaponWorldPos;
if (!weaponWorld || !this._popupBody?.isValid) return;
const rootUt = this.node.getComponent(UITransform);
const bodyUt = this._popupBody.getComponent(UITransform);
if (!rootUt || !bodyUt) return;
const step = data?.gridStep ?? 93;
const halfW = bodyUt.contentSize.width * 0.5;
const halfH = bodyUt.contentSize.height * 0.5;
const gap = UIBattleWeaponDesc1.PANEL_GAP_GRIDS;
const weaponLocal = rootUt.convertToNodeSpaceAR(
new Vec3(weaponWorld.x, weaponWorld.y, weaponWorld.z ?? 0),
);
const x = 0;
const y = weaponLocal.y + step * (0.5 + gap) + halfH;
const rootHalfW = rootUt.contentSize.width * 0.5;
const rootHalfH = rootUt.contentSize.height * 0.5;
const clampedX = Math.max(-rootHalfW + halfW, Math.min(rootHalfW - halfW, x));
const clampedY = Math.max(-rootHalfH + halfH, Math.min(rootHalfH - halfH, y));
this._popupBody.setPosition(clampedX, clampedY, 0);
}
private _ensurePanelVisible(): void {
if (!this.node?.isValid) return;
this.node.active = true;
Tween.stopAllByTarget(this.node);
const body = this._popupBody;
if (body?.isValid) {
for (const r of body.getComponentsInChildren(UIRenderer)) {
if (r?.isValid) r.enabled = true;
}
}
this._keepMaskTouchOnly();
}
private _keepMaskTouchOnly(): void {
if (!this.ui_bgMask?.isValid) return;
Tween.stopAllByTarget(this.ui_bgMask);
const maskSpr = this.ui_bgMask.getComponent(Sprite);
if (maskSpr) maskSpr.enabled = false;
const op = this.ui_bgMask.getComponent(UIOpacity);
if (op) op.opacity = 0;
}
private _resolvePopSession(): IPopAnimSession {
const cfg = this.uiInfo?.uiconf?.popAnim as IPopAnimConfig | undefined;
return {
mask: cfg?.mask ?? 'none',
center: cfg?.center ?? 'none',
};
}
}