mirror of
https://github.com/ayangweb/BongoCat.git
synced 2026-03-12 17:51:48 +08:00
refactor: optimize mouse position mapping relationships (#4)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
29
src/utils/monitor.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user