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/com/GemGrid.ts

146 lines
5.2 KiB

import { _decorator, Component, EventTouch, Label, Node, Sprite, Vec2 } from 'cc';
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad';
import { GBundle, UIID } from '../game/ConfigRes';
const { ccclass } = _decorator;
const LOG = '[GemGrid]';
/** 超过此位移视为拖拽,不弹信息 */
const TAP_THRESHOLD = 18;
/**
* 宝石格子:仓库 / 获得弹窗共用。
* bg=宝石框大{quality};icon=Weapon.icon;lbNum=数量。
* 轻点打开 PopGemInfo(拖拽不触发)。
*/
@ccclass('GemGrid')
export class GemGrid extends Component {
/** 是否响应轻点打开信息 */
canClick = true;
/** 品质框 */
bg: Node = null!;
/** 宝石图标 */
icon: Node = null!;
/** 数量 */
lbNum: Label = null!;
/** 当前宝石配表 */
data: ITableWeapon | null = null;
private _pressing = false;
private _pressStart = new Vec2();
protected onLoad(): void {
this._bindNodes();
}
protected onEnable(): void {
this.node.on(Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.on(Node.EventType.TOUCH_END, this._onTouchEnd, this);
this.node.on(Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
}
protected onDisable(): void {
this.node.off(Node.EventType.TOUCH_START, this._onTouchStart, this);
this.node.off(Node.EventType.TOUCH_END, this._onTouchEnd, this);
this.node.off(Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
this._pressing = false;
}
/**
* 打开宝石信息弹窗。
* @param gemId Weapon.id
*/
static openInfo(gemId: number): void {
const id = Math.floor(Number(gemId) || 0);
if (id <= 0) return;
void gg.ui.openPanel(UIID.PopGemInfo, { data: id });
}
/**
* 绑定展示数据。
* @param data Weapon 行;null 表示空
* @param count 数量;传负数隐藏数量文案
*/
setData(data: ITableWeapon | null, count = 0): void {
this._bindNodes();
this.data = data;
const quality = data ? Math.floor(Number(data.quality) || 0) : 0;
if (!data) {
this._setSprite(this.bg, '', false);
this._setSprite(this.icon, '', true);
if (this.icon?.isValid) this.icon.active = false;
} else {
if (quality < 1 || quality > 5) console.warn(LOG, '品质无对应宝石框大', data.id, quality);
this._setSprite(this.bg, `weapon/宝石框大${quality}`, false);
const iconName = String(data.icon || '').trim();
if (!iconName) console.warn(LOG, 'icon 缺失', data.id);
this._setSprite(this.icon, iconName ? `weapon/${iconName}` : '', true);
if (this.icon?.isValid) this.icon.active = !!iconName;
}
if (this.lbNum?.isValid) {
const showNum = count >= 0;
this.lbNum.node.active = showNum;
if (showNum) this.lbNum.string = `${Math.max(0, count | 0)}`;
}
}
/** 按下 */
private _onTouchStart(e: EventTouch): void {
this._pressing = true;
this._pressStart.set(e.getUILocation());
}
/** 抬起:位移未超阈值则打开信息 */
private _onTouchEnd(e: EventTouch): void {
if (!this._pressing) return;
this._pressing = false;
if (!this.canClick || !this.data) return;
const loc = e.getUILocation();
const dx = loc.x - this._pressStart.x;
const dy = loc.y - this._pressStart.y;
if (dx * dx + dy * dy >= TAP_THRESHOLD * TAP_THRESHOLD) return;
GemGrid.openInfo(Number(this.data.id) || 0);
}
/** 取消按下 */
private _onTouchCancel(): void {
this._pressing = false;
}
/** 绑定子节点 */
private _bindNodes(): void {
if (!this.bg?.isValid) this.bg = this.node.getChildByName('bg')!;
if (!this.icon?.isValid) this.icon = this.node.getChildByName('icon')!;
if (!this.lbNum?.isValid) {
const n = this.node.getChildByName('lbNum');
this.lbNum = n?.getComponent(Label) ?? null!;
}
if (!this.bg) console.warn(LOG, 'bg 节点缺失', this.node?.name);
}
/**
* icons/weapon 下图。
* @param nativeSize true=按贴图原始尺寸(不拉伸);false=铺满节点 UITransform
*/
private _setSprite(node: Node | null, path: string, nativeSize: boolean): void {
if (!node?.isValid) return;
if (!path) {
node.active = false;
node.getComponent(SpriteLoad)?.clear();
const sp = node.getComponent(Sprite);
if (sp) sp.spriteFrame = null;
return;
}
node.active = true;
if (!node.getComponent(Sprite)) node.addComponent(Sprite);
const sp = node.getComponent(Sprite)!;
sp.type = Sprite.Type.SIMPLE;
// icon 用 TRIMMED 跟贴图尺寸,避免 CUSTOM 拉伸变形
sp.sizeMode = nativeSize ? Sprite.SizeMode.TRIMMED : Sprite.SizeMode.CUSTOM;
node.getOrAddComponent(SpriteLoad).setSprite(path, GBundle.Items, () => {
if (!node.isValid || !sp.isValid) return;
sp.sizeMode = nativeSize ? Sprite.SizeMode.TRIMMED : Sprite.SizeMode.CUSTOM;
});
}
}