import { _decorator, Component, Node, Label, EditBox, Button, UITransform, Color, Widget, Graphics, Layers, } from 'cc'; import { EDITOR, PREVIEW } from 'cc/env'; import { GameManager } from '../manager/GameManager'; const { ccclass } = _decorator; const HUD_LAYER = Layers.Enum.UI_3D; /** 预览模式下调试条(对齐 Unity Editor/TestPlayer) */ @ccclass('GameplayDebugBar') export class GameplayDebugBar extends Component { private stepBox: EditBox | null = null; static shouldShow(): boolean { return EDITOR && PREVIEW; } static ensure(parent: Node): GameplayDebugBar | null { if (!GameplayDebugBar.shouldShow()) return null; let bar = parent.getChildByName('GameplayDebugBar'); if (!bar) { bar = new Node('GameplayDebugBar'); bar.parent = parent; bar.layer = HUD_LAYER; bar.addComponent(GameplayDebugBar); } bar.setSiblingIndex(parent.children.length - 1); console.log('[GameplayDebugBar] 已显示(左下角)'); return bar.getComponent(GameplayDebugBar)!; } onLoad() { this.node.layer = HUD_LAYER; this.buildUI(); } private gm() { return GameManager.instance; } private buildUI() { const rootUi = this.node.getComponent(UITransform) || this.node.addComponent(UITransform); rootUi.setContentSize(680, 52); rootUi.setAnchorPoint(0, 0); const bg = this.node.getComponent(Graphics) || this.node.addComponent(Graphics); bg.fillColor = new Color(0, 0, 0, 160); bg.clear(); bg.rect(0, 0, 680, 52); bg.fill(); this.mkLabel('Title', '调试', 8, 26, 14, new Color(255, 220, 120)); this.stepBox = this.mkEdit('StepInput', '1', 52, 8, 40); this.mkBtn('前', 100, 8, 44, () => this.act('debugMove', this.step())); this.mkBtn('后', 150, 8, 44, () => this.act('debugMove', -this.step())); this.mkBtn('跳', 200, 8, 40, () => this.act('debugJump')); this.mkBtn('←', 246, 8, 36, () => this.act('debugRotateLeft', 1)); this.mkBtn('→', 288, 8, 36, () => this.act('debugRotateRight', 1)); this.mkBtn('坐标', 330, 8, 52, () => this.act('debugPlayerInfo')); this.mkBtn('结束', 388, 8, 52, () => this.act('debugInputEnd')); this.mkBtn('载具', 446, 8, 52, () => this.act('debugVehicleMove', 1)); const widget = this.node.getComponent(Widget) || this.node.addComponent(Widget); widget.isAlignBottom = true; widget.bottom = 12; widget.isAlignLeft = true; widget.left = 12; widget.alignMode = Widget.AlignMode.ON_WINDOW_RESIZE; } private step(): number { const n = parseInt(this.stepBox?.string ?? '1', 10); return Number.isNaN(n) || n === 0 ? 1 : n; } private act(method: string, arg?: number) { const gm = this.gm(); if (!gm) { console.warn('[GameplayDebugBar] GameController 未就绪'); return; } const fn = (gm as unknown as Record)[method]; if (typeof fn !== 'function') { console.warn(`[GameplayDebugBar] 无方法 ${method}`); return; } if (arg === undefined) (fn as () => void).call(gm); else (fn as (n: number) => void).call(gm, arg); } private mkLabel(name: string, text: string, x: number, y: number, size: number, color: Color): Label { const n = new Node(name); n.parent = this.node; n.layer = HUD_LAYER; n.setPosition(x, y, 0); n.addComponent(UITransform).setContentSize(80, 24); const lb = n.addComponent(Label); lb.string = text; lb.fontSize = size; lb.color = color; return lb; } private mkEdit(name: string, value: string, x: number, y: number, w: number): EditBox { const n = new Node(name); n.parent = this.node; n.layer = HUD_LAYER; n.setPosition(x, y, 0); n.addComponent(UITransform).setContentSize(w, 32); const box = n.addComponent(EditBox); box.string = value; box.fontSize = 16; const tl = new Node('TEXT_LABEL'); tl.parent = n; tl.layer = HUD_LAYER; tl.addComponent(UITransform).setContentSize(w, 32); box.textLabel = tl.addComponent(Label); box.textLabel.fontSize = 16; box.textLabel.color = new Color(255, 255, 255); const pl = new Node('PLACEHOLDER_LABEL'); pl.parent = n; pl.layer = HUD_LAYER; pl.addComponent(UITransform).setContentSize(w, 32); box.placeholderLabel = pl.addComponent(Label); box.placeholderLabel.fontSize = 16; box.placeholderLabel.color = new Color(140, 140, 140); return box; } private mkBtn(caption: string, x: number, y: number, w: number, handler: () => void) { const n = new Node(`Btn_${caption}`); n.parent = this.node; n.layer = HUD_LAYER; n.setPosition(x, y, 0); n.addComponent(UITransform).setContentSize(w, 32); const btn = n.addComponent(Button); btn.transition = Button.Transition.SCALE; const tl = new Node('Label'); tl.parent = n; tl.layer = HUD_LAYER; tl.addComponent(UITransform).setContentSize(w, 32); const lb = tl.addComponent(Label); lb.string = caption; lb.fontSize = 15; lb.color = new Color(255, 255, 255); n.on(Button.EventType.CLICK, handler, this); } }