//********************* // create by 流云 // time: Thu Mar 06 2025 // desc: //********************* import { _decorator, Component, Node, find, sys, game, instantiate, EventTouch, Layout, UITransform, Vec2, Label } from 'cc'; import { Auto_PanelSettings } from './Auto_PanelSettings'; import { StatusType } from '../../game/GameData'; import { TableNames } from '../../game/ConfigTableData'; import { GEvent } from 'db://assets/mx/module/event/GEvent'; import { GM } from '../../game/GM'; import { UIID, GAudioPath } from '../../game/ConfigRes'; import { sdkConfig } from '../../sdk/sdkConfig'; import type { LangCode } from 'db://assets/mx/module/lang/Lang'; import { Lang } from 'db://assets/mx/module/lang/Lang'; import { HeadIconManager } from '../../manager/HeadIconManager'; const { ccclass, property } = _decorator; @ccclass('UIPanelSettings') export class UIPanelSettings extends Auto_PanelSettings { clickTime: number = 0; btnArray: Node[] = []; btnKeyArray: string[] = []; /** 头像列表数据 */ private _headRows: ITableHeadicon[] = []; /** 当前选中下标(对应 _headRows) */ private _selectedHeadIdx = 0; /** 头像项模板 */ private _headItemTemplate: Node | null = null; /** 列表项节点(用于注销点击) */ private _headItemNodes: Node[] = []; /** 打开时滚到选中项的重试次数 */ private _scrollHeadRetries = 0; onLoad(): void { super.onLoad(); } onEnable(): void { super.onEnable(); } onDisable(): void { this.unschedule(this._scrollHeadListToSelected); this._scrollHeadRetries = 0; this._unbindHeadList(); super.onDisable(); } async onInit(): Promise { this.ui_boxLang.active = sdkConfig.config.noChangeLang; if (sdkConfig.config.noChangeLang) { this.btnKeyArray = [ "cn", "cn", "en", "cn", "cn", "cn", "cn", "cn", "cn", "cn", ] this.btnArray = [ this.btn_jtzw, this.btn_fanti, this.btn_english, this.btn_hanyu, this.btn_riben, this.btn_xibanya, this.btn_fayu, this.btn_deyu, this.btn_eluosi, this.btn_putaoya, ] //sdkConfig.defaultLang this.refreshChangeBtn(false) } this.updateBtnStatus(); if (gg.data.doc.roleId == 1) { this.btn_choseMan.getChildByName('choose').active = true this.btn_choseWoman.getChildByName('choose').active = false } else { this.btn_choseMan.getChildByName('choose').active = false this.btn_choseWoman.getChildByName('choose').active = true } this.btnGM.active = sys.isBrowser || sdkConfig.isOpenGM; await HeadIconManager.syncUnlocksFromProgressAsync(); await this._buildHeadList(); } /** 构建 Headicon 头像列表 */ private async _buildHeadList(): Promise { if (!this.ui_headItem?.isValid || !this.sv_headList?.content) { console.log('[UIPanelSettings] 头像列表节点缺失'); return; } await gg.data.table.ensureTableLoaded(TableNames.Headicon); this._unbindHeadList(); this._headItemTemplate = this.ui_headItem; this._headItemTemplate.active = false; const tplLock = this._findHeadItemLock(this._headItemTemplate); if (tplLock) tplLock.active = false; this._headRows = HeadIconManager.getHeadIconList(); if (this._headRows.length <= 0) { console.log('[UIPanelSettings] Headicon 表无数据'); return; } const currentId = HeadIconManager.getPlayerHeadIconId(); const idx = this._headRows.findIndex((row) => row.id === currentId); this._selectedHeadIdx = idx >= 0 ? idx : 0; const content = this.sv_headList.content; content.removeAllChildren(); this._headItemNodes = []; for (let i = 0; i < this._headRows.length; i++) { const item = instantiate(this._headItemTemplate); item.parent = content; item.setPosition(0, 0, 0); item.active = true; this._bindHeadItem(item, i); this._headItemNodes.push(item); } content.getComponent(Layout)?.updateLayout(); this._scrollHeadRetries = 4; this.scheduleOnce(this._scrollHeadListToSelected, 0); } /** 横向列表滚到当前选中头像(布局/弹窗入场后再算偏移) */ private _scrollHeadListToSelected = (): void => { const sv = this.sv_headList; const item = this._headItemNodes[this._selectedHeadIdx]; const content = sv?.content; if (!sv?.isValid || !item?.isValid || !content?.isValid) { this._scrollHeadRetries = 0; return; } content.getComponent(Layout)?.updateLayout(); const viewUt = sv.node.getComponent(UITransform); const contentUt = content.getComponent(UITransform); const itemUt = item.getComponent(UITransform); if (!viewUt || !contentUt || !itemUt) { this._scrollHeadRetries = 0; return; } const viewWidth = viewUt.contentSize.width; const contentWidth = contentUt.contentSize.width; const maxOffset = sv.getMaxScrollOffset(); if (contentWidth <= viewWidth || maxOffset.x <= 0) { sv.stopAutoScroll(); sv.scrollToOffset(new Vec2(0, 0), 0); this._scrollHeadRetries = 0; return; } const itemCenterX = item.position.x; let offsetX = itemCenterX - viewWidth * 0.5; offsetX = Math.max(0, Math.min(offsetX, maxOffset.x)); sv.stopAutoScroll(); sv.scrollToOffset(new Vec2(offsetX, 0), 0.25); this._scrollHeadRetries--; if (this._scrollHeadRetries > 0) { this.scheduleOnce(this._scrollHeadListToSelected, 0); } }; /** 绑定单个头像项 */ private _bindHeadItem(item: Node, index: number): void { const row = this._headRows[index]; const select = item.getChildByName('select'); if (select) select.active = index === this._selectedHeadIdx; const headNode = item.find('headMask/head') ?? item.getChildByName('head'); HeadIconManager.applyRowToNode(headNode, row); const lockNode = this._findHeadItemLock(item); if (lockNode) { const showLock = HeadIconManager.shouldShowLock(row); lockNode.active = showLock; const unlockLb = lockNode.getChildByName('unlock')?.getComponent(Label); if (unlockLb) { unlockLb.string = showLock ? String(row.desc ?? '').trim() : ''; } } item.on(Node.EventType.TOUCH_END, this._onHeadItemTouch, this); } /** 查找头像项 lock 节点 */ private _findHeadItemLock(item: Node | null | undefined): Node | null { if (!item?.isValid) return null; return item.getChildByName('lock') ?? item.getChildByPath('lock'); } /** 头像项点击:更新选中下标 */ private _onHeadItemTouch(ev: EventTouch): void { let node: Node | null = ev.target as Node; const content = this.sv_headList?.content ?? null; while (node?.isValid && node !== content) { const index = this._headItemNodes.indexOf(node); if (index >= 0) { const row = this._headRows[index]; if (row && !HeadIconManager.isUnlocked(row)) { const tip = String(row.desc ?? '').trim(); gg.ui.showToast(tip || '头像未解锁'); return; } if (index !== this._selectedHeadIdx) { this._selectedHeadIdx = index; this._refreshHeadSelectState(); } return; } node = node.parent; } } /** 刷新列表选中框 */ private _refreshHeadSelectState(): void { for (let i = 0; i < this._headItemNodes.length; i++) { const item = this._headItemNodes[i]; if (!item?.isValid) continue; const select = item.getChildByName('select'); if (select) select.active = i === this._selectedHeadIdx; } } /** 注销头像列表点击 */ private _unbindHeadList(): void { for (const item of this._headItemNodes) { if (item?.isValid) { item.off(Node.EventType.TOUCH_END, this._onHeadItemTouch, this); } } this._headItemNodes = []; } click_btnSetting(): void { const row = this._headRows[this._selectedHeadIdx]; if (!row) { gg.ui.showToast('请选择头像'); return; } if (!HeadIconManager.isUnlocked(row)) { const tip = String(row.desc ?? '').trim(); gg.ui.showToast(tip || '头像未解锁'); return; } HeadIconManager.setPlayerHeadIconId(row.id); GEvent.Ins.emit(GEvent.UpdateHeadIcon); this.close(2); } refreshChangeBtn(ischange: boolean = true) { let defaultLang = sdkConfig.defaultLang; this.btnArray.forEach((btnNode) => { btnNode.getChildByName('choose').active = false }) let findKey = 0 for (let i = 0; i < this.btnKeyArray.length; i++) { if (this.btnKeyArray[i] == defaultLang) { findKey = i; break; } } this.btnArray[findKey].getChildByName('choose').active = true if (ischange) { gg.lang.Current = defaultLang as LangCode; } } _vibrateOpen = false; click_btnMusic() { gg.audio.MuteMusic = !gg.audio.MuteMusic; gg.data.setStatus(StatusType.MuteMusic, gg.audio.MuteMusic ? 1 : 0); this.updateBtnStatus(); if (!gg.audio.MuteMusic) gg.audio.playMusic({ name: "首页背景音", path: GAudioPath.Bgm }); else gg.audio.stopMusic(); } click_btnEffect() { gg.audio.MuteEffect = !gg.audio.MuteEffect; gg.data.setStatus(StatusType.MuteEffect, gg.audio.MuteEffect ? 1 : 0); this.updateBtnStatus(); } click_btnVibrate() { this._vibrateOpen = !this._vibrateOpen; gg.sdk.Vibrate.IsEnable = !this._vibrateOpen; this.updateBtnStatus(); } click_btnSave() { gg.data.saveLocal(); gg.data.saveToServer((res) => { if (res) { gg.ui.showToast("已保存"); } else { gg.ui.showToast("保存失败"); } }); } click_btnClose() { this.close(2); } updateBtn(btn, status) { btn.getChildByName("open").active = !status; btn.getChildByName("close").active = status; } click_btnGM() { GM.show(); this.close(2); } click_btnRestart() { gg.ui.openPanel(UIID.MsgBox, { data: { content: "重置将丢失当前游戏进度,重新开始游戏,确定重置吗?", yesFun: () => { gg.game.reset('设置重置'); } } }) } updateBtnStatus() { this.updateBtn(this.btnMusic, gg.audio.MuteMusic); this.updateBtn(this.btnEffect, gg.audio.MuteEffect); this.updateBtn(this.btnVibrate, this._vibrateOpen); } click_btn1(): void { // this.time = game.totalTime; // this.step = 1; } click_btn2(): void { // if (this.step == 1) // this.step = 2; } click_btn3(): void { // let t = game.totalTime - this.time; // if (this.step == 2 && t < 1500) { // GM.show(); // this.close(2); // } } time = 0; step = 0; click_btnResetArea() { this.clickTime++ if (this.clickTime >= 10) { this.btnRestart.active = true; } } click_bgMask() { this.close(2); } click_btnDuiHuan() { gg.ui.openPanel(UIID.PanelCDK); } click_btn_jtzw() { sdkConfig.defaultLang = this.btnKeyArray[0]; this.refreshChangeBtn(); } click_btn_fanti() { sdkConfig.defaultLang = this.btnKeyArray[1]; this.refreshChangeBtn(); } click_btn_english() { sdkConfig.defaultLang = this.btnKeyArray[2]; this.refreshChangeBtn(); } click_btn_hanyu() { sdkConfig.defaultLang = this.btnKeyArray[3]; this.refreshChangeBtn(); } click_btn_riben() { sdkConfig.defaultLang = this.btnKeyArray[4]; this.refreshChangeBtn(); } click_btn_xibanya() { sdkConfig.defaultLang = this.btnKeyArray[5]; this.refreshChangeBtn(); } click_btn_fayu() { sdkConfig.defaultLang = this.btnKeyArray[6]; this.refreshChangeBtn(); } click_btn_deyu() { sdkConfig.defaultLang = this.btnKeyArray[7]; this.refreshChangeBtn(); } click_btn_eluosi() { sdkConfig.defaultLang = this.btnKeyArray[8]; this.refreshChangeBtn(); } click_btn_putaoya() { sdkConfig.defaultLang = this.btnKeyArray[9]; this.refreshChangeBtn(); } click_btn_choseMan() { let homeShow = gg.ui.panelIsShow(UIID.Home); if (!homeShow) { gg.ui.showToast("请切换到战斗界面选择角色"); return; } if (gg.data.doc.roleId == 1) { return; } //关闭角色界面 gg.ui.closePanel(UIID.Role); this.btn_choseMan.getChildByName('choose').active = true this.btn_choseWoman.getChildByName('choose').active = false gg.data.doc.roleId = 1 } click_btn_choseWoman() { let homeShow = gg.ui.panelIsShow(UIID.Home); if (!homeShow) { gg.ui.showToast("请切换到战斗界面选择角色"); return; } if (gg.data.doc.roleId == 0) { return; } //关闭角色界面 gg.ui.closePanel(UIID.Role); this.btn_choseMan.getChildByName('choose').active = false this.btn_choseWoman.getChildByName('choose').active = true gg.data.doc.roleId = 0 } }