From 95dc31329d622e2f20244c20cfad690170e159bf Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 12 Mar 2024 16:23:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=80=A7=E8=83=BD=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/main/init/hotkey.ts | 30 +++++ src/core/main/init/settings.tsx | 19 ++- src/core/main/init/ui.ts | 3 +- src/core/main/setting.ts | 2 + src/panel/performance.vue | 208 ++++++++++++++++++++++++++++++++ src/plugin/frame.ts | 96 ++++++++++++++- src/ui/index.ts | 1 + src/ui/performance.vue | 38 ++++++ 8 files changed, 391 insertions(+), 6 deletions(-) create mode 100644 src/panel/performance.vue create mode 100644 src/ui/performance.vue diff --git a/src/core/main/init/hotkey.ts b/src/core/main/init/hotkey.ts index 5d67d77..3cb2b89 100644 --- a/src/core/main/init/hotkey.ts +++ b/src/core/main/init/hotkey.ts @@ -5,6 +5,12 @@ import { hovered } from './fixed'; import { hasMarkedEnemy, markEnemy, unmarkEnemy } from '@/plugin/mark'; import { mainUi } from './ui'; import { GameStorage } from '../storage'; +import { mainSetting } from '../setting'; +import { + isPaused as isFramePaused, + pauseFrame, + resumeFrame +} from '@/plugin/frame'; export const mainScope = Symbol.for('@key_main'); export const gameKey = new Hotkey('gameKey', '游戏按键'); @@ -396,6 +402,19 @@ gameKey id: '@fly_right_t_2', name: '后10张地图_2', defaults: KeyCode.PageUp + }) + .group('debug', '调试按键') + .register({ + id: 'toggleFrameMonitor', + name: '暂停/继续帧率监控', + defaults: KeyCode.F2, + ctrl: true + }) + .register({ + id: 'toggleFrameDisplay', + name: '开关帧率显示', + defaults: KeyCode.F3, + ctrl: true }); gameKey.enable(); @@ -517,6 +536,17 @@ gameKey break; } } + }) + .realize('toggleFrameDisplay', () => { + const value = mainSetting.getValue('debug.frame'); + mainSetting.setValue('debug.frame', !value); + }) + .realize('toggleFrameMonitor', () => { + if (isFramePaused()) { + resumeFrame(); + } else { + pauseFrame(); + } }); // ----- Storage diff --git a/src/core/main/init/settings.tsx b/src/core/main/init/settings.tsx index 4194630..f825f5a 100644 --- a/src/core/main/init/settings.tsx +++ b/src/core/main/init/settings.tsx @@ -10,6 +10,7 @@ interface Components { HotkeySetting: SettingComponent; ToolbarEditor: SettingComponent; Radio: (items: string[]) => SettingComponent; + Performance: SettingComponent; } export type { Components as SettingDisplayComponents }; @@ -21,7 +22,8 @@ export function createSettingComponents() { Number: NumberSetting, HotkeySetting, ToolbarEditor, - Radio: RadioSetting + Radio: RadioSetting, + Performance: PerformanceSetting }; return com; } @@ -180,3 +182,18 @@ function ToolbarEditor(props: SettingComponentProps) { ); } + +function PerformanceSetting(props: SettingComponentProps) { + return ( +
+ +
+ ); +} diff --git a/src/core/main/init/ui.ts b/src/core/main/init/ui.ts index f5249b1..1dc5a3c 100644 --- a/src/core/main/init/ui.ts +++ b/src/core/main/init/ui.ts @@ -13,7 +13,8 @@ mainUi.register( new GameUi('shop', UI.Shop), new GameUi('hotkey', UI.Hotkey), new GameUi('toolEditor', UI.ToolEditor), - new GameUi('virtualKey', MiscUI.VirtualKey) + new GameUi('virtualKey', MiscUI.VirtualKey), + new GameUi('performance', UI.Performance) // todo: 把游戏主 div 加入到 mainUi 里面 ); mainUi.showAll(); diff --git a/src/core/main/setting.ts b/src/core/main/setting.ts index d19d0f9..d73aeaa 100644 --- a/src/core/main/setting.ts +++ b/src/core/main/setting.ts @@ -487,6 +487,8 @@ mainSetting '调试设置', new MotaSetting() .register('frame', '帧率显示', false, COM.Boolean) + .register('performance', '性能分析', false, COM.Performance) + .setDisplayFunc('performance', () => '') ); const loading = Mota.require('var', 'loading'); diff --git a/src/panel/performance.vue b/src/panel/performance.vue new file mode 100644 index 0000000..18c333d --- /dev/null +++ b/src/panel/performance.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/src/plugin/frame.ts b/src/plugin/frame.ts index 4f8e355..aa09289 100644 --- a/src/plugin/frame.ts +++ b/src/plugin/frame.ts @@ -12,6 +12,21 @@ span.style.color = 'lightgreen'; span.style.padding = '5px'; let showing = false; +let pause = false; + +interface FrameInfo { + time: number; + frame: number; + mark?: string; + period?: number; +} + +const frameList: FrameInfo[] = []; + +let inLowFrame = false; +let leaveLowFrameTime = 0; +let starting = 0; +let beginLeaveTime = 0; export function init() { const settings = Mota.require('var', 'mainSetting'); @@ -19,18 +34,77 @@ export function init() { /** 记录前5帧的时间戳 */ let lasttimes = [0, 0, 0, 0, 0]; ticker.add(time => { - if (!setting?.value) return; + if (!setting?.value || pause) return; + let marked = false; lasttimes.shift(); lasttimes.push(time); - span.innerText = (1000 / ((lasttimes[4] - lasttimes[0]) / 4)).toFixed( - 1 - ); + const frame = 1000 / ((lasttimes[4] - lasttimes[0]) / 4); + starting++; + if (frame < 50 && starting > 5) { + if (!inLowFrame) { + performance.mark(`low_frame_start`); + inLowFrame = true; + frameList.push({ + time, + frame, + mark: 'low_frame_start' + }); + marked = true; + } + } + if (inLowFrame) { + if (leaveLowFrameTime === 0) { + performance.mark('low_frame_end'); + const measure = performance.measure( + 'low_frame', + 'low_frame_start', + 'low_frame_end' + ); + beginLeaveTime = measure.duration; + } + if (frame >= 50) { + leaveLowFrameTime++; + } else { + performance.clearMarks('low_frame_end'); + performance.clearMeasures('low_frame'); + leaveLowFrameTime = 0; + } + if (leaveLowFrameTime >= 10) { + leaveLowFrameTime = 0; + inLowFrame = false; + marked = true; + console.warn( + `Mota frame performance analyzer: Marked a low frame period.` + ); + performance.clearMarks(); + frameList.push({ + time, + frame, + mark: 'low_frame_end', + period: beginLeaveTime + }); + } + } + frameList.push(); + span.innerText = frame.toFixed(1); + if (!marked) { + frameList.push({ + time, + frame + }); + } + if (frameList.length >= 1000) frameList.shift(); }); } +export function getFrameList() { + return frameList; +} + export function show() { showing = true; document.body.appendChild(span); + starting = 0; } export function hide() { @@ -41,3 +115,17 @@ export function hide() { export function isShowing() { return showing; } + +export function pauseFrame() { + pause = true; + span.innerText += '(paused)'; +} + +export function resumeFrame() { + pause = false; + starting = 0; +} + +export function isPaused() { + return pause; +} diff --git a/src/ui/index.ts b/src/ui/index.ts index 5130200..41ea7ac 100644 --- a/src/ui/index.ts +++ b/src/ui/index.ts @@ -14,3 +14,4 @@ export { default as Toolbox } from './toolbox.vue'; export { default as Hotkey } from './hotkey.vue'; export { default as Toolbar } from './toolbar.vue'; export { default as ToolEditor } from './toolEditor.vue'; +export { default as Performance } from './performance.vue'; diff --git a/src/ui/performance.vue b/src/ui/performance.vue new file mode 100644 index 0000000..afd9c73 --- /dev/null +++ b/src/ui/performance.vue @@ -0,0 +1,38 @@ + + + + +