forked from akanyan/STARTLINER
246 lines
5.3 KiB
Vue
246 lines
5.3 KiB
Vue
<script setup lang="ts">
|
||
import { computed, ref } from 'vue';
|
||
import InputText from 'primevue/inputtext';
|
||
import { usePrfStore } from '../stores';
|
||
import { OngekiButtons } from '../types';
|
||
|
||
const prf = usePrfStore();
|
||
|
||
const hasClickedM1Once = ref(false);
|
||
|
||
const handleKey = (
|
||
button: string | undefined,
|
||
event: KeyboardEvent,
|
||
index?: number
|
||
) => {
|
||
event.preventDefault();
|
||
|
||
const keycode = toKeycode(event.code);
|
||
if (keycode !== null && button !== undefined) {
|
||
const data = prf.current!.data.keyboard!.data as any;
|
||
if (index !== undefined) {
|
||
data[button][index] = keycode;
|
||
} else {
|
||
data[button] = keycode;
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleMouse = (
|
||
button: string | undefined,
|
||
event: MouseEvent,
|
||
index?: number
|
||
) => {
|
||
if (button === undefined || button == 'use_mouse') {
|
||
return;
|
||
}
|
||
|
||
if (event.button === 0) {
|
||
if (hasClickedM1Once.value === false) {
|
||
hasClickedM1Once.value = true;
|
||
return;
|
||
}
|
||
} else {
|
||
event.preventDefault();
|
||
}
|
||
|
||
let keycode;
|
||
switch (event.button) {
|
||
case 0:
|
||
keycode = 1;
|
||
break;
|
||
case 1:
|
||
keycode = 4;
|
||
break;
|
||
case 2:
|
||
keycode = 2;
|
||
break;
|
||
case 3:
|
||
keycode = 5;
|
||
break;
|
||
case 4:
|
||
keycode = 6;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (keycode !== undefined) {
|
||
const data = prf.current!.data.keyboard!.data as any;
|
||
|
||
if (index !== undefined) {
|
||
data[button][index] = keycode;
|
||
} else {
|
||
data[button] = keycode;
|
||
}
|
||
}
|
||
};
|
||
|
||
const getKey = (key: keyof OngekiButtons, index?: number) =>
|
||
computed(() => {
|
||
const data = prf.current!.data.keyboard?.data as any;
|
||
const keycode =
|
||
index === undefined
|
||
? (data[key] as number | undefined)
|
||
: (data[key]?.[index] as number | undefined);
|
||
return keycode && fromKeycode(keycode) ? fromKeycode(keycode) : '–';
|
||
});
|
||
|
||
const KEY_MAP: { [key: number]: string } = {
|
||
1: 'M1',
|
||
2: 'M2',
|
||
4: 'M3',
|
||
5: 'M4',
|
||
6: 'M5',
|
||
8: 'Backspace',
|
||
9: 'Tab',
|
||
13: 'Enter',
|
||
19: 'Pause',
|
||
20: 'CapsLock',
|
||
27: 'Escape',
|
||
32: 'Space',
|
||
33: 'PageUp',
|
||
34: 'PageDown',
|
||
35: 'End',
|
||
36: 'Home',
|
||
37: 'ArrowLeft',
|
||
38: 'ArrowUp',
|
||
39: 'ArrowRight',
|
||
40: 'ArrowDown',
|
||
45: 'Insert',
|
||
46: 'Delete',
|
||
48: 'Digit0',
|
||
49: 'Digit1',
|
||
50: 'Digit2',
|
||
51: 'Digit3',
|
||
52: 'Digit4',
|
||
53: 'Digit5',
|
||
54: 'Digit6',
|
||
55: 'Digit7',
|
||
56: 'Digit8',
|
||
57: 'Digit9',
|
||
65: 'KeyA',
|
||
66: 'KeyB',
|
||
67: 'KeyC',
|
||
68: 'KeyD',
|
||
69: 'KeyE',
|
||
70: 'KeyF',
|
||
71: 'KeyG',
|
||
72: 'KeyH',
|
||
73: 'KeyI',
|
||
74: 'KeyJ',
|
||
75: 'KeyK',
|
||
76: 'KeyL',
|
||
77: 'KeyM',
|
||
78: 'KeyN',
|
||
79: 'KeyO',
|
||
80: 'KeyP',
|
||
81: 'KeyQ',
|
||
82: 'KeyR',
|
||
83: 'KeyS',
|
||
84: 'KeyT',
|
||
85: 'KeyU',
|
||
86: 'KeyV',
|
||
87: 'KeyW',
|
||
88: 'KeyX',
|
||
89: 'KeyY',
|
||
90: 'KeyZ',
|
||
91: 'MetaLeft',
|
||
92: 'MetaRight',
|
||
93: 'ContextMenu',
|
||
96: 'Numpad0',
|
||
97: 'Numpad1',
|
||
98: 'Numpad2',
|
||
99: 'Numpad3',
|
||
100: 'Numpad4',
|
||
101: 'Numpad5',
|
||
102: 'Numpad6',
|
||
103: 'Numpad7',
|
||
104: 'Numpad8',
|
||
105: 'Numpad9',
|
||
106: 'NumpadMultiply',
|
||
107: 'NumpadAdd',
|
||
109: 'NumpadSubtract',
|
||
110: 'NumpadDecimal',
|
||
111: 'NumpadDivide',
|
||
112: 'F1',
|
||
113: 'F2',
|
||
114: 'F3',
|
||
115: 'F4',
|
||
116: 'F5',
|
||
117: 'F6',
|
||
118: 'F7',
|
||
119: 'F8',
|
||
120: 'F9',
|
||
121: 'F10',
|
||
122: 'F11',
|
||
123: 'F12',
|
||
144: 'NumLock',
|
||
145: 'ScrollLock',
|
||
160: 'ShiftLeft',
|
||
161: 'ShiftRight',
|
||
162: 'ControlLeft',
|
||
163: 'ControlRight',
|
||
164: 'AltLeft',
|
||
165: 'AltRight',
|
||
186: 'Semicolon',
|
||
187: 'Equal',
|
||
188: 'Comma',
|
||
189: 'Minus',
|
||
190: 'Period',
|
||
191: 'Slash',
|
||
192: 'Backquote',
|
||
219: 'BracketLeft',
|
||
220: 'Backslash',
|
||
221: 'BracketRight',
|
||
222: 'Quote',
|
||
};
|
||
|
||
const fromKeycode = (keyCode: number): string | null => {
|
||
return KEY_MAP[keyCode] ?? null;
|
||
};
|
||
|
||
const toKeycode = (key: string): number | null => {
|
||
const res = Object.entries(KEY_MAP).find(([_, v]) => v === key)?.[0];
|
||
return res ? parseInt(res) : null;
|
||
};
|
||
|
||
defineProps({
|
||
small: Boolean,
|
||
verySmall: Boolean,
|
||
tall: Boolean,
|
||
tooltip: String,
|
||
button: String,
|
||
color: String,
|
||
index: Number,
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<InputText
|
||
:style="{
|
||
width: small ? '3em' : '5em',
|
||
height: small ? '3em' : tall ? '10em' : '5em',
|
||
fontSize: small ? '0.9em' : '1em',
|
||
backgroundColor: color,
|
||
}"
|
||
unstyled
|
||
class="text-center buttoninputtext"
|
||
v-tooltip="tooltip"
|
||
@contextmenu.prevent="() => {}"
|
||
@keydown="(ev: KeyboardEvent) => handleKey(button, ev, index)"
|
||
@mousedown="
|
||
(ev: MouseEvent) =>
|
||
handleMouse(button as keyof OngekiButtons, ev, index)
|
||
"
|
||
@focusout="() => (hasClickedM1Once = false)"
|
||
:model-value="getKey(button as keyof OngekiButtons, index) as any"
|
||
/>
|
||
</template>
|
||
|
||
<style scoped lang="css">
|
||
.buttoninputtext {
|
||
border-radius: 6px;
|
||
border: 1px solid rgba(200, 200, 200, 0.3);
|
||
}
|
||
</style>
|