diff options
| -rw-r--r-- | justfile | 7 | ||||
| -rw-r--r-- | py_modules/lsfg_vk/configuration.py | 2 | ||||
| -rw-r--r-- | py_modules/lsfg_vk/plugin.py | 40 | ||||
| -rw-r--r-- | scripts/generate_ts_schema.py | 135 | ||||
| -rw-r--r-- | src/api/lsfgApi.ts | 11 | ||||
| -rw-r--r-- | src/components/ConfigurationSection.tsx | 26 | ||||
| -rw-r--r-- | src/config/configSchema.ts | 23 |
7 files changed, 183 insertions, 61 deletions
@@ -1,8 +1,11 @@ default: - echo "Available recipes: build, test, clean" + echo "Available recipes: build, test, clean, generate-schema" + +generate-schema: + python3 scripts/generate_ts_schema.py build: - sudo rm -rf node_modules && .vscode/build.sh + python3 scripts/generate_ts_schema.py && sudo rm -rf node_modules && .vscode/build.sh test: scp "out/Lossless Scaling.zip" deck@192.168.0.6:~/Desktop diff --git a/py_modules/lsfg_vk/configuration.py b/py_modules/lsfg_vk/configuration.py index 82982e5..68ff577 100644 --- a/py_modules/lsfg_vk/configuration.py +++ b/py_modules/lsfg_vk/configuration.py @@ -222,7 +222,7 @@ class ConfigurationService(BaseService): if config.get("mangohud_workaround", False): lines.append("export MANGOHUD=1") - lines.append("export MANGOHUD_CONFIG=alpha=0.01,background_alpha=0.01") + lines.append("export MANGOHUD_CONFIG=alpha=0.001,background_alpha=0.001") if config.get("disable_vkbasalt", False): lines.append("export DISABLE_VKBASALT=1") diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py index 7deed71..d126d84 100644 --- a/py_modules/lsfg_vk/plugin.py +++ b/py_modules/lsfg_vk/plugin.py @@ -184,36 +184,30 @@ class Plugin: "defaults": ConfigurationManager.get_defaults() } - async def update_lsfg_config(self, dll: str, multiplier: int, flow_scale: float, - performance_mode: bool, hdr_mode: bool, - experimental_present_mode: str = "fifo", - dxvk_frame_rate: int = 0, - enable_wow64: bool = False, - disable_steamdeck_mode: bool = False, - mangohud_workaround: bool = False, - disable_vkbasalt: bool = False) -> Dict[str, Any]: - """Update lsfg TOML configuration + async def update_lsfg_config(self, config: Dict[str, Any]) -> Dict[str, Any]: + """Update lsfg TOML configuration using object-based API Args: - dll: Path to Lossless.dll - multiplier: LSFG multiplier value - flow_scale: LSFG flow scale value - performance_mode: Whether to enable performance mode - hdr_mode: Whether to enable HDR mode - experimental_present_mode: Experimental Vulkan present mode override - dxvk_frame_rate: Frame rate cap for DirectX games, before frame multiplier (0 = disabled) - enable_wow64: Whether to enable PROTON_USE_WOW64=1 for 32-bit games - disable_steamdeck_mode: Whether to disable Steam Deck mode - mangohud_workaround: Whether to enable MangoHud workaround with transparent overlay - disable_vkbasalt: Whether to disable vkBasalt layer + config: Configuration data dictionary containing all settings Returns: ConfigurationResponse dict with success status """ + # Validate and extract configuration from the config dict + validated_config = ConfigurationManager.validate_config(config) + return self.configuration_service.update_config( - dll, multiplier, flow_scale, performance_mode, hdr_mode, - experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode, - mangohud_workaround, disable_vkbasalt + dll=validated_config["dll"], + multiplier=validated_config["multiplier"], + flow_scale=validated_config["flow_scale"], + performance_mode=validated_config["performance_mode"], + hdr_mode=validated_config["hdr_mode"], + experimental_present_mode=validated_config["experimental_present_mode"], + dxvk_frame_rate=validated_config["dxvk_frame_rate"], + enable_wow64=validated_config["enable_wow64"], + disable_steamdeck_mode=validated_config["disable_steamdeck_mode"], + mangohud_workaround=validated_config["mangohud_workaround"], + disable_vkbasalt=validated_config["disable_vkbasalt"] ) async def update_dll_path(self, dll_path: str) -> Dict[str, Any]: diff --git a/scripts/generate_ts_schema.py b/scripts/generate_ts_schema.py new file mode 100644 index 0000000..dcdddf2 --- /dev/null +++ b/scripts/generate_ts_schema.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +""" +Generate TypeScript schema from Python shared_config.py + +This script reads the canonical schema from shared_config.py and generates +the corresponding TypeScript files, ensuring single source of truth. +""" + +import sys +from pathlib import Path + +# Add project root to path to import shared_config +project_root = Path(__file__).parent.parent +sys.path.insert(0, str(project_root)) + +from shared_config import CONFIG_SCHEMA_DEF, ConfigFieldType + + +def generate_typescript_schema(): + """Generate generatedConfigSchema.ts from Python schema""" + + # Generate enum + enum_lines = [ + "// src/config/generatedConfigSchema.ts", + "// Configuration field type enum - matches Python", + "export enum ConfigFieldType {", + " BOOLEAN = \"boolean\",", + " INTEGER = \"integer\",", + " FLOAT = \"float\",", + " STRING = \"string\"", + "}", + "", + "// Configuration field definition", + "export interface ConfigField {", + " name: string;", + " fieldType: ConfigFieldType;", + " default: boolean | number | string;", + " description: string;", + "}", + "", + "// Configuration schema - auto-generated from Python", + "export const CONFIG_SCHEMA: Record<string, ConfigField> = {" + ] + + # Generate schema entries + schema_entries = [] + interface_fields = [] + defaults_fields = [] + field_types = [] + + for field_name, field_def in CONFIG_SCHEMA_DEF.items(): + # Schema entry + default_value = field_def["default"] + if isinstance(default_value, str): + default_str = f'"{default_value}"' + elif isinstance(default_value, bool): + default_str = "true" if default_value else "false" + else: + default_str = str(default_value) + + schema_entries.append(f' {field_name}: {{') + schema_entries.append(f' name: "{field_def["name"]}",') + schema_entries.append(f' fieldType: ConfigFieldType.{field_def["fieldType"].upper()},') + schema_entries.append(f' default: {default_str},') + schema_entries.append(f' description: "{field_def["description"]}"') + schema_entries.append(' },') + + # Interface field + if field_def["fieldType"] == ConfigFieldType.BOOLEAN: + ts_type = "boolean" + elif field_def["fieldType"] == ConfigFieldType.INTEGER: + ts_type = "number" + elif field_def["fieldType"] == ConfigFieldType.FLOAT: + ts_type = "number" + elif field_def["fieldType"] == ConfigFieldType.STRING: + ts_type = "string" + else: + ts_type = "any" + + interface_fields.append(f' {field_name}: {ts_type};') + defaults_fields.append(f' {field_name}: {default_str},') + field_types.append(f' {field_name}: ConfigFieldType.{field_def["fieldType"].upper()},') + + # Complete the file + all_lines = enum_lines + schema_entries + [ + "};", + "", + "// Type-safe configuration data structure", + "export interface ConfigurationData {", + ] + interface_fields + [ + "}", + "", + "// Helper functions", + "export function getFieldNames(): string[] {", + " return Object.keys(CONFIG_SCHEMA);", + "}", + "", + "export function getDefaults(): ConfigurationData {", + " return {", + ] + defaults_fields + [ + " };", + "}", + "", + "export function getFieldTypes(): Record<string, ConfigFieldType> {", + " return {", + ] + field_types + [ + " };", + "}", + "", + "" + ] + + return "\n".join(all_lines) + + +def main(): + """Main function to generate TypeScript schema""" + try: + # Generate the TypeScript content + ts_content = generate_typescript_schema() + + # Write to the target file + target_file = project_root / "src" / "config" / "generatedConfigSchema.ts" + target_file.write_text(ts_content) + + print(f"✅ Generated {target_file} from shared_config.py") + print(f" Fields: {len(CONFIG_SCHEMA_DEF)}") + + except Exception as e: + print(f"❌ Error generating TypeScript schema: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts index 0b221e9..8d14da6 100644 --- a/src/api/lsfgApi.ts +++ b/src/api/lsfgApi.ts @@ -1,5 +1,5 @@ import { callable } from "@decky/api"; -import { ConfigurationData, ConfigurationManager } from "../config/configSchema"; +import { ConfigurationData } from "../config/configSchema"; // Type definitions for API responses export interface InstallationResult { @@ -99,16 +99,15 @@ export const getLaunchOption = callable<[], LaunchOptionResult>("get_launch_opti export const getConfigFileContent = callable<[], FileContentResult>("get_config_file_content"); export const getLaunchScriptContent = callable<[], FileContentResult>("get_launch_script_content"); -// Updated config function using centralized configuration +// Updated config function using object-based configuration (single source of truth) export const updateLsfgConfig = callable< - [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean], + [ConfigurationData], ConfigUpdateResult >("update_lsfg_config"); -// Helper function to create config update from configuration object +// Legacy helper function for backward compatibility export const updateLsfgConfigFromObject = async (config: ConfigurationData): Promise<ConfigUpdateResult> => { - const args = ConfigurationManager.createArgsFromConfig(config); - return updateLsfgConfig(...args as [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean]); + return updateLsfgConfig(config); }; // Self-updater API functions diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx index 26099e7..1c0d2b2 100644 --- a/src/components/ConfigurationSection.tsx +++ b/src/components/ConfigurationSection.tsx @@ -112,16 +112,26 @@ export function ConfigurationSection({ <PanelSectionRow> <div style={{ - fontSize: "14px", - fontWeight: "bold", - marginTop: "16px", - marginBottom: "8px", - borderBottom: "1px solid rgba(255, 255, 255, 0.2)", - paddingBottom: "4px", - color: "white" + fontSize: "14px", + fontWeight: "bold", + marginTop: "16px", + marginBottom: "2px", + borderBottom: "1px solid rgba(255, 255, 255, 0.2)", + paddingBottom: "2px", + color: "white" + }} + > + Environment Variables + </div> + <div + style={{ + fontSize: "12px", + color: "#cccccc", + marginTop: "2px", + marginBottom: "8px" }} > - Environment Variables (Requires re-launch) + Must be toggled before game start or restart game to take effect </div> </PanelSectionRow> diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts index 979d3c9..fdf6212 100644 --- a/src/config/configSchema.ts +++ b/src/config/configSchema.ts @@ -8,6 +8,7 @@ import { callable } from "@decky/api"; import type { ConfigurationData } from './generatedConfigSchema'; import { getDefaults } from './generatedConfigSchema'; +import { updateLsfgConfig } from "../api/lsfgApi"; // Re-export all auto-generated configuration constants export { @@ -30,7 +31,6 @@ export class ConfigurationManager { // Callable methods for backend communication private getConfiguration = callable<[], { success: boolean; data?: ConfigurationData; error?: string }>("get_configuration"); - private setConfiguration = callable<[{ config_data: ConfigurationData }], { success: boolean; error?: string }>("set_configuration"); private resetConfiguration = callable<[], { success: boolean; data?: ConfigurationData; error?: string }>("reset_configuration"); private constructor() {} @@ -50,25 +50,6 @@ export class ConfigurationManager { } /** - * Create args array from config object for lsfg API calls - */ - static createArgsFromConfig(config: ConfigurationData): [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean] { - return [ - config.dll, - config.multiplier, - config.flow_scale, - config.performance_mode, - config.hdr_mode, - config.experimental_present_mode, - config.dxvk_frame_rate, - config.enable_wow64, - config.disable_steamdeck_mode, - config.mangohud_workaround, - config.disable_vkbasalt - ]; - } - - /** * Load configuration from backend */ async loadConfig(): Promise<ConfigurationData> { @@ -91,7 +72,7 @@ export class ConfigurationManager { */ async saveConfig(config: ConfigurationData): Promise<void> { try { - const result = await this.setConfiguration({ config_data: config }); + const result = await updateLsfgConfig(config); if (result.success) { this._config = config; } else { |
