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 @@
+
+
+
+
+
+
+