From fef6286ed2c82a9be900e064b4f2aecc6857d722 Mon Sep 17 00:00:00 2001 From: ayangweb <75017711+ayangweb@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:35:50 +0800 Subject: [PATCH] refactor: optimize mouse position mapping relationships (#4) --- src-tauri/src/core/device.rs | 9 ++--- src/composables/useModel.ts | 20 +++++------ src/pages/main.vue | 68 +++++++++++++++++------------------- src/utils/monitor.ts | 29 +++++++++++++++ 4 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 src/utils/monitor.ts diff --git a/src-tauri/src/core/device.rs b/src-tauri/src/core/device.rs index e31b01b..5cf3ebb 100644 --- a/src-tauri/src/core/device.rs +++ b/src-tauri/src/core/device.rs @@ -1,11 +1,8 @@ use rdev::{listen, Event, EventType}; use serde::Serialize; use serde_json::{json, Value}; -use std::{ - sync::atomic::{AtomicBool, Ordering}, - thread::spawn, -}; -use tauri::{AppHandle, Emitter}; +use std::sync::atomic::{AtomicBool, Ordering}; +use tauri::{async_runtime, AppHandle, Emitter}; static IS_RUNNING: AtomicBool = AtomicBool::new(false); @@ -31,7 +28,7 @@ pub fn start_listening(app_handle: AppHandle) { IS_RUNNING.store(true, Ordering::SeqCst); - spawn(move || { + async_runtime::block_on(async move { let callback = move |event: Event| { let device = match event.event_type { EventType::ButtonPress(button) => DeviceEvent { diff --git a/src/composables/useModel.ts b/src/composables/useModel.ts index 3f3ab3c..63beb4a 100644 --- a/src/composables/useModel.ts +++ b/src/composables/useModel.ts @@ -1,11 +1,6 @@ -import type { IApplicationOptions } from 'pixi.js' import { Live2DModel } from 'pixi-live2d-display' import { Application } from 'pixi.js' -import { ref } from 'vue' - -interface Options extends IApplicationOptions { - url: string -} +import { onMounted, ref } from 'vue' interface Motion { Name: string @@ -21,22 +16,27 @@ interface Expression { } export function useModel() { + const mode = ref('standard') const model = ref() const motions = ref>({}) const expressions = ref([]) - const loadModel = async (options: Options) => { - const { url, ...rest } = options + onMounted(() => { + loadModel() + }) + const loadModel = async () => { destroyModel() + const view = document.getElementById('live2dCanvas') as HTMLCanvasElement + const app = new Application({ + view, resizeTo: window, backgroundAlpha: 0, - ...rest, }) - const loadedModel = await Live2DModel.from(url) + const loadedModel = await Live2DModel.from(`/models/${mode.value}/cat.model3.json`) app.stage.addChild(loadedModel) diff --git a/src/pages/main.vue b/src/pages/main.vue index d2805c0..63d2f9c 100644 --- a/src/pages/main.vue +++ b/src/pages/main.vue @@ -3,60 +3,58 @@ import { LogicalSize } from '@tauri-apps/api/dpi' import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow' import { Live2DModel } from 'pixi-live2d-display' import { Ticker } from 'pixi.js' -import { ref, useTemplateRef, watch, watchEffect } from 'vue' +import { onMounted, ref, watch } from 'vue' import { useDevice } from '../composables/useDevice' import { useModel } from '../composables/useModel' +import { getCursorMonitor } from '../utils/monitor' Live2DModel.registerTicker(Ticker) -const canvasRef = useTemplateRef('canvasRef') const mode = ref('standard') const { pressedKeys, pressedMouses, mousePosition } = useDevice() -const { model, loadModel, setParameterValue } = useModel() +const { model, setParameterValue } = useModel() -watch([mode, canvasRef], (value) => { - const [mode, canvas] = value - - if (!canvas) return - - loadModel({ - view: canvas, - url: `/models/${mode}/cat.model3.json`, - }) -}, { immediate: true }) - -watchEffect(() => { - if (!model.value) return - - handleResized() - - window.removeEventListener('resize', handleResized) +onMounted(() => { window.addEventListener('resize', handleResized) }) -watchEffect(() => { - const hasArrowKey = pressedKeys.value.some(key => key.endsWith('Arrow')) - const hasNonArrowKey = pressedKeys.value.some(key => !key.endsWith('Arrow')) +watch(model, (value) => { + if (!value) return + + handleResized() +}) + +watch(pressedKeys, (value) => { + const hasArrowKey = value.some(key => key.endsWith('Arrow')) + const hasNonArrowKey = value.some(key => !key.endsWith('Arrow')) setParameterValue('CatParamRightHandDown', hasArrowKey) setParameterValue('CatParamLeftHandDown', hasNonArrowKey) }) -watchEffect(() => { - const isLeftDown = pressedMouses.value.includes('Left') - const isRightDown = pressedMouses.value.includes('Right') +watch(pressedMouses, (value) => { + const isLeftDown = value.includes('Left') + const isRightDown = value.includes('Right') setParameterValue('ParamMouseLeftDown', isLeftDown) setParameterValue('ParamMouseRightDown', isRightDown) }) -watchEffect(() => { - if (!mousePosition.value) return +watch(mousePosition, async () => { + if (!model.value) return - const { innerWidth, innerHeight } = window + const monitor = await getCursorMonitor() - const x = -30 + (mousePosition.value.x / innerWidth) * 15 - const y = -30 + (mousePosition.value.y / innerHeight) * 15 + if (!monitor) return + + const { size, cursorX, cursorY } = monitor + const { width, height } = size + + const xRatio = cursorX / width + const yRatio = cursorY / height + + const x = (xRatio * 60) - 30 + const y = (yRatio * 60) - 30 setParameterValue('ParamMouseX', -x) setParameterValue('ParamMouseY', -y) @@ -93,11 +91,11 @@ function handleMouseDown() { > - + - diff --git a/src/utils/monitor.ts b/src/utils/monitor.ts new file mode 100644 index 0000000..5c92736 --- /dev/null +++ b/src/utils/monitor.ts @@ -0,0 +1,29 @@ +import { + availableMonitors, + cursorPosition, +} from '@tauri-apps/api/window' + +export async function getCursorMonitor() { + const monitors = await availableMonitors() + + if (!monitors.length) return + + const { x, y } = await cursorPosition() + + const monitor = monitors.find((monitor) => { + const { position, size } = monitor + + const inX = x >= position.x && x <= position.x + size.width + const inY = y >= position.y && y <= position.y + size.height + + return inX && inY + }) + + if (!monitor) return + + return { + ...monitor, + cursorX: x, + cursorY: y, + } +}