mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
chore: format code style and update linting configuration
This commit is contained in:
@@ -1,59 +1,57 @@
|
||||
// src/composables/useGamepad.ts
|
||||
import { ref, onMounted, onUnmounted, reactive, readonly, Ref, DeepReadonly, computed, watch } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useGamepad } from '@vueuse/core';
|
||||
import type {
|
||||
GamepadConnectionInfo,
|
||||
RawGamepadState,
|
||||
NormalizedGamepadState,
|
||||
LogicalButton,
|
||||
ButtonInputState,
|
||||
StickInputState
|
||||
} from '@/types/gamepad'; // 使用 @ 指向 src 目录
|
||||
import { LogicalButtonsList } from '@/types/gamepad';
|
||||
GamepadConnectionInfo,
|
||||
LogicalButton,
|
||||
NormalizedGamepadState,
|
||||
} from '@/types/gamepad' // 使用 @ 指向 src 目录
|
||||
import { useGamepad } from '@vueuse/core'
|
||||
import { defineStore } from 'pinia'
|
||||
// src/composables/useGamepad.ts
|
||||
import { computed, reactive, readonly, ref, watch } from 'vue'
|
||||
import { LogicalButtonsList } from '@/types/gamepad'
|
||||
|
||||
// 定义事件处理函数类型
|
||||
type GamepadEventHandler = (gamepadInfo: GamepadConnectionInfo, index: number) => void;
|
||||
type GamepadEventHandler = (gamepadInfo: GamepadConnectionInfo, index: number) => void
|
||||
|
||||
// 标准按钮映射,根据标准布局将gamepad API的按钮索引映射到逻辑按钮
|
||||
const standardButtonMap: Partial<Record<number, LogicalButton>> = {
|
||||
0: 'ACTION_DOWN', // Xbox A / PS Cross / Nintendo B
|
||||
1: 'ACTION_RIGHT', // Xbox B / PS Circle / Nintendo A
|
||||
2: 'ACTION_LEFT', // Xbox X / PS Square / Nintendo Y
|
||||
3: 'ACTION_UP', // Xbox Y / PS Triangle / Nintendo X
|
||||
0: 'ACTION_DOWN', // Xbox A / PS Cross / Nintendo B
|
||||
1: 'ACTION_RIGHT', // Xbox B / PS Circle / Nintendo A
|
||||
2: 'ACTION_LEFT', // Xbox X / PS Square / Nintendo Y
|
||||
3: 'ACTION_UP', // Xbox Y / PS Triangle / Nintendo X
|
||||
4: 'LEFT_SHOULDER_1', // LB / L1
|
||||
5: 'RIGHT_SHOULDER_1', // RB / R1
|
||||
6: 'LEFT_SHOULDER_2', // LT / L2 (触发器)
|
||||
6: 'LEFT_SHOULDER_2', // LT / L2 (触发器)
|
||||
7: 'RIGHT_SHOULDER_2', // RT / R2 (触发器)
|
||||
8: 'SELECT', // Xbox View / PS Select / Nintendo -
|
||||
9: 'START', // Xbox Menu / PS Start / Nintendo +
|
||||
8: 'SELECT', // Xbox View / PS Select / Nintendo -
|
||||
9: 'START', // Xbox Menu / PS Start / Nintendo +
|
||||
10: 'LEFT_STICK_PRESS', // 左摇杆按下
|
||||
11: 'RIGHT_STICK_PRESS', // 右摇杆按下
|
||||
12: 'DPAD_UP', // 方向键上
|
||||
13: 'DPAD_DOWN', // 方向键下
|
||||
14: 'DPAD_LEFT', // 方向键左
|
||||
15: 'DPAD_RIGHT', // 方向键右
|
||||
16: 'HOME', // Xbox Home / PS Home / Nintendo Home
|
||||
17: 'PS_TOUCHPAD', // PS触摸板按下
|
||||
12: 'DPAD_UP', // 方向键上
|
||||
13: 'DPAD_DOWN', // 方向键下
|
||||
14: 'DPAD_LEFT', // 方向键左
|
||||
15: 'DPAD_RIGHT', // 方向键右
|
||||
16: 'HOME', // Xbox Home / PS Home / Nintendo Home
|
||||
17: 'PS_TOUCHPAD', // PS触摸板按下
|
||||
// 18可能对应任天堂的截图按钮
|
||||
18: 'NINTENDO_CAPTURE'
|
||||
};
|
||||
18: 'NINTENDO_CAPTURE',
|
||||
}
|
||||
|
||||
export const useGamepadStore = defineStore('gamepad', () => {
|
||||
const { gamepads, onConnected, onDisconnected } = useGamepad();
|
||||
const { gamepads, onConnected, onDisconnected } = useGamepad()
|
||||
|
||||
const connectedGamepadInfo = ref<GamepadConnectionInfo | null>(null);
|
||||
const activeGamepadIndex = ref<number | null>(null);
|
||||
const connectedGamepadInfo = ref<GamepadConnectionInfo | null>(null)
|
||||
const activeGamepadIndex = ref<number | null>(null)
|
||||
|
||||
// 存储自定义事件处理器
|
||||
const connectedHandlers: Set<GamepadEventHandler> = new Set();
|
||||
const disconnectedHandlers: Set<GamepadEventHandler> = new Set();
|
||||
const connectedHandlers: Set<GamepadEventHandler> = new Set()
|
||||
const disconnectedHandlers: Set<GamepadEventHandler> = new Set()
|
||||
|
||||
// 初始化所有按钮状态
|
||||
const initialButtonStates = LogicalButtonsList.reduce((acc, key) => {
|
||||
acc[key] = { pressed: false, value: 0 };
|
||||
return acc;
|
||||
}, {} as Record<LogicalButton, ButtonInputState>);
|
||||
acc[key] = { pressed: false, value: 0 }
|
||||
return acc
|
||||
}, {} as Record<LogicalButton, ButtonInputState>)
|
||||
|
||||
// 手柄状态,包含按钮和摇杆
|
||||
const normalizedGamepadState = reactive<NormalizedGamepadState>({
|
||||
@@ -62,123 +60,123 @@ export const useGamepadStore = defineStore('gamepad', () => {
|
||||
LEFT_STICK: { x: 0, y: 0 },
|
||||
RIGHT_STICK: { x: 0, y: 0 },
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
// 计算属性:手柄是否已连接
|
||||
const isGamepadConnected = computed(() => activeGamepadIndex.value !== null && !!gamepads.value[activeGamepadIndex.value]?.connected);
|
||||
const isGamepadConnected = computed(() => activeGamepadIndex.value !== null && !!gamepads.value[activeGamepadIndex.value]?.connected)
|
||||
|
||||
// 重置手柄状态
|
||||
const resetNormalizedState = () => {
|
||||
Object.keys(normalizedGamepadState.buttons).forEach(key => {
|
||||
const buttonKey = key as LogicalButton;
|
||||
if (normalizedGamepadState.buttons[buttonKey]) {
|
||||
normalizedGamepadState.buttons[buttonKey]!.pressed = false;
|
||||
normalizedGamepadState.buttons[buttonKey]!.value = 0;
|
||||
}
|
||||
});
|
||||
normalizedGamepadState.sticks.LEFT_STICK = { x: 0, y: 0 };
|
||||
normalizedGamepadState.sticks.RIGHT_STICK = { x: 0, y: 0 };
|
||||
};
|
||||
Object.keys(normalizedGamepadState.buttons).forEach((key) => {
|
||||
const buttonKey = key as LogicalButton
|
||||
if (normalizedGamepadState.buttons[buttonKey]) {
|
||||
normalizedGamepadState.buttons[buttonKey].pressed = false
|
||||
normalizedGamepadState.buttons[buttonKey].value = 0
|
||||
}
|
||||
})
|
||||
normalizedGamepadState.sticks.LEFT_STICK = { x: 0, y: 0 }
|
||||
normalizedGamepadState.sticks.RIGHT_STICK = { x: 0, y: 0 }
|
||||
}
|
||||
|
||||
// 更新手柄状态
|
||||
const updateNormalizedState = (gamepad: Gamepad | undefined) => {
|
||||
if (!gamepad || !gamepad.connected) {
|
||||
resetNormalizedState();
|
||||
return;
|
||||
resetNormalizedState()
|
||||
return
|
||||
}
|
||||
|
||||
// 更新按钮状态
|
||||
gamepad.buttons.forEach((button, index) => {
|
||||
const logicalKey = standardButtonMap[index];
|
||||
const logicalKey = standardButtonMap[index]
|
||||
if (logicalKey && normalizedGamepadState.buttons[logicalKey]) {
|
||||
normalizedGamepadState.buttons[logicalKey]!.pressed = button.pressed;
|
||||
normalizedGamepadState.buttons[logicalKey]!.value = button.value;
|
||||
normalizedGamepadState.buttons[logicalKey].pressed = button.pressed
|
||||
normalizedGamepadState.buttons[logicalKey].value = button.value
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// 更新摇杆状态
|
||||
normalizedGamepadState.sticks.LEFT_STICK.x = gamepad.axes[0] ?? 0;
|
||||
normalizedGamepadState.sticks.LEFT_STICK.y = gamepad.axes[1] ?? 0;
|
||||
normalizedGamepadState.sticks.RIGHT_STICK.x = gamepad.axes[2] ?? 0;
|
||||
normalizedGamepadState.sticks.RIGHT_STICK.y = gamepad.axes[3] ?? 0;
|
||||
};
|
||||
normalizedGamepadState.sticks.LEFT_STICK.x = gamepad.axes[0] ?? 0
|
||||
normalizedGamepadState.sticks.LEFT_STICK.y = gamepad.axes[1] ?? 0
|
||||
normalizedGamepadState.sticks.RIGHT_STICK.x = gamepad.axes[2] ?? 0
|
||||
normalizedGamepadState.sticks.RIGHT_STICK.y = gamepad.axes[3] ?? 0
|
||||
}
|
||||
|
||||
// 手柄连接事件处理
|
||||
onConnected((index: number) => {
|
||||
const gamepad = navigator.getGamepads()[index];
|
||||
if (!gamepad) return;
|
||||
const gamepad = navigator.getGamepads()[index]
|
||||
if (!gamepad) return
|
||||
|
||||
console.log('手柄已连接:', gamepad.id, '索引:', index);
|
||||
console.log('手柄已连接:', gamepad.id, '索引:', index)
|
||||
// 如果当前没有活动的,或者连接的是同一个,则激活
|
||||
if (activeGamepadIndex.value === null || activeGamepadIndex.value === index) {
|
||||
activeGamepadIndex.value = index;
|
||||
activeGamepadIndex.value = index
|
||||
connectedGamepadInfo.value = {
|
||||
id: gamepad.id,
|
||||
mapping: gamepad.mapping
|
||||
};
|
||||
mapping: gamepad.mapping,
|
||||
}
|
||||
|
||||
// 触发外部注册的连接事件处理器
|
||||
if (connectedGamepadInfo.value) {
|
||||
connectedHandlers.forEach(handler => {
|
||||
connectedHandlers.forEach((handler) => {
|
||||
try {
|
||||
handler(connectedGamepadInfo.value!, index);
|
||||
handler(connectedGamepadInfo.value!, index)
|
||||
} catch (err) {
|
||||
console.error('手柄连接事件处理器执行错误:', err);
|
||||
console.error('手柄连接事件处理器执行错误:', err)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 如果已有活动手柄,而新连接的手柄不是当前活动的,则忽略,或按需处理(例如允许切换)
|
||||
console.log(`另一个手柄 (索引: ${activeGamepadIndex.value}) 已经处于活动状态`);
|
||||
console.log(`另一个手柄 (索引: ${activeGamepadIndex.value}) 已经处于活动状态`)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// 手柄断开连接事件处理
|
||||
onDisconnected((index: number) => {
|
||||
const gamepadCache = gamepads.value[index];
|
||||
if (!gamepadCache) return;
|
||||
const gamepadCache = gamepads.value[index]
|
||||
if (!gamepadCache) return
|
||||
|
||||
console.log('手柄已断开连接:', gamepadCache.id);
|
||||
console.log('手柄已断开连接:', gamepadCache.id)
|
||||
|
||||
// 保存断开连接前的信息,用于触发事件
|
||||
const disconnectedInfo = connectedGamepadInfo.value ? { ...connectedGamepadInfo.value } : null;
|
||||
const disconnectedInfo = connectedGamepadInfo.value ? { ...connectedGamepadInfo.value } : null
|
||||
|
||||
if (activeGamepadIndex.value === index) {
|
||||
activeGamepadIndex.value = null;
|
||||
connectedGamepadInfo.value = null;
|
||||
resetNormalizedState();
|
||||
activeGamepadIndex.value = null
|
||||
connectedGamepadInfo.value = null
|
||||
resetNormalizedState()
|
||||
|
||||
// 触发外部注册的断开连接事件处理器
|
||||
if (disconnectedInfo) {
|
||||
disconnectedHandlers.forEach(handler => {
|
||||
disconnectedHandlers.forEach((handler) => {
|
||||
try {
|
||||
handler(disconnectedInfo, index);
|
||||
handler(disconnectedInfo, index)
|
||||
} catch (err) {
|
||||
console.error('手柄断开连接事件处理器执行错误:', err);
|
||||
console.error('手柄断开连接事件处理器执行错误:', err)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// 尝试连接其他已连接的手柄 (VueUse 的 gamepads 数组会自动更新)
|
||||
const nextGamepad = gamepads.value.find(gp => gp && gp.connected);
|
||||
const nextGamepad = gamepads.value.find(gp => gp && gp.connected)
|
||||
if (nextGamepad) {
|
||||
activeGamepadIndex.value = nextGamepad.index;
|
||||
activeGamepadIndex.value = nextGamepad.index
|
||||
connectedGamepadInfo.value = {
|
||||
id: nextGamepad.id,
|
||||
mapping: nextGamepad.mapping
|
||||
};
|
||||
mapping: nextGamepad.mapping,
|
||||
}
|
||||
|
||||
// 如果自动切换到其他手柄,也触发连接事件
|
||||
connectedHandlers.forEach(handler => {
|
||||
connectedHandlers.forEach((handler) => {
|
||||
try {
|
||||
handler(connectedGamepadInfo.value!, nextGamepad.index);
|
||||
handler(connectedGamepadInfo.value!, nextGamepad.index)
|
||||
} catch (err) {
|
||||
console.error('手柄连接事件处理器执行错误:', err);
|
||||
console.error('手柄连接事件处理器执行错误:', err)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// 监视 VueUse 的 gamepads 数组中的活动手柄
|
||||
// VueUse 内部使用 rAF 来更新 gamepads 数组中的状态
|
||||
@@ -187,38 +185,38 @@ export const useGamepadStore = defineStore('gamepad', () => {
|
||||
// 确保 activeGamepadIndex.value 不为 null,并且对应的 gamepad 存在
|
||||
return activeGamepadIndex.value !== null && gamepads.value[activeGamepadIndex.value]
|
||||
? gamepads.value[activeGamepadIndex.value]
|
||||
: undefined;
|
||||
: undefined
|
||||
},
|
||||
(activePad) => {
|
||||
updateNormalizedState(activePad);
|
||||
updateNormalizedState(activePad)
|
||||
},
|
||||
{ deep: true, immediate: true } // immediate: true 保证初始状态也被处理
|
||||
);
|
||||
{ deep: true, immediate: true }, // immediate: true 保证初始状态也被处理
|
||||
)
|
||||
|
||||
// 对外提供的连接事件注册方法
|
||||
const onGamepadConnected = (handler: GamepadEventHandler) => {
|
||||
connectedHandlers.add(handler);
|
||||
connectedHandlers.add(handler)
|
||||
|
||||
// 如果当前已有连接的手柄,立即触发一次事件
|
||||
if (isGamepadConnected.value && connectedGamepadInfo.value && activeGamepadIndex.value !== null) {
|
||||
handler(connectedGamepadInfo.value, activeGamepadIndex.value);
|
||||
handler(connectedGamepadInfo.value, activeGamepadIndex.value)
|
||||
}
|
||||
|
||||
// 返回取消注册的函数
|
||||
return () => {
|
||||
connectedHandlers.delete(handler);
|
||||
};
|
||||
};
|
||||
connectedHandlers.delete(handler)
|
||||
}
|
||||
}
|
||||
|
||||
// 对外提供的断开连接事件注册方法
|
||||
const onGamepadDisconnected = (handler: GamepadEventHandler) => {
|
||||
disconnectedHandlers.add(handler);
|
||||
disconnectedHandlers.add(handler)
|
||||
|
||||
// 返回取消注册的函数
|
||||
return () => {
|
||||
disconnectedHandlers.delete(handler);
|
||||
};
|
||||
};
|
||||
disconnectedHandlers.delete(handler)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
connectedGamepadInfo: readonly(connectedGamepadInfo),
|
||||
@@ -226,5 +224,5 @@ export const useGamepadStore = defineStore('gamepad', () => {
|
||||
isGamepadConnected: readonly(isGamepadConnected),
|
||||
onConnected: onGamepadConnected,
|
||||
onDisconnected: onGamepadDisconnected,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user