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.
467 lines
16 KiB
467 lines
16 KiB
|
1 week ago
|
|
||
|
|
//*********************
|
||
|
|
// create by 流云
|
||
|
|
// time: Wed Oct 07 2026
|
||
|
|
// desc: 宝石镶嵌 / 仓库 / 一键合成
|
||
|
|
//*********************
|
||
|
|
import { _decorator, EventMouse, EventTouch, Input, input, instantiate, Node, ScrollView, sp, Sprite, UIOpacity, UITransform, Vec2, Vec3 } from 'cc';
|
||
|
|
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad';
|
||
|
|
import { ensureSpineSkeletonDataRuntime } from 'db://assets/mx/module/lang/spineRuntimePatch';
|
||
|
|
import { GemGrid } from '../../com/GemGrid';
|
||
|
|
import { GBundle, UIID } from '../../game/ConfigRes';
|
||
|
|
import { GEM_SLOT_COUNT, IGemBagEntry } from '../../game/GameDataEnums';
|
||
|
|
import { Auto_PanelGemstone } from './Auto_PanelGemstone';
|
||
|
|
const { ccclass } = _decorator;
|
||
|
|
|
||
|
|
const LOG = '[PanelGemstone]';
|
||
|
|
const DRAG_THRESHOLD = 18;
|
||
|
|
const GHOST_OPACITY = 180;
|
||
|
|
const ELEMENT_COUNT = 5;
|
||
|
|
const SLOT_NAMES = ['g1', 'g2', 'g3', 'g4'];
|
||
|
|
const ELEMENT_SKINS = ['', '金', '木', '水', '火', '土'];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 宝石页:五行镶嵌 + 仓库筛选 + 拖拽装备/卸下 + 一键合成。
|
||
|
|
*/
|
||
|
|
@ccclass('UIPanelGemstone')
|
||
|
|
export class UIPanelGemstone extends Auto_PanelGemstone {
|
||
|
|
|
||
|
|
/** 五行格子模板 */
|
||
|
|
private _itemTpl: Node | null = null;
|
||
|
|
/** 仓库格子模板 */
|
||
|
|
private _bagTpl: Node | null = null;
|
||
|
|
/** 已创建的五行格 */
|
||
|
|
private _elementItems: Node[] = [];
|
||
|
|
/** 仓库动态格 */
|
||
|
|
private _bagItems: Node[] = [];
|
||
|
|
/** 当前筛选:0全部 1通用 2~6五行 */
|
||
|
|
private _filterType = 0;
|
||
|
|
/** 仓库数据 */
|
||
|
|
private _bagList: IGemBagEntry[] = [];
|
||
|
|
/** ScrollView 节点(卸下命中区) */
|
||
|
|
private _scrollNode: Node | null = null;
|
||
|
|
|
||
|
|
private _pressing = false;
|
||
|
|
private _dragging = false;
|
||
|
|
private _dragStart = new Vec2();
|
||
|
|
private _hitPos = new Vec2();
|
||
|
|
private _ghostPos = new Vec3();
|
||
|
|
private _ghost: Node | null = null;
|
||
|
|
private _dragListening = false;
|
||
|
|
/** 拖中的宝石 id */
|
||
|
|
private _dragGemId = 0;
|
||
|
|
/** 从槽拖出:五行 1~5;0=仓库 */
|
||
|
|
private _dragFromElement = 0;
|
||
|
|
/** 从槽拖出:槽下标 0~3;-1=仓库 */
|
||
|
|
private _dragFromSlot = -1;
|
||
|
|
|
||
|
|
onLoad(): void {
|
||
|
|
super.onLoad();
|
||
|
|
this._itemTpl = this.ui_list?.getChildByName('itemTemplate') ?? null;
|
||
|
|
if (this._itemTpl) {
|
||
|
|
this._itemTpl.active = false;
|
||
|
|
}
|
||
|
|
this._bagTpl = this.ui_content?.getChildByName('bagItemTemplate') ?? null;
|
||
|
|
if (this._bagTpl) {
|
||
|
|
this._bagTpl.active = false;
|
||
|
|
}
|
||
|
|
this._scrollNode = this.ui_content?.parent?.parent ?? null;
|
||
|
|
this._bindDrag(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
onEnable(): void {
|
||
|
|
super.onEnable();
|
||
|
|
this._bindDrag(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
onDisable(): void {
|
||
|
|
this._bindDrag(false);
|
||
|
|
this._endDrag();
|
||
|
|
super.onDisable();
|
||
|
|
}
|
||
|
|
|
||
|
|
onInit(): void {
|
||
|
|
this._filterType = 0;
|
||
|
|
this._selectTag(this.btnAll);
|
||
|
|
void this._refresh();
|
||
|
|
}
|
||
|
|
|
||
|
|
click_btnClose(): void {
|
||
|
|
void this.close(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
click_btnAll(): void { this._onTag(0, this.btnAll); }
|
||
|
|
click_btn0(): void { this._onTag(1, this.btn0); }
|
||
|
|
click_btn1(): void { this._onTag(2, this.btn1); }
|
||
|
|
click_btn2(): void { this._onTag(3, this.btn2); }
|
||
|
|
click_btn3(): void { this._onTag(4, this.btn3); }
|
||
|
|
click_btn4(): void { this._onTag(5, this.btn4); }
|
||
|
|
click_btn5(): void { this._onTag(6, this.btn5); }
|
||
|
|
|
||
|
|
click_btnFuse(): void {
|
||
|
|
const gains = gg.gem.fuseAll();
|
||
|
|
this._refreshBag();
|
||
|
|
this._refreshAllSlots();
|
||
|
|
if (!gains.length) {
|
||
|
|
gg.ui.showToast('没有可合成的宝石');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
void gg.ui.openPanel(UIID.PopGetGem, { data: gains });
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 筛选切换 */
|
||
|
|
private _onTag(filterType: number, btn: Node): void {
|
||
|
|
this._filterType = filterType;
|
||
|
|
this._selectTag(btn);
|
||
|
|
this._refreshBag();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 标签底移到当前按钮 */
|
||
|
|
private _selectTag(btn: Node | null): void {
|
||
|
|
if (!this.ui_tagBtnBg?.isValid || !btn?.isValid) return;
|
||
|
|
this.ui_tagBtnBg.setWorldPosition(btn.worldPosition);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 全量刷新 */
|
||
|
|
private async _refresh(): Promise<void> {
|
||
|
|
await gg.gem.ensureTable();
|
||
|
|
if (!this.isValid) return;
|
||
|
|
this._buildElements();
|
||
|
|
this._refreshBag();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 实例化五行 */
|
||
|
|
private _buildElements(): void {
|
||
|
|
if (!this.ui_list?.isValid || !this._itemTpl?.isValid) {
|
||
|
|
console.warn(LOG, 'ui_list/itemTemplate 缺失');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (let i = 0; i < this._elementItems.length; i++) {
|
||
|
|
const n = this._elementItems[i];
|
||
|
|
if (n?.isValid) n.destroy();
|
||
|
|
}
|
||
|
|
this._elementItems.length = 0;
|
||
|
|
for (let e = 1; e <= ELEMENT_COUNT; e++) {
|
||
|
|
const node = instantiate(this._itemTpl);
|
||
|
|
node.parent = this.ui_list;
|
||
|
|
node.active = true;
|
||
|
|
node.name = `element_${e}`;
|
||
|
|
(node as any)._element = e;
|
||
|
|
this._applyNumSkin(node, e);
|
||
|
|
this._refreshElementSlots(node, e);
|
||
|
|
this._elementItems.push(node);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** numSkin 切五行皮肤 */
|
||
|
|
private _applyNumSkin(item: Node, element: number): void {
|
||
|
|
const skinNode = item.getChildByName('numSkin');
|
||
|
|
const sk = skinNode?.getComponent(sp.Skeleton);
|
||
|
|
if (!sk) {
|
||
|
|
console.warn(LOG, 'numSkin Skeleton 缺失', element);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const skin = ELEMENT_SKINS[element] || '';
|
||
|
|
if (!skin) {
|
||
|
|
console.warn(LOG, '五行皮肤名无效', element);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (sk.skeletonData) ensureSpineSkeletonDataRuntime(sk.skeletonData);
|
||
|
|
try {
|
||
|
|
sk.setSkin(skin);
|
||
|
|
sk.setSlotsToSetupPose();
|
||
|
|
if (sk.findAnimation('待机')) sk.setAnimation(0, '待机', true);
|
||
|
|
} catch (err) {
|
||
|
|
console.warn(LOG, 'setSkin 失败', skin, err);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 刷新某一行五行的 4 槽 */
|
||
|
|
private _refreshElementSlots(item: Node, element: number): void {
|
||
|
|
const slots = gg.gem.getElementSlots(element);
|
||
|
|
for (let s = 0; s < GEM_SLOT_COUNT; s++) {
|
||
|
|
const slotNode = item.getChildByName(SLOT_NAMES[s]);
|
||
|
|
if (!slotNode?.isValid) {
|
||
|
|
console.warn(LOG, '镶嵌位缺失', SLOT_NAMES[s], element);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
(slotNode as any)._element = element;
|
||
|
|
(slotNode as any)._slot = s;
|
||
|
|
this._paintSlot(slotNode, slots[s] || 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 刷新全部镶嵌 */
|
||
|
|
private _refreshAllSlots(): void {
|
||
|
|
for (let i = 0; i < this._elementItems.length; i++) {
|
||
|
|
const item = this._elementItems[i];
|
||
|
|
const e = Number((item as any)?._element) || (i + 1);
|
||
|
|
this._refreshElementSlots(item, e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 画单个镶嵌位 */
|
||
|
|
private _paintSlot(slotNode: Node, gemId: number): void {
|
||
|
|
const bg = slotNode.getChildByName('bg');
|
||
|
|
const icon = slotNode.getChildByName('icon');
|
||
|
|
const conf = gemId > 0 ? gg.gem.getGem(gemId) : null;
|
||
|
|
const quality = conf ? Math.floor(Number(conf.quality) || 0) : 0;
|
||
|
|
this._setWeaponSprite(bg, `weapon/宝石框小${Math.max(0, Math.min(5, quality))}`);
|
||
|
|
const iconName = conf ? String(conf.icon || '').trim() : '';
|
||
|
|
if (conf && !iconName) console.warn(LOG, 'icon 缺失', gemId);
|
||
|
|
this._setWeaponSprite(icon, iconName ? `weapon/${iconName}` : '');
|
||
|
|
if (icon?.isValid) icon.active = !!iconName;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 刷新仓库 */
|
||
|
|
private _refreshBag(): void {
|
||
|
|
if (!this.ui_content?.isValid || !this._bagTpl?.isValid) {
|
||
|
|
console.warn(LOG, 'ui_content/bagItemTemplate 缺失');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (let i = 0; i < this._bagItems.length; i++) {
|
||
|
|
const n = this._bagItems[i];
|
||
|
|
if (n?.isValid) n.destroy();
|
||
|
|
}
|
||
|
|
this._bagItems.length = 0;
|
||
|
|
this._bagList = gg.gem.getBagList(this._filterType);
|
||
|
|
for (let i = 0; i < this._bagList.length; i++) {
|
||
|
|
const entry = this._bagList[i];
|
||
|
|
const node = instantiate(this._bagTpl);
|
||
|
|
node.parent = this.ui_content;
|
||
|
|
node.active = true;
|
||
|
|
const grid = node.getComponent(GemGrid) || node.addComponent(GemGrid);
|
||
|
|
grid.setData(gg.gem.getGem(entry.gemId), entry.count);
|
||
|
|
(node as any)._gemId = entry.gemId;
|
||
|
|
this._bagItems.push(node);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** icons/weapon */
|
||
|
|
private _setWeaponSprite(node: Node | null, path: string): void {
|
||
|
|
if (!node?.isValid) return;
|
||
|
|
if (!path) {
|
||
|
|
node.getComponent(SpriteLoad)?.clear();
|
||
|
|
const spComp = node.getComponent(Sprite);
|
||
|
|
if (spComp) spComp.spriteFrame = null;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!node.getComponent(Sprite)) node.addComponent(Sprite);
|
||
|
|
node.getOrAddComponent(SpriteLoad).setSprite(path, GBundle.Items);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---------- 拖拽 ----------
|
||
|
|
|
||
|
|
private _bindDrag(on: boolean): void {
|
||
|
|
if (this._dragListening === on) return;
|
||
|
|
this._dragListening = on;
|
||
|
|
if (on) {
|
||
|
|
this.node.on(Node.EventType.TOUCH_START, this._onTouchStart, this, true);
|
||
|
|
this.node.on(Node.EventType.TOUCH_MOVE, this._onTouchMove, this, true);
|
||
|
|
this.node.on(Node.EventType.TOUCH_END, this._onTouchEnd, this, true);
|
||
|
|
this.node.on(Node.EventType.TOUCH_CANCEL, this._onTouchEnd, this, true);
|
||
|
|
input.on(Input.EventType.MOUSE_DOWN, this._onMouseDown, this);
|
||
|
|
input.on(Input.EventType.MOUSE_MOVE, this._onMouseMove, this);
|
||
|
|
input.on(Input.EventType.MOUSE_UP, this._onMouseUp, this);
|
||
|
|
} else {
|
||
|
|
this.node.off(Node.EventType.TOUCH_START, this._onTouchStart, this, true);
|
||
|
|
this.node.off(Node.EventType.TOUCH_MOVE, this._onTouchMove, this, true);
|
||
|
|
this.node.off(Node.EventType.TOUCH_END, this._onTouchEnd, this, true);
|
||
|
|
this.node.off(Node.EventType.TOUCH_CANCEL, this._onTouchEnd, this, true);
|
||
|
|
input.off(Input.EventType.MOUSE_DOWN, this._onMouseDown, this);
|
||
|
|
input.off(Input.EventType.MOUSE_MOVE, this._onMouseMove, this);
|
||
|
|
input.off(Input.EventType.MOUSE_UP, this._onMouseUp, this);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private _onTouchStart(e: EventTouch): void { this._pointerStart(e.getUILocation()); }
|
||
|
|
private _onTouchMove(e: EventTouch): void { this._pointerMove(e.getUILocation()); }
|
||
|
|
private _onTouchEnd(e: EventTouch): void { this._pointerEnd(e.getUILocation()); }
|
||
|
|
|
||
|
|
private _onMouseDown(e: EventMouse): void {
|
||
|
|
if (e.getButton() !== EventMouse.BUTTON_LEFT) return;
|
||
|
|
this._pointerStart(e.getUILocation());
|
||
|
|
}
|
||
|
|
private _onMouseMove(e: EventMouse): void { this._pointerMove(e.getUILocation()); }
|
||
|
|
private _onMouseUp(e: EventMouse): void { this._pointerEnd(e.getUILocation()); }
|
||
|
|
|
||
|
|
private _pointerStart(loc: Vec2): void {
|
||
|
|
if (this._pressing || this._dragging) return;
|
||
|
|
const bag = this._hitBag(loc);
|
||
|
|
if (bag) {
|
||
|
|
const gemId = Number((bag as any)._gemId) || 0;
|
||
|
|
if (gemId <= 0) return;
|
||
|
|
this._resetDrag();
|
||
|
|
this._pressing = true;
|
||
|
|
this._dragStart.set(loc);
|
||
|
|
this._dragGemId = gemId;
|
||
|
|
this._dragFromElement = 0;
|
||
|
|
this._dragFromSlot = -1;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const slot = this._hitSlot(loc);
|
||
|
|
if (!slot) return;
|
||
|
|
const element = Number((slot as any)._element) || 0;
|
||
|
|
const si = Number((slot as any)._slot);
|
||
|
|
if (element <= 0 || si < 0) return;
|
||
|
|
const gemId = gg.gem.getSlotGem(element, si);
|
||
|
|
if (gemId <= 0) return;
|
||
|
|
this._resetDrag();
|
||
|
|
this._pressing = true;
|
||
|
|
this._dragStart.set(loc);
|
||
|
|
this._dragGemId = gemId;
|
||
|
|
this._dragFromElement = element;
|
||
|
|
this._dragFromSlot = si;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _pointerMove(loc: Vec2): void {
|
||
|
|
if (this._dragging) {
|
||
|
|
this._moveGhost(loc);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!this._pressing || this._dragGemId <= 0) return;
|
||
|
|
const dx = loc.x - this._dragStart.x;
|
||
|
|
const dy = loc.y - this._dragStart.y;
|
||
|
|
if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) return;
|
||
|
|
this._beginDrag(loc);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _pointerEnd(loc: Vec2): void {
|
||
|
|
if (!this._pressing && !this._dragging) return;
|
||
|
|
if (this._dragging) {
|
||
|
|
this._finishDrag(loc);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this._endDrag();
|
||
|
|
}
|
||
|
|
|
||
|
|
private _beginDrag(loc: Vec2): void {
|
||
|
|
this._dragging = true;
|
||
|
|
this._setScrollEnabled(false);
|
||
|
|
this._spawnGhost(loc);
|
||
|
|
this._moveGhost(loc);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _finishDrag(loc: Vec2): void {
|
||
|
|
const gemId = this._dragGemId;
|
||
|
|
const fromE = this._dragFromElement;
|
||
|
|
const fromS = this._dragFromSlot;
|
||
|
|
const toSlot = this._hitSlot(loc);
|
||
|
|
const toBag = this._hitBagArea(loc);
|
||
|
|
this._endDrag();
|
||
|
|
if (gemId <= 0) return;
|
||
|
|
|
||
|
|
if (toSlot) {
|
||
|
|
const te = Number((toSlot as any)._element) || 0;
|
||
|
|
const ts = Number((toSlot as any)._slot);
|
||
|
|
if (te <= 0 || ts < 0) return;
|
||
|
|
if (fromE > 0 && fromS >= 0) {
|
||
|
|
if (fromE === te && fromS === ts) return;
|
||
|
|
if (!gg.gem.swapSlots(fromE, fromS, te, ts)) {
|
||
|
|
gg.ui.showToast('无法镶嵌到该位置');
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (!gg.gem.wearFromBag(te, ts, gemId)) {
|
||
|
|
gg.ui.showToast('无法镶嵌到该位置');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
this._refreshAllSlots();
|
||
|
|
this._refreshBag();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (fromE > 0 && fromS >= 0 && toBag) {
|
||
|
|
gg.gem.unequip(fromE, fromS);
|
||
|
|
this._refreshAllSlots();
|
||
|
|
this._refreshBag();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private _spawnGhost(loc: Vec2): void {
|
||
|
|
this._clearGhost();
|
||
|
|
const tpl = this._bagTpl;
|
||
|
|
if (!tpl?.isValid) return;
|
||
|
|
const conf = gg.gem.getGem(this._dragGemId);
|
||
|
|
if (!conf) return;
|
||
|
|
const ghost = instantiate(tpl);
|
||
|
|
ghost.parent = this.node;
|
||
|
|
ghost.active = true;
|
||
|
|
const grid = ghost.getComponent(GemGrid) || ghost.addComponent(GemGrid);
|
||
|
|
grid.setData(conf, -1);
|
||
|
|
const op = ghost.getComponent(UIOpacity) || ghost.addComponent(UIOpacity);
|
||
|
|
op.opacity = GHOST_OPACITY;
|
||
|
|
const ut = ghost.getComponent(UITransform);
|
||
|
|
if (ut) ut.hitTest = () => false;
|
||
|
|
this._ghost = ghost;
|
||
|
|
this._moveGhost(loc);
|
||
|
|
}
|
||
|
|
|
||
|
|
private _moveGhost(loc: Vec2): void {
|
||
|
|
if (this._ghost?.isValid) {
|
||
|
|
this._ghost.setWorldPosition(this._ghostPos.set(loc.x, loc.y, 0));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private _clearGhost(): void {
|
||
|
|
if (this._ghost?.isValid) this._ghost.destroy();
|
||
|
|
this._ghost = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _endDrag(): void {
|
||
|
|
this._clearGhost();
|
||
|
|
this._setScrollEnabled(true);
|
||
|
|
this._resetDrag();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 拖拽时禁用仓库滚动 */
|
||
|
|
private _setScrollEnabled(on: boolean): void {
|
||
|
|
const sv = this._scrollNode?.getComponent(ScrollView);
|
||
|
|
if (sv) sv.enabled = on;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _resetDrag(): void {
|
||
|
|
this._pressing = false;
|
||
|
|
this._dragging = false;
|
||
|
|
this._dragGemId = 0;
|
||
|
|
this._dragFromElement = 0;
|
||
|
|
this._dragFromSlot = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _hitBag(loc: Vec2): Node | null {
|
||
|
|
if (!this.ui_content?.isValid) return null;
|
||
|
|
this._hitPos.set(loc.x, loc.y);
|
||
|
|
const kids = this._bagItems;
|
||
|
|
for (let i = kids.length - 1; i >= 0; i--) {
|
||
|
|
const child = kids[i];
|
||
|
|
if (!child?.activeInHierarchy) continue;
|
||
|
|
const ut = child.getComponent(UITransform);
|
||
|
|
if (ut?.getBoundingBoxToWorld().contains(this._hitPos)) return child;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private _hitSlot(loc: Vec2): Node | null {
|
||
|
|
this._hitPos.set(loc.x, loc.y);
|
||
|
|
for (let i = 0; i < this._elementItems.length; i++) {
|
||
|
|
const item = this._elementItems[i];
|
||
|
|
if (!item?.activeInHierarchy) continue;
|
||
|
|
for (let s = 0; s < SLOT_NAMES.length; s++) {
|
||
|
|
const slot = item.getChildByName(SLOT_NAMES[s]);
|
||
|
|
if (!slot?.activeInHierarchy) continue;
|
||
|
|
const ut = slot.getComponent(UITransform);
|
||
|
|
if (ut?.getBoundingBoxToWorld().contains(this._hitPos)) return slot;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 是否落在仓库 ScrollView 区域 */
|
||
|
|
private _hitBagArea(loc: Vec2): boolean {
|
||
|
|
const root = this._scrollNode;
|
||
|
|
if (!root?.isValid) return false;
|
||
|
|
this._hitPos.set(loc.x, loc.y);
|
||
|
|
const ut = root.getComponent(UITransform);
|
||
|
|
return !!ut?.getBoundingBoxToWorld().contains(this._hitPos);
|
||
|
|
}
|
||
|
|
}
|