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/gm/ProjectGmPanels.ts

727 lines
26 KiB

import {
Button, Color, Graphics, Label, Layout, Mask, Node, ScrollView, Sprite, UITransform, Widget,
HorizontalTextAlignment, VerticalTextAlignment, Layers, Overflow,
} from 'cc';
import { SpriteLoad } from '../../mx/components/SpriteLoad';
import type { IGmContentPanel, IGmPanelContext } from '../../mx/module/gm';
import { GmRegistry } from '../../mx/module/gm';
import { GBundle, GPath } from '../game/ConfigRes';
import { TableNames } from '../game/ConfigTableData';
import { battleBuffSlotType } from '../manager/BattleBuffParse';
import { BattleBuffSlotType } from '../manager/battleBuff/BattleBuffTypes';
import { RankDataManager } from '../manager/RankDataManager';
import { ProjectGmActions } from './ProjectGmActions';
import { GmSaveEditorPanel } from './ProjectGmSavePanel';
/** 本项目内容面板 id */
export const ProjectGmPanelId = {
itemPicker: 'itemPicker',
buffPicker: 'buffPicker',
levelPicker: 'levelPicker',
rankPicker: 'rankPicker',
saveEditor: 'saveEditor',
} as const;
/**
* buffPicker 面板数据。
* 新表已无 type 列时 expectType 请传 0,否则列表会被滤空。
*/
export interface IGmBuffPickerData {
/** BattleBuffSlotType:1主动 2被动 3自动;0=不限(推荐) */
expectType: number;
/** 写入目标 */
mode: 'carryPassive' | 'aiActive' | 'aiPassive';
}
const BUFF_C = {
text: new Color(255, 255, 255, 255),
dim: new Color(180, 190, 210, 255),
accent: new Color(255, 220, 70, 255),
rowBg: new Color(28, 36, 56, 255),
rowLine: new Color(100, 160, 240, 160),
rowOn: new Color(255, 220, 70, 255),
btn: new Color(45, 105, 190, 255),
btnClear: new Color(210, 120, 35, 255),
btnBack: new Color(70, 78, 96, 255),
};
const QUALITY_COLOR: { [q: number]: Color } = {
1: new Color(90, 210, 120, 255),
2: new Color(80, 160, 255, 255),
3: new Color(190, 110, 255, 255),
4: new Color(255, 170, 60, 255),
};
const QUALITY_NAME: { [q: number]: string } = {
1: '绿',
2: '蓝',
3: '紫',
4: '橙',
};
const SLOT_NAME: { [t: number]: string } = {
[BattleBuffSlotType.Active]: '主动',
[BattleBuffSlotType.Passive]: '被动',
[BattleBuffSlotType.Auto]: '自动',
};
/**
* 创建文字按钮。
*/
function makeLabelBtn(parent: Node, text: string, w: number, h: number, onClick: () => void): Node {
const n = new Node('btn');
n.layer = Layers.Enum.UI_2D;
n.addComponent(UITransform).setContentSize(w, h);
const lb = n.addComponent(Label);
lb.string = text;
lb.fontSize = 22;
lb.color = Color.WHITE;
lb.horizontalAlign = HorizontalTextAlignment.CENTER;
lb.verticalAlign = VerticalTextAlignment.CENTER;
n.addComponent(Button);
n.on(Button.EventType.CLICK, onClick, null);
parent.addChild(n);
return n;
}
/**
* 垂直滚动列表宿主。
*/
function makeVScroll(parent: Node, w: number, h: number): { host: Node; content: Node } {
const host = new Node('scroll');
host.layer = Layers.Enum.UI_2D;
host.addComponent(UITransform).setContentSize(w, h);
const view = new Node('view');
view.layer = Layers.Enum.UI_2D;
view.addComponent(UITransform).setContentSize(w, h);
view.addComponent(Mask);
host.addChild(view);
const content = new Node('content');
content.layer = Layers.Enum.UI_2D;
const cut = content.addComponent(UITransform);
cut.setContentSize(w, h);
cut.setAnchorPoint(0.5, 1);
content.setPosition(0, h / 2);
const layout = content.addComponent(Layout);
layout.type = Layout.Type.VERTICAL;
layout.resizeMode = Layout.ResizeMode.CONTAINER;
layout.spacingY = 4;
layout.paddingTop = 4;
view.addChild(content);
const sv = host.addComponent(ScrollView);
sv.content = content;
sv.horizontal = false;
sv.vertical = true;
parent.addChild(host);
return { host, content };
}
/**
* 道具图标点选 + 数量步进。
*/
class GmItemPickerPanel implements IGmContentPanel {
private _root: Node | null = null;
private _selectedId = 0;
private _qty = 1;
private _lbSel: Label | null = null;
open(parent: Node, ctx: IGmPanelContext): void {
this.close();
const pUt = parent.getComponent(UITransform);
const W = pUt?.width || 660;
const H = pUt?.height || 900;
this._root = new Node('itemPicker');
this._root.layer = Layers.Enum.UI_2D;
this._root.addComponent(UITransform).setContentSize(W, H);
const rw = this._root.addComponent(Widget);
rw.isAlignLeft = rw.isAlignRight = rw.isAlignTop = rw.isAlignBottom = true;
rw.left = rw.right = rw.top = rw.bottom = 0;
parent.addChild(this._root);
const tip = new Node('tip');
tip.layer = Layers.Enum.UI_2D;
tip.addComponent(UITransform).setContentSize(W - 24, 40);
const tl = tip.addComponent(Label);
tl.string = '点图标立刻 +1 · 底部可一次 +10/+100';
tl.fontSize = 22;
tl.color = new Color(255, 196, 72, 255);
tl.horizontalAlign = HorizontalTextAlignment.CENTER;
tip.setPosition(0, H / 2 - 28);
this._root.addChild(tip);
const barH = 120;
const scrollH = H - 80 - barH;
const { host, content } = makeVScroll(this._root, W - 16, scrollH);
host.setPosition(0, barH / 2 - 10);
const items = gg.data.table.getTableList<ITableItem>(TableNames.Item) ?? [];
items.sort((a, b) => Number(a.id) - Number(b.id));
const cell = 80;
const cols = Math.max(4, Math.floor((W - 24) / (cell + 6)));
let rowNode: Node | null = null;
for (let i = 0; i < items.length; i++) {
if (i % cols === 0) {
rowNode = new Node(`row${i}`);
rowNode.layer = Layers.Enum.UI_2D;
rowNode.addComponent(UITransform).setContentSize(W - 24, cell);
const lay = rowNode.addComponent(Layout);
lay.type = Layout.Type.HORIZONTAL;
lay.spacingX = 6;
content.addChild(rowNode);
}
const row = items[i];
const cellN = new Node(`i${row.id}`);
cellN.layer = Layers.Enum.UI_2D;
cellN.addComponent(UITransform).setContentSize(cell - 4, cell - 4);
const sp = cellN.addComponent(Sprite);
sp.sizeMode = Sprite.SizeMode.CUSTOM;
const loader = cellN.addComponent(SpriteLoad);
if (row.icon) loader.setSprite(GPath.Item(row.icon), GBundle.Items);
cellN.addComponent(Button);
const id = Number(row.id);
const name = row.name ?? '';
cellN.on(Button.EventType.CLICK, () => {
this._selectedId = id;
ProjectGmActions.addItemNum(id, 1);
this._qty = gg.data.getItemNum(id);
this._paint();
ctx.host.toast(`${name} +1 → ${this._qty}`);
}, this);
rowNode!.addChild(cellN);
}
content.getComponent(Layout)?.updateLayout();
const bar = new Node('bar');
bar.layer = Layers.Enum.UI_2D;
bar.addComponent(UITransform).setContentSize(W - 16, barH - 16);
bar.setPosition(0, -H / 2 + barH / 2);
this._root.addChild(bar);
this._lbSel = (() => {
const sel = new Node('sel');
sel.layer = Layers.Enum.UI_2D;
sel.addComponent(UITransform).setContentSize(W - 40, 28);
const lb = sel.addComponent(Label);
lb.fontSize = 20;
lb.color = new Color(180, 220, 255, 255);
lb.horizontalAlign = HorizontalTextAlignment.CENTER;
lb.overflow = Overflow.SHRINK;
sel.setPosition(0, 28);
bar.addChild(sel);
return lb;
})();
makeLabelBtn(bar, '+10', 100, 44, () => {
if (!this._selectedId) {
ctx.host.toast('先点一个图标');
return;
}
ProjectGmActions.addItemNum(this._selectedId, 10);
this._qty = gg.data.getItemNum(this._selectedId);
this._paint();
}).setPosition(-160, -16);
makeLabelBtn(bar, '+100', 100, 44, () => {
if (!this._selectedId) {
ctx.host.toast('先点一个图标');
return;
}
ProjectGmActions.addItemNum(this._selectedId, 100);
this._qty = gg.data.getItemNum(this._selectedId);
this._paint();
}).setPosition(-40, -16);
makeLabelBtn(bar, '返回', 120, 44, () => {
ctx.refreshList();
ctx.goBack();
}).setPosition(120, -16);
this._paint();
}
close(): void {
if (this._root?.isValid) this._root.destroy();
this._root = null;
this._lbSel = null;
}
private _paint(): void {
if (this._lbSel) {
this._lbSel.string = this._selectedId
? `最近:${this._selectedId} 持有 ${gg.data.getItemNum(this._selectedId)}`
: '点图标立刻 +1';
}
}
}
/**
* 词条页:上=未选、下=已选;点击即对调并立刻写入。
*/
class GmBuffPickerPanel implements IGmContentPanel {
private _root: Node | null = null;
private _ctx: IGmPanelContext | null = null;
private _data: IGmBuffPickerData | null = null;
private _listW = 640;
private _allRows: ITableBattlebuff[] = [];
private _selected: number[] = [];
private _availContent: Node | null = null;
private _selContent: Node | null = null;
private _lbAvail: Label | null = null;
private _lbSel: Label | null = null;
open(parent: Node, ctx: IGmPanelContext): void {
this.close();
this._ctx = ctx;
const raw = ctx.command.panelData as IGmBuffPickerData | undefined;
const data: IGmBuffPickerData = {
expectType: raw?.expectType ?? 0,
mode: raw?.mode ?? 'carryPassive',
};
this._data = data;
this._selected = this._loadCurrentIds();
const pUt = parent.getComponent(UITransform);
const W = pUt?.width || 660;
const H = pUt?.height || 900;
this._listW = W - 16;
this._root = new Node('buffPicker');
this._root.layer = Layers.Enum.UI_2D;
this._root.addComponent(UITransform).setContentSize(W, H);
const rw = this._root.addComponent(Widget);
rw.isAlignLeft = rw.isAlignRight = rw.isAlignTop = rw.isAlignBottom = true;
rw.left = rw.right = rw.top = rw.bottom = 0;
parent.addChild(this._root);
const headH = 36;
const gap = 10;
const clearH = 44;
const usable = Math.max(200, H - headH * 2 - gap - clearH - 8);
const availH = Math.floor(usable * 0.58);
const selH = usable - availH;
this._lbAvail = this._addHead(this._root, '未选择(点选加入)', this._listW, headH);
this._lbAvail.node.setPosition(0, H / 2 - headH / 2 - 2);
const { host: availHost, content: availContent } = makeVScroll(this._root, this._listW, availH);
this._availContent = availContent;
const availLay = availContent.getComponent(Layout);
if (availLay) {
availLay.spacingY = 8;
availLay.paddingBottom = 12;
}
availHost.setPosition(0, H / 2 - headH - availH / 2 - 4);
const selTopY = -H / 2 + clearH + selH + headH + 4;
this._lbSel = this._addHead(this._root, '已选择', this._listW, headH);
this._lbSel.node.setPosition(0, selTopY - headH / 2);
const { host: selHost, content: selContent } = makeVScroll(this._root, this._listW, selH);
this._selContent = selContent;
const selLay = selContent.getComponent(Layout);
if (selLay) {
selLay.spacingY = 8;
selLay.paddingBottom = 12;
}
selHost.setPosition(0, -H / 2 + clearH + selH / 2);
this._pillBtn(this._root, '清空已选', 200, 40, BUFF_C.btnClear, () => this._clearSelected())
.setPosition(0, -H / 2 + clearH / 2);
this._allRows = [];
const list = gg.data.table.getTableList<ITableBattlebuff>(TableNames.Battlebuff) ?? [];
list.sort((a, b) => Number(a.id) - Number(b.id));
for (let i = 0; i < list.length; i++) {
const row = list[i];
const id = Math.floor(Number(row.id) || 0);
if (id <= 0) continue;
const slot = battleBuffSlotType(row);
if (data.expectType > 0 && slot !== data.expectType) continue;
this._allRows.push(row);
}
if (this._allRows.length <= 0) {
console.warn('[GM] buffPicker 列表为空', data);
}
this._rebuildLists();
}
close(): void {
if (this._root?.isValid) this._root.destroy();
this._root = null;
this._ctx = null;
this._data = null;
this._allRows = [];
this._selected = [];
this._availContent = null;
this._selContent = null;
this._lbAvail = null;
this._lbSel = null;
}
/** 读取当前已生效 id */
private _loadCurrentIds(): number[] {
if (!this._data) return [];
if (this._data.mode === 'carryPassive') return ProjectGmActions.getCarryBuffIds();
const cur = this._data.mode === 'aiActive'
? gg.game.gmAiActiveBuffIds
: gg.game.gmAiPassiveBuffIds;
return cur?.length ? cur.slice() : [];
}
private _hasId(id: number): boolean {
for (let i = 0; i < this._selected.length; i++) {
if (this._selected[i] === id) return true;
}
return false;
}
/** 点击未选 → 加入;点击已选 → 移除;立刻写入 */
private _move(id: number, toSelected: boolean): void {
if (toSelected) {
if (!this._hasId(id)) this._selected.push(id);
} else {
const next: number[] = [];
for (let i = 0; i < this._selected.length; i++) {
if (this._selected[i] !== id) next.push(this._selected[i]);
}
this._selected = next;
}
this._applyNow();
this._rebuildLists();
}
private _clearSelected(): void {
this._selected = [];
this._applyNow();
this._rebuildLists();
}
private _applyNow(): void {
if (!this._data) return;
const ids = this._selected.slice();
if (this._data.mode === 'carryPassive') {
ProjectGmActions.setCarryBuffIds(ids, true);
} else if (this._data.mode === 'aiActive') {
ProjectGmActions.setAiBuffIds(ids.length ? ids : null, true);
} else {
ProjectGmActions.setAiBuffIds(ids.length ? ids : null, false);
}
}
private _rebuildLists(): void {
if (!this._availContent?.isValid || !this._selContent?.isValid) return;
this._availContent.removeAllChildren();
this._selContent.removeAllChildren();
let availN = 0;
let selN = 0;
for (let i = 0; i < this._allRows.length; i++) {
const row = this._allRows[i];
const id = Math.floor(Number(row.id) || 0);
if (this._hasId(id)) {
this._addBuffCard(this._selContent, this._listW, row, false);
selN++;
} else {
this._addBuffCard(this._availContent, this._listW, row, true);
availN++;
}
}
if (availN <= 0) this._addEmptyHint(this._availContent, '已全部选中');
if (selN <= 0) this._addEmptyHint(this._selContent, '点击上方加入');
if (this._lbAvail) this._lbAvail.string = `未选择 ${availN}(点选加入)`;
if (this._lbSel) this._lbSel.string = `已选择 ${selN}(点选移除)`;
this._availContent.getComponent(Layout)?.updateLayout();
this._selContent.getComponent(Layout)?.updateLayout();
}
private _addEmptyHint(parent: Node, text: string): void {
const n = new Node('empty');
n.layer = Layers.Enum.UI_2D;
n.addComponent(UITransform).setContentSize(this._listW, 48);
const lb = n.addComponent(Label);
lb.string = text;
lb.fontSize = 22;
lb.color = BUFF_C.dim;
lb.horizontalAlign = HorizontalTextAlignment.CENTER;
parent.addChild(n);
}
private _addHead(parent: Node, text: string, w: number, h: number): Label {
const n = new Node('head');
n.layer = Layers.Enum.UI_2D;
n.addComponent(UITransform).setContentSize(w, h);
const lb = n.addComponent(Label);
lb.string = text;
lb.fontSize = 24;
lb.isBold = true;
lb.color = BUFF_C.accent;
lb.horizontalAlign = HorizontalTextAlignment.LEFT;
lb.verticalAlign = VerticalTextAlignment.CENTER;
lb.overflow = Overflow.CLAMP;
parent.addChild(n);
return lb;
}
/**
* @param toSelected true=点后加入已选;false=点后移回未选
*/
private _addBuffCard(parent: Node, w: number, row: ITableBattlebuff, toSelected: boolean): void {
const h = 84;
const id = Math.floor(Number(row.id) || 0);
const name = String(row.name ?? '');
const desc = String(row.desc ?? '');
const q = Math.max(0, Math.floor(Number(row.quality) || 0));
const slot = battleBuffSlotType(row);
const qColor = QUALITY_COLOR[q] || BUFF_C.dim;
const qName = QUALITY_NAME[q] || `Q${q}`;
const slotName = slot != null ? (SLOT_NAME[slot] || `t${slot}`) : '?';
const card = new Node(`buff${id}`);
card.layer = Layers.Enum.UI_2D;
card.addComponent(UITransform).setContentSize(w, h);
this._drawRound(card, BUFF_C.rowBg, w, h, 12, toSelected ? BUFF_C.rowLine : BUFF_C.rowOn);
const iconSz = 56;
const iconN = new Node('icon');
iconN.layer = Layers.Enum.UI_2D;
iconN.addComponent(UITransform).setContentSize(iconSz, iconSz);
const sp = iconN.addComponent(Sprite);
sp.sizeMode = Sprite.SizeMode.CUSTOM;
const loader = iconN.addComponent(SpriteLoad);
const iconName = String(row.icon || row.name || '').trim();
if (iconName) loader.setSprite(GPath.ShopSkill(iconName), GBundle.Items);
iconN.setPosition(-w / 2 + iconSz / 2 + 10, 0);
card.addChild(iconN);
const textW = w - iconSz - 28;
const head = new Node('head');
head.layer = Layers.Enum.UI_2D;
head.addComponent(UITransform).setContentSize(textW, 30);
const hl = head.addComponent(Label);
hl.string = `${id} ${name} · ${qName}/${slotName}`;
hl.fontSize = 22;
hl.isBold = true;
hl.color = qColor;
hl.horizontalAlign = HorizontalTextAlignment.LEFT;
hl.verticalAlign = VerticalTextAlignment.CENTER;
hl.overflow = Overflow.CLAMP;
hl.enableWrapText = false;
head.setPosition(iconSz / 2 + 4, 16);
card.addChild(head);
const body = new Node('desc');
body.layer = Layers.Enum.UI_2D;
body.addComponent(UITransform).setContentSize(textW, 34);
const bl = body.addComponent(Label);
bl.string = desc || '(无描述)';
bl.fontSize = 17;
bl.color = BUFF_C.dim;
bl.horizontalAlign = HorizontalTextAlignment.LEFT;
bl.verticalAlign = VerticalTextAlignment.TOP;
bl.overflow = Overflow.CLAMP;
bl.enableWrapText = true;
body.setPosition(iconSz / 2 + 4, -16);
card.addChild(body);
card.addComponent(Button);
card.on(Button.EventType.CLICK, () => this._move(id, toSelected), this);
parent.addChild(card);
}
private _pillBtn(parent: Node, text: string, w: number, h: number, bg: Color, onClick: () => void): Node {
const n = new Node(text);
n.layer = Layers.Enum.UI_2D;
n.addComponent(UITransform).setContentSize(w, h);
this._drawRound(n, bg, w, h, 10);
const lbN = new Node('lb');
lbN.layer = Layers.Enum.UI_2D;
lbN.addComponent(UITransform).setContentSize(w - 6, h - 4);
const lb = lbN.addComponent(Label);
lb.string = text;
lb.fontSize = 22;
lb.isBold = true;
lb.color = BUFF_C.text;
lb.horizontalAlign = HorizontalTextAlignment.CENTER;
lb.verticalAlign = VerticalTextAlignment.CENTER;
n.addChild(lbN);
n.addComponent(Button);
n.on(Button.EventType.CLICK, onClick, this);
parent.addChild(n);
return n;
}
private _drawRound(node: Node, fill: Color, w: number, h: number, r: number, stroke?: Color): void {
const g = node.getComponent(Graphics) || node.addComponent(Graphics);
g.clear();
g.fillColor = fill;
g.roundRect(-w / 2, -h / 2, w, h, r);
g.fill();
if (stroke) {
g.strokeColor = stroke;
g.lineWidth = stroke === BUFF_C.rowOn ? 3 : 2;
g.roundRect(-w / 2, -h / 2, w, h, r);
g.stroke();
}
}
}
/**
* 关卡列表点选。
*/
class GmLevelPickerPanel implements IGmContentPanel {
private _root: Node | null = null;
open(parent: Node, ctx: IGmPanelContext): void {
this.close();
this._root = new Node('levelPicker');
this._root.layer = Layers.Enum.UI_2D;
this._root.addComponent(UITransform).setContentSize(660, 900);
parent.addChild(this._root);
const title = new Node('t');
title.layer = Layers.Enum.UI_2D;
title.addComponent(UITransform).setContentSize(600, 36);
const tl = title.addComponent(Label);
tl.string = ctx.command.title;
tl.fontSize = 26;
tl.color = Color.WHITE;
tl.horizontalAlign = HorizontalTextAlignment.CENTER;
title.setPosition(0, 420);
this._root.addChild(title);
const { host, content } = makeVScroll(this._root, 640, 700);
host.setPosition(0, 20);
makeLabelBtn(content, '0 关闭固定(随机)', 620, 44, () => {
ProjectGmActions.setFixedMap(0);
ctx.refreshList();
ctx.goBack();
});
const list = gg.data.table.getTableList<ITableLevel>(TableNames.Level) ?? [];
list.sort((a, b) => Number(a.id) - Number(b.id));
for (let i = 0; i < list.length; i++) {
const row = list[i];
const id = Number(row.id);
const name = row.name ?? '';
makeLabelBtn(content, `${id} ${name}`, 620, 44, () => {
ProjectGmActions.setFixedMap(id);
ctx.refreshList();
ctx.goBack();
});
}
content.getComponent(Layout)?.updateLayout();
makeLabelBtn(this._root, '返回', 140, 44, () => ctx.goBack()).setPosition(0, -400);
}
close(): void {
if (this._root?.isValid) this._root.destroy();
this._root = null;
}
}
/**
* 段位点选 + 星级步进。
*/
class GmRankPickerPanel implements IGmContentPanel {
private _root: Node | null = null;
private _rankId = 1;
private _star = 1;
private _lb: Label | null = null;
open(parent: Node, ctx: IGmPanelContext): void {
this.close();
this._rankId = RankDataManager.getPlayerRankId() || 1;
this._star = RankDataManager.getIntraTierStars() || 1;
this._root = new Node('rankPicker');
this._root.layer = Layers.Enum.UI_2D;
this._root.addComponent(UITransform).setContentSize(660, 900);
parent.addChild(this._root);
const title = new Node('t');
title.layer = Layers.Enum.UI_2D;
title.addComponent(UITransform).setContentSize(600, 36);
const tl = title.addComponent(Label);
tl.string = ctx.command.title;
tl.fontSize = 26;
tl.color = Color.WHITE;
tl.horizontalAlign = HorizontalTextAlignment.CENTER;
title.setPosition(0, 420);
this._root.addChild(title);
const cur = new Node('cur');
cur.layer = Layers.Enum.UI_2D;
cur.addComponent(UITransform).setContentSize(600, 36);
this._lb = cur.addComponent(Label);
this._lb.fontSize = 24;
this._lb.color = Color.YELLOW;
this._lb.horizontalAlign = HorizontalTextAlignment.CENTER;
cur.setPosition(0, 360);
this._root.addChild(cur);
const { host, content } = makeVScroll(this._root, 640, 480);
host.setPosition(0, 40);
const list = gg.data.table.getTableList<ITableRank>(TableNames.Rank) ?? [];
list.sort((a, b) => Number(a.id) - Number(b.id));
for (let i = 0; i < list.length; i++) {
const row = list[i];
const id = Number(row.id);
const name = row.name ?? '';
makeLabelBtn(content, `${id} ${name}`, 620, 44, () => {
this._rankId = id;
this._paint();
});
}
content.getComponent(Layout)?.updateLayout();
makeLabelBtn(this._root, '星-1', 100, 40, () => {
this._star = Math.max(1, this._star - 1);
this._paint();
}).setPosition(-160, -260);
makeLabelBtn(this._root, '星+1', 100, 40, () => {
this._star = Math.min(5, this._star + 1);
this._paint();
}).setPosition(-40, -260);
makeLabelBtn(this._root, '应用', 120, 44, () => {
ProjectGmActions.setRankAndStar(this._rankId, this._star);
ctx.refreshList();
ctx.goBack();
}).setPosition(100, -260);
makeLabelBtn(this._root, '返回', 120, 44, () => ctx.goBack()).setPosition(0, -320);
this._paint();
}
close(): void {
if (this._root?.isValid) this._root.destroy();
this._root = null;
this._lb = null;
}
private _paint(): void {
if (this._lb) this._lb.string = `段位 ${this._rankId} 星 ${this._star}`;
}
}
/**
* 注册本项目内容面板。
*/
export class ProjectGmPanels {
private static _done = false;
/** 幂等注册 */
static ensureRegistered(): void {
if (this._done) return;
this._done = true;
GmRegistry.registerPanel(ProjectGmPanelId.itemPicker, () => new GmItemPickerPanel());
GmRegistry.registerPanel(ProjectGmPanelId.buffPicker, () => new GmBuffPickerPanel());
GmRegistry.registerPanel(ProjectGmPanelId.levelPicker, () => new GmLevelPickerPanel());
GmRegistry.registerPanel(ProjectGmPanelId.rankPicker, () => new GmRankPickerPanel());
GmRegistry.registerPanel(ProjectGmPanelId.saveEditor, () => new GmSaveEditorPanel());
}
}