forked from akanyan/STARTLINER
235 lines
7.9 KiB
Vue
235 lines
7.9 KiB
Vue
<script setup lang="ts">
|
|
import { Ref, computed, ref } from 'vue';
|
|
import InputNumber from 'primevue/inputnumber';
|
|
import Select from 'primevue/select';
|
|
import SelectButton from 'primevue/selectbutton';
|
|
import ToggleSwitch from 'primevue/toggleswitch';
|
|
import OptionCategory from '../OptionCategory.vue';
|
|
import OptionRow from '../OptionRow.vue';
|
|
import { invoke } from '../../invoke';
|
|
import { usePrfStore } from '../../stores';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
const { t } = useI18n();
|
|
|
|
const capabilities: Ref<string[]> = ref([]);
|
|
const displayList: Ref<{ title: string; value: string }[]> = ref([
|
|
{
|
|
title: t('cfg.display.primary'),
|
|
value: 'default',
|
|
},
|
|
]);
|
|
const prf = usePrfStore();
|
|
|
|
const extraDisplayOptionsDisabled = computed(() => {
|
|
return prf.current?.data.display.target === 'default';
|
|
});
|
|
|
|
const loadDisplays = () => {
|
|
const newList = [
|
|
{
|
|
title: t('cfg.display.primary'),
|
|
value: 'default',
|
|
},
|
|
];
|
|
invoke('list_platform_capabilities')
|
|
.then(async (v: unknown) => {
|
|
let different = false;
|
|
if (Array.isArray(v)) {
|
|
capabilities.value.push(...v);
|
|
}
|
|
if (capabilities.value.includes('display')) {
|
|
for (const [devName, devString] of (await invoke(
|
|
'list_displays'
|
|
)) as Array<[string, string]>) {
|
|
newList.push({
|
|
title: `${devName.replace('\\\\.\\', '')} (${devString})`,
|
|
value: devName,
|
|
});
|
|
if (
|
|
displayList.value.find(
|
|
(item) => item.value === devName
|
|
) === undefined
|
|
) {
|
|
different = true;
|
|
}
|
|
}
|
|
}
|
|
if (displayList.value.length !== newList.length) {
|
|
different = true;
|
|
}
|
|
if (different) {
|
|
displayList.value = newList;
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
};
|
|
|
|
loadDisplays();
|
|
|
|
const game = prf.current!.meta.game;
|
|
const isVertical = game === 'ongeki';
|
|
const adjustableRez = game === 'ongeki';
|
|
const canSkipPrimarySwitch = game === 'ongeki';
|
|
</script>
|
|
|
|
<template>
|
|
<OptionCategory title="Display">
|
|
<OptionRow
|
|
v-if="capabilities.includes('display')"
|
|
:title="t('cfg.display.target')"
|
|
>
|
|
<Select
|
|
v-model="prf.current!.data.display.target"
|
|
:options="displayList"
|
|
option-label="title"
|
|
option-value="value"
|
|
placeholder="(Disconnected)"
|
|
@show="loadDisplays"
|
|
></Select>
|
|
</OptionRow>
|
|
<OptionRow
|
|
class="number-input"
|
|
title="Game resolution"
|
|
v-if="adjustableRez"
|
|
>
|
|
<InputNumber
|
|
class="shrink"
|
|
size="small"
|
|
:min="480"
|
|
:max="9999"
|
|
:use-grouping="false"
|
|
v-model="prf.current!.data.display.rez[0]"
|
|
/>
|
|
x
|
|
<InputNumber
|
|
class="shrink"
|
|
size="small"
|
|
:min="640"
|
|
:max="9999"
|
|
:use-grouping="false"
|
|
v-model="prf.current!.data.display.rez[1]"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow :title="t('cfg.display.mode')">
|
|
<SelectButton
|
|
v-model="prf.current!.data.display.mode"
|
|
:options="[
|
|
{ title: 'Window', value: 'Window' },
|
|
{ title: 'Borderless window', value: 'Borderless' },
|
|
{ title: 'Fullscreen', value: 'Fullscreen' },
|
|
]"
|
|
:allow-empty="false"
|
|
option-label="title"
|
|
option-value="value"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow
|
|
:title="t('cfg.display.rotation')"
|
|
v-if="capabilities.includes('display')"
|
|
>
|
|
<SelectButton
|
|
v-model="prf.current!.data.display.rotation"
|
|
:options="
|
|
isVertical
|
|
? [
|
|
{ title: t('cfg.display.portrait'), value: 90 },
|
|
{
|
|
title: `${t('cfg.display.portrait')} (${t('cfg.display.flipped')})`,
|
|
value: 270,
|
|
},
|
|
]
|
|
: [
|
|
{ title: t('cfg.display.landscape'), value: 0 },
|
|
{
|
|
title: `${t('cfg.display.landscape')} (${t('cfg.display.flipped')})`,
|
|
value: 180,
|
|
},
|
|
]
|
|
"
|
|
:allow-empty="true"
|
|
option-label="title"
|
|
option-value="value"
|
|
:disabled="extraDisplayOptionsDisabled"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow
|
|
v-if="capabilities.includes('display')"
|
|
class="number-input"
|
|
:title="t('cfg.display.refreshRate')"
|
|
>
|
|
<InputNumber
|
|
v-if="game === 'ongeki'"
|
|
class="shrink"
|
|
size="small"
|
|
:min="60"
|
|
:max="999"
|
|
:use-grouping="false"
|
|
v-model="prf.current!.data.display.frequency"
|
|
:disabled="extraDisplayOptionsDisabled"
|
|
/>
|
|
<SelectButton
|
|
v-if="game === 'chunithm'"
|
|
v-model="prf.current!.data.display.frequency"
|
|
:options="[
|
|
{ title: '60Hz (CVT)', value: 60 },
|
|
{ title: '120Hz (SP)', value: 120 },
|
|
]"
|
|
:allow-empty="false"
|
|
option-label="title"
|
|
option-value="value"
|
|
:disabled="extraDisplayOptionsDisabled"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow
|
|
:title="t('cfg.display.borderlessFullscreen')"
|
|
v-if="capabilities.includes('display')"
|
|
:tooltip="t('cfg.display.borderlessFullscreenTooltip')"
|
|
>
|
|
<ToggleSwitch
|
|
:disabled="
|
|
extraDisplayOptionsDisabled ||
|
|
prf.current?.data.display.mode !== 'Borderless'
|
|
"
|
|
v-model="prf.current!.data.display.borderless_fullscreen"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow
|
|
:title="t('cfg.display.dontSwitchPrimary')"
|
|
v-if="
|
|
capabilities.includes('display') &&
|
|
prf.current?.data.display.target !== 'default' &&
|
|
(prf.current!.data.display.dont_switch_primary ||
|
|
displayList.length > 2) &&
|
|
canSkipPrimarySwitch
|
|
"
|
|
:dangerous-tooltip="t('cfg.display.dontSwitchPrimaryTooltip')"
|
|
>
|
|
<ToggleSwitch
|
|
:disabled="extraDisplayOptionsDisabled"
|
|
v-model="prf.current!.data.display.dont_switch_primary"
|
|
/>
|
|
</OptionRow>
|
|
<OptionRow
|
|
:title="t('cfg.display.index')"
|
|
class="number-input"
|
|
v-if="
|
|
capabilities.includes('display') &&
|
|
prf.current?.data.display.target !== 'default' &&
|
|
prf.current!.data.display.dont_switch_primary
|
|
"
|
|
>
|
|
<InputNumber
|
|
class="shrink"
|
|
size="small"
|
|
:min="game === 'chunithm' ? 0 : 1"
|
|
:max="32"
|
|
:use-grouping="false"
|
|
v-model="prf.current!.data.display.monitor_index_override"
|
|
:disabled="extraDisplayOptionsDisabled"
|
|
:allow-empty="true"
|
|
/>
|
|
</OptionRow>
|
|
</OptionCategory>
|
|
</template>
|