import { _decorator, Component, Node, Label, EditBox, Button, UITransform, Color, Widget, } from 'cc'; import { GameManager } from '../manager/GameManager'; import { getMaxLevelId, getMinLevelId } from '../level/LevelRegistry'; const { ccclass } = _decorator; /** * 预览/运行时的关卡切换条(真实 Button,不依赖 Inspector 扩展) */ @ccclass('LevelSwitchBar') export class LevelSwitchBar extends Component { private editBox: EditBox | null = null; static ensure(parent: Node): LevelSwitchBar { let bar = parent.getChildByName('LevelSwitchBar'); if (!bar) { bar = new Node('LevelSwitchBar'); bar.parent = parent; bar.addComponent(LevelSwitchBar); } return bar.getComponent(LevelSwitchBar)!; } onLoad() { this.buildUI(); } private buildUI() { const rootUi = this.node.getComponent(UITransform) || this.node.addComponent(UITransform); rootUi.setContentSize(520, 48); const hint = this.node.getChildByName('HintLabel') ?? new Node('HintLabel'); hint.parent = this.node; const hintUi = hint.getComponent(UITransform) || hint.addComponent(UITransform); hintUi.setContentSize(200, 36); hint.setPosition(-160, 0, 0); const hintLabel = hint.getComponent(Label) || hint.addComponent(Label); hintLabel.string = `关卡 ${getMinLevelId()}–${getMaxLevelId()}`; hintLabel.fontSize = 18; hintLabel.color = new Color(200, 220, 255); let inputNode = this.node.getChildByName('LevelInput'); if (!inputNode) { inputNode = new Node('LevelInput'); inputNode.parent = this.node; } inputNode.setPosition(-20, 0, 0); const inputUi = inputNode.getComponent(UITransform) || inputNode.addComponent(UITransform); inputUi.setContentSize(80, 36); this.editBox = inputNode.getComponent(EditBox) || inputNode.addComponent(EditBox); this.editBox.placeholder = '关卡号'; this.editBox.string = '1'; this.editBox.fontSize = 20; this.editBox.textLabel = this.ensureEditLabel(inputNode); this.editBox.placeholderLabel = this.ensurePlaceholderLabel(inputNode); let btnNode = this.node.getChildByName('BtnSwitchLevel'); if (!btnNode) { btnNode = new Node('BtnSwitchLevel'); btnNode.parent = this.node; } btnNode.setPosition(120, 0, 0); const btnUi = btnNode.getComponent(UITransform) || btnNode.addComponent(UITransform); btnUi.setContentSize(140, 40); const btn = btnNode.getComponent(Button) || btnNode.addComponent(Button); btn.transition = Button.Transition.SCALE; const btnLabel = this.ensureButtonLabel(btnNode); btnLabel.string = '切换关卡'; btnLabel.fontSize = 20; btnLabel.color = new Color(255, 255, 255); btn.node.off(Button.EventType.CLICK); btn.node.on(Button.EventType.CLICK, this.onClickSwitch, this); let prevNode = this.node.getChildByName('BtnPrev'); if (!prevNode) { prevNode = new Node('BtnPrev'); prevNode.parent = this.node; } prevNode.setPosition(200, 0, 0); prevNode.getComponent(UITransform) || prevNode.addComponent(UITransform).setContentSize(56, 36); const prevBtn = prevNode.getComponent(Button) || prevNode.addComponent(Button); const prevLbl = this.ensureButtonLabel(prevNode); prevLbl.string = '◀'; prevLbl.fontSize = 22; prevNode.off(Button.EventType.CLICK); prevNode.on(Button.EventType.CLICK, () => GameManager.instance?.prevLevel(), this); let nextNode = this.node.getChildByName('BtnNext'); if (!nextNode) { nextNode = new Node('BtnNext'); nextNode.parent = this.node; } nextNode.setPosition(248, 0, 0); nextNode.getComponent(UITransform) || nextNode.addComponent(UITransform).setContentSize(56, 36); const nextBtn = nextNode.getComponent(Button) || nextNode.addComponent(Button); const nextLbl = this.ensureButtonLabel(nextNode); nextLbl.string = '▶'; nextLbl.fontSize = 22; nextNode.off(Button.EventType.CLICK); nextNode.on(Button.EventType.CLICK, () => GameManager.instance?.nextLevel(), this); const widget = this.node.getComponent(Widget) || this.node.addComponent(Widget); widget.isAlignTop = true; widget.top = 12; widget.isAlignHorizontalCenter = true; widget.alignMode = Widget.AlignMode.ON_WINDOW_RESIZE; } syncFromManager() { const gm = GameManager.instance; if (!gm || !this.editBox) return; this.editBox.string = gm.inputLevel || String(gm.curLevelID); } private onClickSwitch() { const gm = GameManager.instance; if (!gm) { console.warn('[LevelSwitchBar] GameManager 未就绪'); return; } if (this.editBox) { gm.inputLevel = this.editBox.string.trim(); } gm.clickSwitchLevel(); this.syncFromManager(); } private ensureButtonLabel(btnNode: Node): Label { let t = btnNode.getChildByName('Label'); if (!t) { t = new Node('Label'); t.parent = btnNode; t.addComponent(UITransform).setContentSize(140, 40); } return t.getComponent(Label) || t.addComponent(Label); } private ensureEditLabel(parent: Node): Label { let t = parent.getChildByName('TEXT_LABEL'); if (!t) { t = new Node('TEXT_LABEL'); t.parent = parent; t.addComponent(UITransform).setContentSize(80, 36); } return t.getComponent(Label) || t.addComponent(Label); } private ensurePlaceholderLabel(parent: Node): Label { let t = parent.getChildByName('PLACEHOLDER_LABEL'); if (!t) { t = new Node('PLACEHOLDER_LABEL'); t.parent = parent; t.addComponent(UITransform).setContentSize(80, 36); } const lb = t.getComponent(Label) || t.addComponent(Label); lb.color = new Color(160, 160, 160); return lb; } }