diff options
| author | Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> | 2025-07-18 16:01:47 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-18 16:01:47 -0400 |
| commit | 1d296606babfb0ceb02068e852582ade7adc4d98 (patch) | |
| tree | b29330427adf1b27487a9d2a4b59942a71f585e3 /src | |
| parent | fa328306e3393a787d7c4f5855ecc23177eaa480 (diff) | |
| parent | 3b60286fc360704eb6faeb72edbec602c624bd51 (diff) | |
| download | decky-lsfg-vk-1d296606babfb0ceb02068e852582ade7adc4d98.tar.gz decky-lsfg-vk-1d296606babfb0ceb02068e852582ade7adc4d98.zip | |
Merge pull request #34 from xXJSONDeruloXx/conf-per-game
implement conf file and real time changes
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/lsfgApi.ts | 11 | ||||
| -rw-r--r-- | src/components/ConfigurationSection.tsx | 103 | ||||
| -rw-r--r-- | src/components/Content.tsx | 2 | ||||
| -rw-r--r-- | src/components/LaunchOptionInfo.tsx | 25 | ||||
| -rw-r--r-- | src/components/PluginUpdateChecker.tsx | 121 | ||||
| -rw-r--r-- | src/components/UsageInstructions.tsx | 151 | ||||
| -rw-r--r-- | src/components/index.ts | 3 | ||||
| -rw-r--r-- | src/config/configSchema.ts | 89 | ||||
| -rw-r--r-- | src/hooks/useLsfgHooks.ts | 2 | ||||
| -rwxr-xr-x | src/index.tsx | 2 |
10 files changed, 273 insertions, 236 deletions
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts index f7363c1..5d866ef 100644 --- a/src/api/lsfgApi.ts +++ b/src/api/lsfgApi.ts @@ -66,6 +66,12 @@ export interface UpdateDownloadResult { error?: string; } +export interface LaunchOptionResult { + launch_option: string; + instructions: string; + explanation: string; +} + // API functions export const installLsfgVk = callable<[], InstallationResult>("install_lsfg_vk"); export const uninstallLsfgVk = callable<[], InstallationResult>("uninstall_lsfg_vk"); @@ -73,17 +79,18 @@ export const checkLsfgVkInstalled = callable<[], InstallationStatus>("check_lsfg export const checkLosslessScalingDll = callable<[], DllDetectionResult>("check_lossless_scaling_dll"); export const getLsfgConfig = callable<[], ConfigResult>("get_lsfg_config"); export const getConfigSchema = callable<[], ConfigSchemaResult>("get_config_schema"); +export const getLaunchOption = callable<[], LaunchOptionResult>("get_launch_option"); // Updated config function using centralized configuration export const updateLsfgConfig = callable< - [boolean, number, number, boolean, boolean, boolean, boolean, number], + [boolean, string, number, number, boolean, boolean, string, number], ConfigUpdateResult >("update_lsfg_config"); // Helper function to create config update from configuration object export const updateLsfgConfigFromObject = async (config: ConfigurationData): Promise<ConfigUpdateResult> => { const args = ConfigurationManager.createArgsFromConfig(config); - return updateLsfgConfig(...args as [boolean, number, number, boolean, boolean, boolean, boolean, number]); + return updateLsfgConfig(...args as [boolean, string, number, number, boolean, boolean, string, number]); }; // Self-updater API functions diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx index 2545217..dc8da89 100644 --- a/src/components/ConfigurationSection.tsx +++ b/src/components/ConfigurationSection.tsx @@ -1,9 +1,9 @@ -import { PanelSectionRow, ToggleField, SliderField } from "@decky/ui"; +import { PanelSectionRow, ToggleField, SliderField, DropdownItem } from "@decky/ui"; import { ConfigurationData } from "../config/configSchema"; interface ConfigurationSectionProps { config: ConfigurationData; - onConfigChange: (fieldName: keyof ConfigurationData, value: boolean | number) => Promise<void>; + onConfigChange: (fieldName: keyof ConfigurationData, value: boolean | number | string) => Promise<void>; } export function ConfigurationSection({ @@ -27,28 +27,38 @@ export function ConfigurationSection({ </div> </PanelSectionRow> - <PanelSectionRow> + {/* <PanelSectionRow> <ToggleField label="Enable LSFG" - description="Enables the frame generation layer" - checked={config.enable_lsfg} - onChange={(value) => onConfigChange('enable_lsfg', value)} + description="Enables lsfg globally (apply before launching games)" + checked={config.enable} + onChange={(value) => onConfigChange('enable', value)} /> - </PanelSectionRow> + </PanelSectionRow> */} + + {/* <PanelSectionRow> + <TextField + label="Lossless.dll Path" + description="specify where Lossless.dll is stored" + value={config.dll} + onChange={(e) => onConfigChange('dll', e.target.value)} + /> + </PanelSectionRow> */} <PanelSectionRow> <SliderField label="FPS Multiplier" description="Traditional FPS multiplier value" value={config.multiplier} - min={2} + min={1} max={4} step={1} - notchCount={3} + notchCount={4} notchLabels={[ - { notchIndex: 0, label: "2X" }, - { notchIndex: 1, label: "3X" }, - { notchIndex: 2, label: "4X" } + { notchIndex: 0, label: "OFF" }, + { notchIndex: 1, label: "2X" }, + { notchIndex: 2, label: "3X" }, + { notchIndex: 3, label: "4X" } ]} onChange={(value) => onConfigChange('multiplier', value)} /> @@ -57,7 +67,7 @@ export function ConfigurationSection({ <PanelSectionRow> <SliderField label={`Flow Scale ${Math.round(config.flow_scale * 100)}%`} - description="Lowers the internal motion estimation resolution" + description="Lowers internal motion estimation resolution, improving performance slightly" value={config.flow_scale} min={0.25} max={1.0} @@ -68,51 +78,66 @@ export function ConfigurationSection({ <PanelSectionRow> <ToggleField - label="HDR Mode" - description="Enable HDR mode (only if Game supports HDR)" - checked={config.hdr} - onChange={(value) => onConfigChange('hdr', value)} + label="Performance Mode" + description="Uses a lighter model for FG (Recommended for most games)" + checked={config.performance_mode} + onChange={(value) => onConfigChange('performance_mode', value)} /> </PanelSectionRow> <PanelSectionRow> <ToggleField - label="Performance Mode" - description="Use lighter model for FG" - checked={config.perf_mode} - onChange={(value) => onConfigChange('perf_mode', value)} + label="HDR Mode" + description="Enables HDR mode (only for games that support HDR)" + checked={config.hdr_mode} + onChange={(value) => onConfigChange('hdr_mode', value)} /> </PanelSectionRow> <PanelSectionRow> - <ToggleField - label="Immediate Mode" - description="Reduce input lag (Experimental, will cause issues in many games)" - checked={config.immediate_mode} - onChange={(value) => onConfigChange('immediate_mode', value)} + <div + style={{ + fontSize: "14px", + fontWeight: "bold", + marginTop: "16px", + marginBottom: "8px", + borderBottom: "1px solid rgba(255, 255, 255, 0.2)", + paddingBottom: "4px", + color: "white" + }} + > + Experimental Features + </div> + </PanelSectionRow> + + <PanelSectionRow> + <DropdownItem + label="Override Vulkan present mode" + description="Select a specific Vulkan presentation mode for better performance or compatibility (may cause crashes)" + menuLabel="Select presentation mode" + selectedOption={config.experimental_present_mode} + onChange={(value) => onConfigChange('experimental_present_mode', value.data)} + rgOptions={[ + { data: "", label: "Default" }, + { data: "fifo", label: "FIFO" }, + { data: "vsync", label: "VSync" }, + { data: "mailbox", label: "Mailbox" }, + { data: "immediate", label: "Immediate" } + ]} /> </PanelSectionRow> <PanelSectionRow> <SliderField - label={`Game Frame Cap ${config.frame_cap === 0 ? "(Disabled)" : `(${config.frame_cap} FPS)`}`} - description="Limit base game FPS (0 = disabled)" - value={config.frame_cap} + label={`FPS Limit${config.experimental_fps_limit > 0 ? ` (${config.experimental_fps_limit} FPS)` : ' (Off)'}`} + description="Base framerate cap for DirectX games, before frame multiplier (requires game re-launch)" + value={config.experimental_fps_limit} min={0} max={60} step={1} - onChange={(value) => onConfigChange('frame_cap', value)} + onChange={(value) => onConfigChange('experimental_fps_limit', value)} /> </PanelSectionRow> - - {/* <PanelSectionRow> - <ToggleField - label="Disable vkbasalt" - description="Some plugins add vkbasalt layer, which can break lsfg. Toggling on fixes this" - checked={config.disable_vkbasalt} - onChange={(value) => onConfigChange('disable_vkbasalt', value)} - /> - </PanelSectionRow> */} </> ); } diff --git a/src/components/Content.tsx b/src/components/Content.tsx index ea3f3c1..613e722 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -37,7 +37,7 @@ export function Content() { }, [isInstalled, loadLsfgConfig]); // Generic configuration change handler - const handleConfigChange = async (fieldName: keyof ConfigurationData, value: boolean | number) => { + const handleConfigChange = async (fieldName: keyof ConfigurationData, value: boolean | number | string) => { await updateField(fieldName, value); }; diff --git a/src/components/LaunchOptionInfo.tsx b/src/components/LaunchOptionInfo.tsx new file mode 100644 index 0000000..298c45a --- /dev/null +++ b/src/components/LaunchOptionInfo.tsx @@ -0,0 +1,25 @@ +import { PanelSectionRow, Field } from "@decky/ui"; + +export function LaunchOptionInfo() { + return ( + <PanelSectionRow> + <Field + bottomSeparator="none" + label="Setup Instructions" + description={ + <> + <div>For each game where you want to use lsfg-vk:</div> + <div style={{ marginTop: "8px" }}> + 1. Right-click the game in Steam → Properties<br/> + 2. Add this to Launch Options: <code>LSFG_PROCESS=decky-lsfg-vk %command%</code><br/> + 3. Or use the "Copy Launch Option" button above + </div> + <div style={{ marginTop: "8px", fontStyle: "italic" }}> + This temporary solution allows hot-reloading while keeping you on the latest lsfg-vk version. + </div> + </> + } + /> + </PanelSectionRow> + ); +} diff --git a/src/components/PluginUpdateChecker.tsx b/src/components/PluginUpdateChecker.tsx index 0028a79..d427c18 100644 --- a/src/components/PluginUpdateChecker.tsx +++ b/src/components/PluginUpdateChecker.tsx @@ -1,7 +1,10 @@ import React, { useState, useEffect } from 'react'; import { ButtonItem, - PanelSection + PanelSection, + PanelSectionRow, + Field, + Focusable } from '@decky/ui'; import { checkForPluginUpdate, downloadPluginUpdate, UpdateCheckResult, UpdateDownloadResult } from '../api/lsfgApi'; @@ -99,88 +102,74 @@ export const PluginUpdateChecker: React.FC<PluginUpdateCheckerProps> = () => { if (updateInfo.updateAvailable) { if (downloadResult?.success) { - return ( - <div style={{ color: 'lightgreen', marginTop: '5px' }}> - ✓ v{updateInfo.latestVersion} downloaded - ready to install - </div> - ); + return "✓ v" + updateInfo.latestVersion + " downloaded - ready to install"; } else { - return ( - <div style={{ color: 'orange', marginTop: '5px' }}> - Update available: v{updateInfo.latestVersion} - </div> - ); + return "Update available: v" + updateInfo.latestVersion; } } else { - return ( - <div style={{ color: 'lightgreen', marginTop: '5px' }}> - Up to date (v{updateInfo.currentVersion}) - </div> - ); + return "Up to date (v" + updateInfo.currentVersion + ")"; } }; return ( - <PanelSection title="Plugin Updates"> - <ButtonItem - layout="below" - onClick={handleCheckForUpdate} - disabled={checkingUpdate} - description={getStatusMessage()} - > - {checkingUpdate ? 'Checking for updates...' : 'Check for Updates'} - </ButtonItem> - - {updateInfo && updateInfo.updateAvailable && !downloadResult?.success && ( + <PanelSection title="PLUGIN UPDATES"> + <PanelSectionRow> <ButtonItem layout="below" - onClick={handleDownloadUpdate} - disabled={downloadingUpdate} - description={`Download version ${updateInfo.latestVersion}`} + onClick={handleCheckForUpdate} + disabled={checkingUpdate} + description={getStatusMessage()} > - {downloadingUpdate ? 'Downloading...' : 'Download Update'} + {checkingUpdate ? 'Checking for updates...' : 'Check for Updates'} </ButtonItem> + </PanelSectionRow> + + {updateInfo && updateInfo.updateAvailable && !downloadResult?.success && ( + <PanelSectionRow> + <ButtonItem + layout="below" + onClick={handleDownloadUpdate} + disabled={downloadingUpdate} + description={`Download version ${updateInfo.latestVersion}`} + > + {downloadingUpdate ? 'Downloading...' : 'Download Update'} + </ButtonItem> + </PanelSectionRow> )} {downloadResult?.success && ( - <div style={{ - marginTop: '10px', - padding: '10px', - backgroundColor: 'rgba(0, 255, 0, 0.1)', - borderRadius: '4px', - border: '1px solid rgba(0, 255, 0, 0.3)' - }}> - <div style={{ color: 'lightgreen', fontWeight: 'bold', marginBottom: '5px' }}> - ✓ Download Complete! - </div> - <div style={{ fontSize: '12px', marginBottom: '10px' }}> - File saved to: {downloadResult.download_path} - </div> - <div style={{ fontSize: '12px' }}> - <strong>Installation Instructions:</strong> - <ol style={{ paddingLeft: '20px', marginTop: '5px' }}> - <li>Go to Decky Loader settings</li> - <li>Click "Developer" tab</li> - <li>Click "Uninstall" next to "Lossless Scaling"</li> - <li>Click "Install from ZIP"</li> - <li>Select the downloaded file</li> - <li>Restart Steam or reload plugins</li> - </ol> - </div> - </div> + <> + <PanelSectionRow> + <Field label="Download Complete!"> + <Focusable> + File saved to: {downloadResult.download_path} + </Focusable> + </Field> + </PanelSectionRow> + + <PanelSectionRow> + <Field label="Installation Instructions:"> + <Focusable> + 1. Go to Decky Loader settings + <br />2. Click "Developer" tab + <br />3. Click "Uninstall" next to "Lossless Scaling" + <br />4. Click "Install from ZIP" + <br />5. Select the downloaded file + <br />6. Restart Steam or reload plugins + </Focusable> + </Field> + </PanelSectionRow> + </> )} {updateError && ( - <div style={{ - color: 'red', - marginTop: '10px', - padding: '8px', - backgroundColor: 'rgba(255, 0, 0, 0.1)', - borderRadius: '4px', - fontSize: '12px' - }}> - {updateError} - </div> + <PanelSectionRow> + <Field label="Error:"> + <Focusable> + {updateError} + </Focusable> + </Field> + </PanelSectionRow> )} </PanelSection> ); diff --git a/src/components/UsageInstructions.tsx b/src/components/UsageInstructions.tsx index 727a0ab..8ac94d8 100644 --- a/src/components/UsageInstructions.tsx +++ b/src/components/UsageInstructions.tsx @@ -6,88 +6,89 @@ interface UsageInstructionsProps { } export function UsageInstructions({ config }: UsageInstructionsProps) { - // Build manual environment variables string based on current config - const buildManualEnvVars = (): string => { - const envVars: string[] = []; - - if (config.enable_lsfg) { - envVars.push("ENABLE_LSFG=1"); - } - - // Always include multiplier and flow_scale if LSFG is enabled, as they have defaults - if (config.enable_lsfg) { - envVars.push(`LSFG_MULTIPLIER=${config.multiplier}`); - envVars.push(`LSFG_FLOW_SCALE=${config.flow_scale}`); - } - - if (config.hdr) { - envVars.push("LSFG_HDR=1"); - } - - if (config.perf_mode) { - envVars.push("LSFG_PERF_MODE=1"); - } - - if (config.immediate_mode) { - envVars.push("MESA_VK_WSI_PRESENT_MODE=immediate"); - } - - if (config.disable_vkbasalt) { - envVars.push("DISABLE_VKBASALT=1"); - } - - if (config.frame_cap > 0) { - envVars.push(`DXVK_FRAME_RATE=${config.frame_cap}`); - } - - return envVars.length > 0 ? `${envVars.join(" ")} %command%` : "%command%"; - }; - return ( <> <PanelSectionRow> <div style={{ - fontSize: "13px", - marginTop: "12px", - padding: "8px", - backgroundColor: "rgba(255, 255, 255, 0.05)", - borderRadius: "4px" + fontSize: "14px", + fontWeight: "bold", + marginTop: "16px", + marginBottom: "8px", + borderBottom: "1px solid rgba(255, 255, 255, 0.2)", + paddingBottom: "4px" + }} + > + Usage Instructions + </div> + </PanelSectionRow> + + <PanelSectionRow> + <div + style={{ + fontSize: "12px", + lineHeight: "1.4", + opacity: "0.8", + whiteSpace: "pre-wrap" + }} + > + {config.enable + ? "Add the launch option below (or use \"Launch Option Clipboard\") to Steam games to activate frame generation." + : "LSFG is disabled. Enable it above and add the launch option to activate frame generation." + } + </div> + </PanelSectionRow> + + <PanelSectionRow> + <div + style={{ + fontSize: "12px", + lineHeight: "1.4", + opacity: "0.8", + backgroundColor: "rgba(255, 255, 255, 0.1)", + padding: "8px", + borderRadius: "4px", + fontFamily: "monospace", + marginTop: "8px", + marginBottom: "8px", + textAlign: "center" + }} + > + <strong>~/lsfg %command%</strong> + </div> + </PanelSectionRow> + + {/* <PanelSectionRow> + <div + style={{ + fontSize: "12px", + lineHeight: "1.4", + opacity: "0.8", + whiteSpace: "pre-wrap" + }} + > + {`Current Configuration: +• Enable: ${config.enable ? "Yes" : "No"} +• DLL Path: ${config.dll} +• Multiplier: ${config.multiplier}x +• Flow Scale: ${Math.round(config.flow_scale * 100)}% +• Performance Mode: ${config.performance_mode ? "Yes" : "No"} +• HDR Mode: ${config.hdr_mode ? "Yes" : "No"} +• Present Mode: ${config.experimental_present_mode || "Default (FIFO)"} +• FPS Limit: ${config.experimental_fps_limit > 0 ? `${config.experimental_fps_limit} FPS` : "Off"}`} + </div> + </PanelSectionRow> */} + + <PanelSectionRow> + <div + style={{ + fontSize: "11px", + lineHeight: "1.3", + opacity: "0.6", + marginTop: "8px" }} > - <div style={{ fontWeight: "bold", marginBottom: "6px" }}> - Usage Instructions: - </div> - <div style={{ marginBottom: "4px" }}> - Option 1: Use the lsfg script (recommended): - </div> - <div - style={{ - fontFamily: "monospace", - backgroundColor: "rgba(0, 0, 0, 0.3)", - padding: "4px", - borderRadius: "2px", - fontSize: "12px", - marginBottom: "6px" - }} - > - ~/lsfg %command% - </div> - <div style={{ marginBottom: "4px" }}> - Option 2: Manual environment variables: - </div> - <div - style={{ - fontFamily: "monospace", - backgroundColor: "rgba(0, 0, 0, 0.3)", - padding: "4px", - borderRadius: "2px", - fontSize: "12px", - marginBottom: "6px" - }} - > - {buildManualEnvVars()} - </div> +The configuration is stored in ~/.config/lsfg-vk/conf.toml and hot-reloads while games are running. </div> </PanelSectionRow> </> diff --git a/src/components/index.ts b/src/components/index.ts index d26159d..ed0b803 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -2,7 +2,8 @@ export { Content } from "./Content"; export { StatusDisplay } from "./StatusDisplay"; export { InstallationButton } from "./InstallationButton"; export { ConfigurationSection } from "./ConfigurationSection"; -export { UsageInstructions } from "./UsageInstructions"; +// export { UsageInstructions } from "./UsageInstructions"; export { WikiButton } from "./WikiButton"; export { ClipboardButton } from "./ClipboardButton"; +export { LaunchOptionInfo } from "./LaunchOptionInfo"; export { PluginUpdateChecker } from "./PluginUpdateChecker"; diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts index 6956030..9b6fc41 100644 --- a/src/config/configSchema.ts +++ b/src/config/configSchema.ts @@ -9,102 +9,87 @@ export enum ConfigFieldType { BOOLEAN = "boolean", INTEGER = "integer", - FLOAT = "float" + FLOAT = "float", + STRING = "string" } // Configuration field definition export interface ConfigField { name: string; fieldType: ConfigFieldType; - default: boolean | number; + default: boolean | number | string; description: string; - scriptTemplate: string; - scriptComment?: string; } // Configuration schema - must match Python CONFIG_SCHEMA export const CONFIG_SCHEMA: Record<string, ConfigField> = { - enable_lsfg: { - name: "enable_lsfg", + enable: { + name: "enable", fieldType: ConfigFieldType.BOOLEAN, default: true, - description: "Enables the frame generation layer", - scriptTemplate: "export ENABLE_LSFG={value}", - scriptComment: "# export ENABLE_LSFG=1" + description: "enable/disable lsfg on every game" + }, + + dll: { + name: "dll", + fieldType: ConfigFieldType.STRING, + default: "/games/Lossless Scaling/Lossless.dll", + description: "specify where Lossless.dll is stored" }, multiplier: { name: "multiplier", fieldType: ConfigFieldType.INTEGER, default: 2, - description: "Traditional FPS multiplier value", - scriptTemplate: "export LSFG_MULTIPLIER={value}" + description: "change the fps multiplier" }, flow_scale: { name: "flow_scale", fieldType: ConfigFieldType.FLOAT, default: 0.8, - description: "Lowers the internal motion estimation resolution", - scriptTemplate: "export LSFG_FLOW_SCALE={value}" - }, - - hdr: { - name: "hdr", - fieldType: ConfigFieldType.BOOLEAN, - default: false, - description: "Enable HDR mode (only if Game supports HDR)", - scriptTemplate: "export LSFG_HDR={value}", - scriptComment: "# export LSFG_HDR=1" + description: "change the flow scale" }, - perf_mode: { - name: "perf_mode", + performance_mode: { + name: "performance_mode", fieldType: ConfigFieldType.BOOLEAN, default: true, - description: "Use lighter model for FG", - scriptTemplate: "export LSFG_PERF_MODE={value}", - scriptComment: "# export LSFG_PERF_MODE=1" + description: "toggle performance mode" }, - immediate_mode: { - name: "immediate_mode", + hdr_mode: { + name: "hdr_mode", fieldType: ConfigFieldType.BOOLEAN, default: false, - description: "Reduce input lag (Experimental, will cause issues in many games)", - scriptTemplate: "export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync", - scriptComment: "# export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync" + description: "enable hdr in games that support it" }, - disable_vkbasalt: { - name: "disable_vkbasalt", - fieldType: ConfigFieldType.BOOLEAN, - default: true, - description: "Some plugins add vkbasalt layer, which can break lsfg. Toggling on fixes this", - scriptTemplate: "export DISABLE_VKBASALT={value}", - scriptComment: "# export DISABLE_VKBASALT=1" + experimental_present_mode: { + name: "experimental_present_mode", + fieldType: ConfigFieldType.STRING, + default: "", + description: "experimental: override vulkan present mode (empty/fifo/vsync/mailbox/immediate)" }, - frame_cap: { - name: "frame_cap", + experimental_fps_limit: { + name: "experimental_fps_limit", fieldType: ConfigFieldType.INTEGER, default: 0, - description: "Limit base game FPS (0 = disabled)", - scriptTemplate: "export DXVK_FRAME_RATE={value}", - scriptComment: "# export DXVK_FRAME_RATE=60" + description: "experimental: base framerate cap for dxvk games, before frame multiplier (0 = disabled)" } }; // Type-safe configuration data structure export interface ConfigurationData { - enable_lsfg: boolean; + enable: boolean; + dll: string; multiplier: number; flow_scale: number; - hdr: boolean; - perf_mode: boolean; - immediate_mode: boolean; - disable_vkbasalt: boolean; - frame_cap: number; + performance_mode: boolean; + hdr_mode: boolean; + experimental_present_mode: string; + experimental_fps_limit: number; } // Centralized configuration manager @@ -140,7 +125,7 @@ export class ConfigurationManager { /** * Create ordered arguments array from configuration object */ - static createArgsFromConfig(config: ConfigurationData): (boolean | number)[] { + static createArgsFromConfig(config: ConfigurationData): (boolean | number | string)[] { return this.getFieldNames().map(fieldName => config[fieldName as keyof ConfigurationData] ); @@ -163,6 +148,8 @@ export class ConfigurationManager { (validated as any)[fieldName] = parseInt(String(value), 10); } else if (fieldDef.fieldType === ConfigFieldType.FLOAT) { (validated as any)[fieldName] = parseFloat(String(value)); + } else if (fieldDef.fieldType === ConfigFieldType.STRING) { + (validated as any)[fieldName] = String(value); } } }); diff --git a/src/hooks/useLsfgHooks.ts b/src/hooks/useLsfgHooks.ts index 8ff9061..e514d72 100644 --- a/src/hooks/useLsfgHooks.ts +++ b/src/hooks/useLsfgHooks.ts @@ -110,7 +110,7 @@ export function useLsfgConfig() { } }, []); - const updateField = useCallback(async (fieldName: keyof ConfigurationData, value: boolean | number): Promise<ConfigUpdateResult> => { + const updateField = useCallback(async (fieldName: keyof ConfigurationData, value: boolean | number | string): Promise<ConfigUpdateResult> => { const newConfig = { ...config, [fieldName]: value }; return updateConfig(newConfig); }, [config, updateConfig]); diff --git a/src/index.tsx b/src/index.tsx index e8ab56f..785ecf5 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,6 +11,8 @@ export default definePlugin(() => { name: "Lossless Scaling", // The element displayed at the top of your plugin's menu titleView: <div className={staticClasses.Title}>Lossless Scaling</div>, + // Always render to retain state when panel is toggled + alwaysRender: true, // The content of your plugin's menu content: <Content />, // The icon displayed in the plugin list |
