feat: slightly better config

This commit is contained in:
2025-02-25 02:01:24 +01:00
parent b7fe76b6ff
commit 43fd622322
7 changed files with 150 additions and 30 deletions

View File

@ -139,7 +139,7 @@ pub async fn init_profile(
pub async fn set_cfg( pub async fn set_cfg(
state: State<'_, Mutex<AppData>>, state: State<'_, Mutex<AppData>>,
key: String, key: String,
value: String value: serde_json::Value
) -> Result<(), ()> { ) -> Result<(), ()> {
log::debug!("invoke: sync_cfg({}, {})", key, value); log::debug!("invoke: sync_cfg({}, {})", key, value);

View File

@ -14,7 +14,7 @@ pub struct Profile {
pub mods: HashSet<PkgKey>, pub mods: HashSet<PkgKey>,
pub wine_runtime: Option<PathBuf>, pub wine_runtime: Option<PathBuf>,
pub wine_prefix: Option<PathBuf>, pub wine_prefix: Option<PathBuf>,
pub cfg: HashMap<String, String> pub cfg: HashMap<String, serde_json::Value>
} }
impl Profile { impl Profile {

View File

@ -57,7 +57,7 @@ pub fn start(p: &Profile, app: AppHandle) -> Result<()> {
.stderr(Stdio::null()); .stderr(Stdio::null());
if let Some(v) = p.cfg.get("intel") { if let Some(v) = p.cfg.get("intel") {
if v == "true" { if v == true {
amd_builder.env("OPENSSL_ia32cap", ":~0x20000000"); amd_builder.env("OPENSSL_ia32cap", ":~0x20000000");
} }
} }

View File

@ -22,10 +22,10 @@ store.setupListeners();
const currentTab = ref('3'); const currentTab = ref('3');
const startEnabled = ref(false); const startEnabled = ref(false);
const loadProfile = async () => { const loadProfile = async (openWindow: boolean) => {
await store.reloadProfile(); await store.reloadProfile();
if (store.profile === null) { if (store.profile === null && openWindow) {
const exePath = await open({ const exePath = await open({
multiple: false, multiple: false,
directory: false, directory: false,
@ -61,7 +61,7 @@ onOpenUrl((urls) => {
}); });
onMounted(async () => { onMounted(async () => {
await loadProfile(); await loadProfile(false);
}); });
listen('launch-end', () => { listen('launch-end', () => {
@ -109,18 +109,44 @@ listen('launch-end', () => {
<Options /> <Options />
</TabPanel> </TabPanel>
<TabPanel value="3"> <TabPanel value="3">
UNDER CONSTRUCTION<br /><br /> <strong>UNDER CONSTRUCTION</strong><br />Many features are
missing.<br />Existing features are expected to break any
time.
<div v-if="isProfileDisabled">
<br />Select <code>mu3.exe</code> to create a
profile:<br />
<Button <Button
:disabled="!isProfileDisabled"
label="Create profile" label="Create profile"
icon="pi pi-plus" icon="pi pi-plus"
aria-label="open-executable" aria-label="open-executable"
@click="loadProfile()" @click="loadProfile(true)"
/> /><br />
<div
style="
margin-top: 5px;
font-weight: bolder;
font-size: 3em;
color: red;
line-height: 1.1em;
"
>
segatools 2024-12-23 or later has to be installed
</div>
(this will change in the future)
</div>
<img <img
v-if="store.profile?.game === 'Ongeki'"
src="/sticker-ongeki.svg" src="/sticker-ongeki.svg"
class="fixed bottom-0 right-0" class="fixed bottom-0 right-0"
/> />
<br /><br /><br />
<Button
style="position: fixed; left: 10px; bottom: 10px"
icon="pi pi-discord"
as="a"
target="_blank"
href="https://discord.gg/jxvzHjjEmc"
/>
</TabPanel> </TabPanel>
</TabPanels> </TabPanels>
</Tabs> </Tabs>

View File

@ -1,25 +1,119 @@
<script setup lang="ts"> <script setup lang="ts">
import { usePkgStore } from '../stores'; import { computed } from 'vue';
import Fieldset from 'primevue/fieldset'; import Fieldset from 'primevue/fieldset';
import InputNumber from 'primevue/inputnumber';
import InputText from 'primevue/inputtext';
import RadioButton from 'primevue/radiobutton';
import Toggle from 'primevue/toggleswitch'; import Toggle from 'primevue/toggleswitch';
import { usePkgStore } from '../stores';
const store = usePkgStore(); const store = usePkgStore();
const _cfg = <T extends string | number | boolean>(key: string, dflt: T) =>
computed({
get() {
return (store.cfg(key) as T) ?? dflt;
},
async set(value) {
await store.set_cfg(key, value ?? dflt);
},
});
const setValue = async (value: boolean) => { const cfgIntel = _cfg('intel', false);
await store.set_cfg('intel', value); const cfgRezW = _cfg('rez-w', 1080);
} const cfgRezH = _cfg('rez-h', 1920);
const cfgDisplayMode = _cfg('display-mode', 'borderless');
const cfgAime = _cfg('aime', true);
const cfgAimeCode = _cfg('aime-code', '00001111222233334444');
</script> </script>
<template> <template>
<Fieldset> <Fieldset legend="Launch options" :toggleable="true">
<div class="flex w-full flex-col"> <div class="flex w-full flex-col gap-1">
<label for="switch" class="flex flex-row w-full p-2"> <label for="switch" class="flex flex-row w-full p-2">
<div class="grow">OpenSSL crash workaround for Intel 10th gen</div> <div class="grow">
<Toggle OpenSSL crash workaround for Intel 10th gen
inputId="switch" </div>
:modelValue="store.cfg('intel') === 'true'" <Toggle inputId="switch" v-model="cfgIntel" />
v-on:value-change="setValue" /> </label>
<label
id="resolution"
class="flex flex-row w-full p-2 gap-2 items-center"
>
<div class="grow">Resolution</div>
<InputNumber
class="shrink"
size="small"
:min="480"
:max="9999"
:use-grouping="false"
v-model="cfgRezW"
/>
x
<InputNumber
class="shrink"
size="small"
:min="640"
:max="9999"
:use-grouping="false"
v-model="cfgRezH"
/>
</label>
<label class="flex flex-row w-full p-2 gap-2">
<div class="grow">Display mode</div>
<div class="flex items-center gap-2">
<RadioButton
v-model="cfgDisplayMode"
inputId="ingredient1"
name="window"
value="window"
/>
<label for="ingredient1">window</label>
</div>
<div class="flex items-center gap-2">
<RadioButton
v-model="cfgDisplayMode"
inputId="ingredient2"
name="borderless"
value="borderless"
/>
<label for="ingredient2">borderless window</label>
</div>
<div class="flex items-center gap-2">
<RadioButton
v-model="cfgDisplayMode"
inputId="ingredient3"
name="fullscreen"
value="fullscreen"
/>
<label for="ingredient3">fullscreen</label>
</div>
</label>
<label for="switch" class="flex flex-row w-full p-2">
<div class="grow">Aime emulation</div>
<Toggle inputId="switch" v-model="cfgAime" />
</label>
<label class="flex flex-row w-full p-2 items-center">
<div class="grow">Aime code</div>
<InputText
class="shrink"
size="small"
:disabled="store.cfg('aime') === false"
:minlength="20"
:maxlength="20"
placeholder="00000000000000000000"
v-model="cfgAimeCode"
/>
</label> </label>
</div> </div>
</Fieldset> </Fieldset>
</template> </template>
<style>
#resolution .p-inputnumber-input {
width: 4rem;
}
.p-inputtext {
font-family: monospace;
}
</style>

View File

@ -25,7 +25,7 @@ export const usePkgStore = defineStore('pkg', {
profile: (state) => state.prf, profile: (state) => state.prf,
isEnabled: (state) => (pkg: Package | undefined) => isEnabled: (state) => (pkg: Package | undefined) =>
pkg !== undefined && state.prf?.mods.includes(pkgKey(pkg)), pkg !== undefined && state.prf?.mods.includes(pkgKey(pkg)),
cfg: (state) => (key: string) => state.prf?.cfg[key] cfg: (state) => (key: string) => state.prf?.cfg[key],
}, },
actions: { actions: {
setupListeners() { setupListeners() {
@ -102,9 +102,9 @@ export const usePkgStore = defineStore('pkg', {
}, },
async set_cfg(key: string, value: string | boolean | number) { async set_cfg(key: string, value: string | boolean | number) {
await invoke('set_cfg', { key, value: `${value}` }); await invoke('set_cfg', { key, value });
await this.reloadProfile(); await this.reloadProfile();
await this.saveProfile(); await this.saveProfile();
} },
}, },
}); });

View File

@ -23,7 +23,7 @@ export interface Profile {
name: string; name: string;
game: 'Ongeki' | 'Chunithm'; game: 'Ongeki' | 'Chunithm';
mods: string[]; mods: string[];
cfg: {[key: string]: string | boolean} cfg: { [key: string]: string | boolean | number };
} }
export type PackageC = Map<string, Package>; export type PackageC = Map<string, Package>;