refactor: optimize mouse position mapping relationships (#4)

This commit is contained in:
ayangweb
2025-03-28 21:35:50 +08:00
committed by GitHub
parent 7bfc12d3ac
commit fef6286ed2
4 changed files with 75 additions and 51 deletions

View File

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

View File

@@ -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<Live2DModel>()
const motions = ref<Record<string, Motion[]>>({})
const expressions = ref<Expression[]>([])
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)

View File

@@ -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<HTMLCanvasElement>('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() {
>
<img :src="`/images/backgrounds/${mode}.png`">
<canvas ref="canvasRef" />
<canvas id="live2dCanvas" />
<template v-for="item in pressedKeys" :key="item">
<img :src="`/images/keys/${item}.png`">
<img :src="`/images/hands/${item}.png`">
<template v-for="key in pressedKeys" :key="key">
<img :src="`/images/keys/${key}.png`">
<img :src="`/images/hands/${key}.png`">
</template>
</div>
</template>

29
src/utils/monitor.ts Normal file
View File

@@ -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,
}
}