forked from akanyan/STARTLINER
feat: segatools.ini loading
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, onMounted, ref } from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import ConfirmDialog from 'primevue/confirmdialog';
|
||||
import Dialog from 'primevue/dialog';
|
||||
import InputIcon from 'primevue/inputicon';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import ScrollPanel from 'primevue/scrollpanel';
|
||||
import Tab from 'primevue/tab';
|
||||
import TabList from 'primevue/tablist';
|
||||
import TabPanel from 'primevue/tabpanel';
|
||||
@ -23,6 +25,7 @@ import {
|
||||
usePrfStore,
|
||||
} from '../stores';
|
||||
import { Dirs } from '../types';
|
||||
import { messageSplit } from '../util';
|
||||
|
||||
const pkg = usePkgStore();
|
||||
const prf = usePrfStore();
|
||||
@ -86,6 +89,23 @@ listen<{ message: string; header: string }>('invoke-error', (event) => {
|
||||
: 'main-scale-xl'
|
||||
"
|
||||
>
|
||||
<ConfirmDialog>
|
||||
<template #message="{ message }">
|
||||
<ScrollPanel
|
||||
v-if="messageSplit(message).length > 5"
|
||||
style="width: 100%; height: 40vh"
|
||||
>
|
||||
<p v-for="m in messageSplit(message)">
|
||||
{{ m }}
|
||||
</p></ScrollPanel
|
||||
>
|
||||
<div v-else>
|
||||
<p v-for="m in messageSplit(message)">
|
||||
{{ m }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</ConfirmDialog>
|
||||
<Dialog
|
||||
modal
|
||||
:visible="errorVisible"
|
||||
|
245
src/components/KeyboardKey.vue
Normal file
245
src/components/KeyboardKey.vue
Normal file
@ -0,0 +1,245 @@
|
||||
<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>
|
@ -6,6 +6,7 @@ const general = useGeneralStore();
|
||||
|
||||
defineProps({
|
||||
title: String,
|
||||
collapsed: Boolean,
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -14,6 +15,7 @@ defineProps({
|
||||
:legend="title"
|
||||
:toggleable="true"
|
||||
v-show="general.cfgCategories.has(title ?? '')"
|
||||
:collapsed="collapsed"
|
||||
>
|
||||
<div class="flex w-full flex-col gap-1">
|
||||
<slot />
|
||||
|
@ -7,6 +7,7 @@ import OptionCategory from './OptionCategory.vue';
|
||||
import OptionRow from './OptionRow.vue';
|
||||
import AimeOptions from './options/Aime.vue';
|
||||
import DisplayOptions from './options/Display.vue';
|
||||
import KeyboardOptions from './options/Keyboard.vue';
|
||||
import MiscOptions from './options/Misc.vue';
|
||||
import NetworkOptions from './options/Network.vue';
|
||||
import SegatoolsOptions from './options/Segatools.vue';
|
||||
@ -129,6 +130,7 @@ prf.reload();
|
||||
v-model="blacklistMaxModel"
|
||||
/></OptionRow> -->
|
||||
</OptionCategory>
|
||||
<KeyboardOptions />
|
||||
<StartlinerOptions />
|
||||
</template>
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, ref } from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import ConfirmDialog from 'primevue/confirmdialog';
|
||||
import ContextMenu from 'primevue/contextmenu';
|
||||
import ScrollPanel from 'primevue/scrollpanel';
|
||||
import { useConfirm } from 'primevue/useconfirm';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
@ -38,6 +36,8 @@ const startline = async (force: boolean, refresh: boolean) => {
|
||||
confirmDialog.require({
|
||||
message: message.join('\n'),
|
||||
header: 'Start check failed',
|
||||
acceptLabel: 'Run anyway',
|
||||
rejectLabel: 'Cancel',
|
||||
accept: () => {
|
||||
startline(true, refresh);
|
||||
},
|
||||
@ -85,10 +85,6 @@ listen('launch-end', () => {
|
||||
getCurrentWindow().setFocus();
|
||||
});
|
||||
|
||||
const messageSplit = (message: any) => {
|
||||
return message.message?.split('\n');
|
||||
};
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
label: 'Refresh and start',
|
||||
@ -111,45 +107,6 @@ const showContextMenu = (event: Event) => {
|
||||
|
||||
<template>
|
||||
<ContextMenu ref="menu" :model="menuItems" />
|
||||
<ConfirmDialog>
|
||||
<template #container="{ message, acceptCallback, rejectCallback }">
|
||||
<div
|
||||
class="flex flex-col p-8 bg-surface-0 dark:bg-surface-900 rounded"
|
||||
>
|
||||
<span class="font-bold self-center text-2xl block mb-2 mt-2">{{
|
||||
message.header
|
||||
}}</span>
|
||||
<ScrollPanel
|
||||
v-if="messageSplit(message).length > 5"
|
||||
style="width: 100%; height: 40vh"
|
||||
>
|
||||
<p v-for="m in messageSplit(message)">
|
||||
{{ m }}
|
||||
</p></ScrollPanel
|
||||
>
|
||||
<div v-else>
|
||||
<p v-for="m in messageSplit(message)">
|
||||
{{ m }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex self-center items-center gap-2 mt-6">
|
||||
<Button
|
||||
label="Run anyway"
|
||||
@click="acceptCallback"
|
||||
size="small"
|
||||
class="w-32"
|
||||
></Button>
|
||||
<Button
|
||||
label="Cancel"
|
||||
outlined
|
||||
size="small"
|
||||
@click="rejectCallback"
|
||||
class="w-32"
|
||||
></Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ConfirmDialog>
|
||||
<Button
|
||||
v-if="startStatus === 'ready'"
|
||||
v-tooltip="disabledTooltip"
|
||||
|
177
src/components/options/Keyboard.vue
Normal file
177
src/components/options/Keyboard.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<script setup lang="ts">
|
||||
import SelectButton from 'primevue/selectbutton';
|
||||
import ToggleSwitch from 'primevue/toggleswitch';
|
||||
import KeyboardKey from '../KeyboardKey.vue';
|
||||
import OptionCategory from '../OptionCategory.vue';
|
||||
import OptionRow from '../OptionRow.vue';
|
||||
import { usePrfStore } from '../../stores';
|
||||
import { ChunithmButtons } from '@/types';
|
||||
|
||||
ToggleSwitch;
|
||||
|
||||
const prf = usePrfStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OptionCategory title="Keyboard">
|
||||
<OptionRow
|
||||
title="Lever mode"
|
||||
v-if="prf.current!.data.keyboard!.game === 'Ongeki'"
|
||||
>
|
||||
<SelectButton
|
||||
v-model="prf.current!.data.keyboard!.data.use_mouse"
|
||||
:options="[
|
||||
{ title: 'XInput', value: false },
|
||||
{ title: 'Mouse', value: true },
|
||||
]"
|
||||
:allow-empty="false"
|
||||
option-label="title"
|
||||
option-value="value"
|
||||
/>
|
||||
</OptionRow>
|
||||
<OptionRow
|
||||
title="Enable multiple IRs"
|
||||
v-if="prf.current!.data.keyboard!.game === 'Chunithm'"
|
||||
>
|
||||
<ToggleSwitch v-model="prf.current!.data.keyboard!.data.split_ir" />
|
||||
</OptionRow>
|
||||
<div
|
||||
:style="`position: relative; height: ${prf.current!.data.keyboard!.game === 'Ongeki' ? 400 : 250}px`"
|
||||
>
|
||||
<div
|
||||
class="absolute left-1/6 top-1/10"
|
||||
style="transform: translateX(-30%) translateY(-50%)"
|
||||
>
|
||||
<div class="flex flex-row gap-2 self-center w-full">
|
||||
<KeyboardKey button="test" small tooltip="Test" />
|
||||
<KeyboardKey button="svc" small tooltip="Service" />
|
||||
<KeyboardKey button="coin" small tooltip="Coin" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="prf.current?.meta.game === 'ongeki'">
|
||||
<div
|
||||
class="absolute left-1/2 top-1/2"
|
||||
style="transform: translateX(-540%) translateY(-200%)"
|
||||
>
|
||||
<KeyboardKey
|
||||
button="lmenu"
|
||||
small
|
||||
color="rgba(255, 0, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="absolute right-1/2 top-1/2"
|
||||
style="transform: translateX(540%) translateY(-200%)"
|
||||
>
|
||||
<KeyboardKey
|
||||
button="rmenu"
|
||||
small
|
||||
color="rgba(255, 255, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="absolute left-1/2 top-1/2"
|
||||
style="transform: translateX(-50%) translateY(-20%)"
|
||||
>
|
||||
<div class="flex flex-row gap-2 self-center w-full">
|
||||
<KeyboardKey
|
||||
button="lwad"
|
||||
tall
|
||||
color="rgba(180, 0, 255, 0.2)"
|
||||
/>
|
||||
<div style="width: 0.7em"></div>
|
||||
<KeyboardKey button="l1" color="rgba(255, 0, 0, 0.2)" />
|
||||
<KeyboardKey button="l2" color="rgba(0, 255, 0, 0.2)" />
|
||||
<KeyboardKey button="l3" color="rgba(0, 0, 255, 0.2)" />
|
||||
<div style="width: 0.7em"></div>
|
||||
<KeyboardKey button="r1" color="rgba(255, 0, 0, 0.2)" />
|
||||
<KeyboardKey button="r2" color="rgba(0, 255, 0, 0.2)" />
|
||||
<KeyboardKey button="r3" color="rgba(0, 0, 255, 0.2)" />
|
||||
<div style="width: 0.7em"></div>
|
||||
<KeyboardKey
|
||||
button="rwad"
|
||||
tall
|
||||
color="rgba(255, 0, 180, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="prf.current?.meta.game === 'chunithm'">
|
||||
<div class="absolute left-1/2 top-1/5">
|
||||
<div
|
||||
class="flex flex-row flex-nowrap gap-2 self-center w-full"
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
(
|
||||
prf.current!.data.keyboard!
|
||||
.data as ChunithmButtons
|
||||
).split_ir
|
||||
"
|
||||
v-for="idx in Array(6)
|
||||
.fill(0)
|
||||
.map((_, i) => i + 1)"
|
||||
>
|
||||
<KeyboardKey
|
||||
button="ir"
|
||||
:index="idx - 1"
|
||||
:tooltip="`ir${idx}`"
|
||||
small
|
||||
color="rgba(0, 255, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<KeyboardKey
|
||||
button="ir"
|
||||
:index="0"
|
||||
:tooltip="`ir0`"
|
||||
small
|
||||
color="rgba(0, 255, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="absolute left-1/2 top-1/2"
|
||||
style="transform: translateX(-50%) translateY(-5%)"
|
||||
>
|
||||
<div
|
||||
class="flex flex-row flex-nowrap gap-2 self-center w-full"
|
||||
>
|
||||
<div
|
||||
v-for="idx in Array(16)
|
||||
.fill(0)
|
||||
.map((_, i) => 16 - i)"
|
||||
>
|
||||
<KeyboardKey
|
||||
button="cell"
|
||||
:index="idx - 1"
|
||||
:tooltip="`cell${idx}`"
|
||||
small
|
||||
color="rgba(255, 255, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 0.6em"></div>
|
||||
<div
|
||||
class="flex flex-row flex-nowrap gap-2 self-center w-full"
|
||||
>
|
||||
<div
|
||||
v-for="idx in Array(16)
|
||||
.fill(0)
|
||||
.map((_, i) => 32 - i)"
|
||||
>
|
||||
<KeyboardKey
|
||||
button="cell"
|
||||
:index="idx - 1"
|
||||
:tooltip="`cell${idx}`"
|
||||
small
|
||||
color="rgba(255, 255, 0, 0.2)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</OptionCategory>
|
||||
</template>
|
@ -17,6 +17,7 @@ const prf = usePrfStore();
|
||||
title="More segatools options"
|
||||
tooltip="Advanced options not covered by STARTLINER"
|
||||
>
|
||||
<!-- <Button icon="pi pi-refresh" size="small" /> -->
|
||||
<FileEditor filename="segatools-base.ini" />
|
||||
</OptionRow>
|
||||
</OptionCategory>
|
||||
|
@ -1,15 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import Select from 'primevue/select';
|
||||
import { useConfirm } from 'primevue/useconfirm';
|
||||
import * as path from '@tauri-apps/api/path';
|
||||
import FilePicker from '../FilePicker.vue';
|
||||
import OptionCategory from '../OptionCategory.vue';
|
||||
import OptionRow from '../OptionRow.vue';
|
||||
import { invoke } from '../../invoke';
|
||||
import { usePkgStore, usePrfStore } from '../../stores';
|
||||
import { Feature } from '../../types';
|
||||
import { pkgKey } from '../../util';
|
||||
|
||||
const prf = usePrfStore();
|
||||
const pkgs = usePkgStore();
|
||||
const confirmDialog = useConfirm();
|
||||
|
||||
const names = computed(() => {
|
||||
switch (prf.current?.meta.game) {
|
||||
@ -31,6 +35,20 @@ const names = computed(() => {
|
||||
throw new Error('Option tab without a profile');
|
||||
}
|
||||
});
|
||||
|
||||
const checkSegatoolsIni = async (target: string) => {
|
||||
const iniPath = await path.join(target, '../segatools.ini');
|
||||
if (await invoke('file_exists', { path: iniPath })) {
|
||||
confirmDialog.require({
|
||||
message: 'Would you like to load the existing configuration data?',
|
||||
header: 'segatools.ini found',
|
||||
accept: async () => {
|
||||
await invoke('load_segatools_ini', { path: iniPath });
|
||||
await prf.reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -45,7 +63,10 @@ const names = computed(() => {
|
||||
extension="exe"
|
||||
:value="prf.current!.data.sgt.target"
|
||||
:callback="
|
||||
(value: string) => (prf.current!.data.sgt.target = value)
|
||||
(value: string) => (
|
||||
(prf.current!.data.sgt.target = value),
|
||||
checkSegatoolsIni(value)
|
||||
)
|
||||
"
|
||||
></FilePicker>
|
||||
</OptionRow>
|
||||
|
@ -347,7 +347,7 @@ export const useClientStore = defineStore('client', () => {
|
||||
scaleFactor.value = value;
|
||||
|
||||
const window = getCurrentWindow();
|
||||
const w = Math.floor(scaleValue(value) * 760);
|
||||
const w = Math.floor(scaleValue(value) * 900);
|
||||
const h = Math.floor(scaleValue(value) * 480);
|
||||
|
||||
let size = await window.innerSize();
|
||||
|
37
src/types.ts
37
src/types.ts
@ -53,6 +53,7 @@ export interface ProfileData {
|
||||
network: NetworkConfig;
|
||||
bepinex: BepInExConfig;
|
||||
mu3_ini: Mu3IniConfig | undefined;
|
||||
keyboard: KeyboardConfig | undefined;
|
||||
}
|
||||
|
||||
export interface SegatoolsConfig {
|
||||
@ -101,6 +102,42 @@ export interface Mu3IniConfig {
|
||||
// blacklist?: [number, number];
|
||||
}
|
||||
|
||||
export interface OngekiButtons {
|
||||
use_mouse: boolean;
|
||||
coin: number;
|
||||
svc: number;
|
||||
test: number;
|
||||
lmenu: number;
|
||||
rmenu: number;
|
||||
l1: number;
|
||||
l2: number;
|
||||
l3: number;
|
||||
r1: number;
|
||||
r2: number;
|
||||
r3: number;
|
||||
lwad: number;
|
||||
rwad: number;
|
||||
}
|
||||
|
||||
export interface ChunithmButtons {
|
||||
split_ir: boolean;
|
||||
coin: number;
|
||||
svc: number;
|
||||
test: number;
|
||||
cell: number[];
|
||||
ir: number[];
|
||||
}
|
||||
|
||||
export type KeyboardConfig =
|
||||
| {
|
||||
game: 'Ongeki';
|
||||
data: OngekiButtons;
|
||||
}
|
||||
| {
|
||||
game: 'Chunithm';
|
||||
data: ChunithmButtons;
|
||||
};
|
||||
|
||||
export interface Profile {
|
||||
meta: ProfileMeta;
|
||||
data: ProfileData;
|
||||
|
@ -55,3 +55,7 @@ export const hasFeature = (pkg: Package | undefined, feature: Feature) => {
|
||||
pkg.loc.status.OK & feature
|
||||
);
|
||||
};
|
||||
|
||||
export const messageSplit = (message: any) => {
|
||||
return message.message?.split('\n');
|
||||
};
|
||||
|
Reference in New Issue
Block a user