feat(3d-nds): lag detection
This commit is contained in:
28
app/components/LagModal.vue
Normal file
28
app/components/LagModal.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const emit = defineEmits<{ close: [] }>();
|
||||||
|
|
||||||
|
const app = useAppStore();
|
||||||
|
|
||||||
|
const keep3d = () => {
|
||||||
|
app.lagDetected = false;
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
const switch2d = () => {
|
||||||
|
app.setRenderingMode("2d");
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UModal :open="true" :dismissible="false" :title="$t('lagModal.title')" :ui="{ footer: 'justify-end' }">
|
||||||
|
<template #body>
|
||||||
|
{{ $t('lagModal.body') }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton variant="ghost" color="neutral" :label="$t('lagModal.keep3d')" @click="keep3d" />
|
||||||
|
<UButton color="neutral" :label="$t('lagModal.switch2d')" @click="switch2d" />
|
||||||
|
</template>
|
||||||
|
</UModal>
|
||||||
|
</template>
|
||||||
@@ -195,7 +195,12 @@ watch(
|
|||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const { onRender } = useLoop();
|
const { onRender, onBeforeRender } = useLoop();
|
||||||
|
|
||||||
|
const LAG_FPS_THRESHOLD = 440;
|
||||||
|
const LAG_DURATION_SECS = 1;
|
||||||
|
let lagSeconds = 0;
|
||||||
|
let lagCheckDone = false;
|
||||||
|
|
||||||
const HINT_SPRITE_SCALE = 2;
|
const HINT_SPRITE_SCALE = 2;
|
||||||
const HINT_SPRITE_DPR = 4;
|
const HINT_SPRITE_DPR = 4;
|
||||||
@@ -337,10 +342,30 @@ useKeyUp(({ ndsButton }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onRender(({ delta }) => {
|
// lag detection
|
||||||
|
onBeforeRender(({ delta }) => {
|
||||||
|
if (!lagCheckDone) {
|
||||||
|
const fps = 1 / delta;
|
||||||
|
if (fps < LAG_FPS_THRESHOLD) {
|
||||||
|
lagSeconds += delta;
|
||||||
|
if (lagSeconds >= LAG_DURATION_SECS) {
|
||||||
|
lagCheckDone = true;
|
||||||
|
app.lagDetected = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lagSeconds = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// upate screens
|
||||||
|
onRender(() => {
|
||||||
if (topScreenTexture) topScreenTexture.needsUpdate = true;
|
if (topScreenTexture) topScreenTexture.needsUpdate = true;
|
||||||
if (bottomScreenTexture) bottomScreenTexture.needsUpdate = true;
|
if (bottomScreenTexture) bottomScreenTexture.needsUpdate = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// update physical buttons
|
||||||
|
onBeforeRender(({ delta }) => {
|
||||||
// cross
|
// cross
|
||||||
const crossButton = meshes.get(CROSS_BUTTON);
|
const crossButton = meshes.get(CROSS_BUTTON);
|
||||||
if (crossButton) {
|
if (crossButton) {
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ export type KeyDownCallback = (params: {
|
|||||||
}) => void;
|
}) => void;
|
||||||
|
|
||||||
export const useKeyDown = (callback: KeyDownCallback) => {
|
export const useKeyDown = (callback: KeyDownCallback) => {
|
||||||
|
const app = useAppStore();
|
||||||
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (app.lagDetected) return;
|
||||||
|
|
||||||
const ndsButton = mapCodeToNDS(event.code);
|
const ndsButton = mapCodeToNDS(event.code);
|
||||||
callback({
|
callback({
|
||||||
key: ndsButton ? `NDS_${ndsButton}` : event.key,
|
key: ndsButton ? `NDS_${ndsButton}` : event.key,
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useWindowSize } from "@vueuse/core";
|
import { useWindowSize } from "@vueuse/core";
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
|
import { LazyLagModal } from "#components";
|
||||||
|
|
||||||
const { isReady } = useAssets();
|
const { isReady } = useAssets();
|
||||||
|
|
||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
|
|
||||||
|
const overlay = useOverlay();
|
||||||
|
const lagModal = overlay.create(LazyLagModal);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => app.lagDetected,
|
||||||
|
(detected) => {
|
||||||
|
if (detected) lagModal.open();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const topScreen = useTemplateRef("topScreen");
|
const topScreen = useTemplateRef("topScreen");
|
||||||
const bottomScreen = useTemplateRef("bottomScreen");
|
const bottomScreen = useTemplateRef("bottomScreen");
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const useAppStore = defineStore("app", {
|
|||||||
camera: null as THREE.Camera | null,
|
camera: null as THREE.Camera | null,
|
||||||
hintsVisible: false,
|
hintsVisible: false,
|
||||||
hintsAllowed: false,
|
hintsAllowed: false,
|
||||||
|
lagDetected: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ export const useAppStore = defineStore("app", {
|
|||||||
setRenderingMode(mode: Settings["renderingMode"]) {
|
setRenderingMode(mode: Settings["renderingMode"]) {
|
||||||
this.ready = mode === "2d";
|
this.ready = mode === "2d";
|
||||||
this.settings.renderingMode = mode;
|
this.settings.renderingMode = mode;
|
||||||
|
if (mode === "3d") this.lagDetected = false;
|
||||||
this.save();
|
this.save();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
"lagModal": {
|
||||||
|
"title": "Performance issues detected",
|
||||||
|
"body": "Your device seems to be struggling with 3D rendering. Switch to 2D mode for a smoother experience.",
|
||||||
|
"keep3d": "Keep 3D",
|
||||||
|
"switch2d": "Switch to 2D"
|
||||||
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
|
|||||||
Reference in New Issue
Block a user