From 2ddcbc9797e9fed272f72a2bce619f25923dc296 Mon Sep 17 00:00:00 2001 From: Ionite Date: Thu, 1 Jun 2023 17:34:37 -0400 Subject: [PATCH] InitialValue support in Launch definition --- StabilityMatrix/Helper/DialogFactory.cs | 6 +- .../Models/LaunchOptionDefinition.cs | 17 +++-- StabilityMatrix/Models/Packages/A3WebUI.cs | 23 ++++--- .../Models/Packages/VladAutomatic.cs | 17 +++-- .../LaunchOptionsDialogViewModel.cs | 66 +++++++++++++++---- 5 files changed, 95 insertions(+), 34 deletions(-) diff --git a/StabilityMatrix/Helper/DialogFactory.cs b/StabilityMatrix/Helper/DialogFactory.cs index d037ef3a..e9b4fc1a 100644 --- a/StabilityMatrix/Helper/DialogFactory.cs +++ b/StabilityMatrix/Helper/DialogFactory.cs @@ -25,13 +25,9 @@ public class DialogFactory : IDialogFactory public LaunchOptionsDialog CreateLaunchOptionsDialog(IEnumerable definitions, InstalledPackage installedPackage) { - launchOptionsDialogViewModel.Clear(); - // Create cards - launchOptionsDialogViewModel.CardsFromDefinitions(definitions); // Load user settings var userLaunchArgs = settingsManager.GetLaunchArgs(installedPackage.Id); - launchOptionsDialogViewModel.LoadFromLaunchArgs(userLaunchArgs); - + launchOptionsDialogViewModel.Initialize(definitions, userLaunchArgs); return new LaunchOptionsDialog(contentDialogService, launchOptionsDialogViewModel); } diff --git a/StabilityMatrix/Models/LaunchOptionDefinition.cs b/StabilityMatrix/Models/LaunchOptionDefinition.cs index 6ec360bc..e33b4365 100644 --- a/StabilityMatrix/Models/LaunchOptionDefinition.cs +++ b/StabilityMatrix/Models/LaunchOptionDefinition.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json.Serialization; namespace StabilityMatrix.Models; @@ -7,7 +8,7 @@ namespace StabilityMatrix.Models; /// public class LaunchOptionDefinition { - public string Name { get; set; } + public string Name { get; init; } /// /// Type of the option. "bool", "int", or "string" @@ -15,12 +16,19 @@ public class LaunchOptionDefinition /// - "int" and "string" should supply a single flag in the Options list (e.g. ["--width"], ["--api"]) /// public LaunchOptionType Type { get; init; } = LaunchOptionType.Bool; - public string? Description { get; set; } + public string? Description { get; init; } /// - /// Constant default value for the option. + /// Server-side default for the option. (Ignored for launch and saving if value matches) + /// Use `InitialValue` to provide a default that is set as the user value and used for launch. /// - public object? DefaultValue { get; set; } + public object? DefaultValue { get; init; } + + /// + /// Initial value for the option if no set value is available, set as the user value on save. + /// Use `DefaultValue` to provide a server-side default that is ignored for launch and saving. + /// + public object? InitialValue { get; set; } // Minimum number of selected options public int? MinSelectedOptions { get; set; } @@ -32,6 +40,7 @@ public class LaunchOptionDefinition /// public List Options { get; set; } + [JsonIgnore] public static LaunchOptionDefinition Extras => new() { Name = "Extra Launch Arguments", diff --git a/StabilityMatrix/Models/Packages/A3WebUI.cs b/StabilityMatrix/Models/Packages/A3WebUI.cs index 5f246c99..cef95b8d 100644 --- a/StabilityMatrix/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix/Models/Packages/A3WebUI.cs @@ -23,12 +23,6 @@ public class A3WebUI : BaseGitPackage public override List LaunchOptions => new() { - new() - { - Name = "API", - DefaultValue = true, - Options = new() {"--api"} - }, new() { Name = "Host", @@ -46,12 +40,25 @@ public class A3WebUI : BaseGitPackage new() { Name = "VRAM", - Options = new() {"--lowvram", "--medvram"} + InitialValue = HardwareHelper.IterGpuInfo().Select(gpu => gpu.MemoryLevel).Max() switch + { + Level.Low => "--lowvram", + Level.Medium => "--medvram", + _ => null + }, + Options = new() { "--lowvram", "--medvram" } }, new() { Name = "Xformers", - Options = new() {"--xformers"} + InitialValue = HardwareHelper.HasNvidiaGpu(), + Options = new() { "--xformers" } + }, + new() + { + Name = "API", + DefaultValue = true, + Options = new() {"--api"} }, LaunchOptionDefinition.Extras }; diff --git a/StabilityMatrix/Models/Packages/VladAutomatic.cs b/StabilityMatrix/Models/Packages/VladAutomatic.cs index 313b233d..a3b3c196 100644 --- a/StabilityMatrix/Models/Packages/VladAutomatic.cs +++ b/StabilityMatrix/Models/Packages/VladAutomatic.cs @@ -22,21 +22,28 @@ public class VladAutomatic : BaseGitPackage public override List LaunchOptions => new() { - new() - { - Name = "API", - Options = new() { "--api" } - }, new() { Name = "VRAM", + InitialValue = HardwareHelper.IterGpuInfo().Select(gpu => gpu.MemoryLevel).Max() switch + { + Level.Low => "--lowvram", + Level.Medium => "--medvram", + _ => null + }, Options = new() { "--lowvram", "--medvram" } }, new() { Name = "Xformers", + InitialValue = HardwareHelper.HasNvidiaGpu() ? "--xformers" : null, Options = new() { "--xformers" } }, + new() + { + Name = "API", + Options = new() { "--api" } + }, LaunchOptionDefinition.Extras }; diff --git a/StabilityMatrix/ViewModels/LaunchOptionsDialogViewModel.cs b/StabilityMatrix/ViewModels/LaunchOptionsDialogViewModel.cs index c37151e2..3ec6b88a 100644 --- a/StabilityMatrix/ViewModels/LaunchOptionsDialogViewModel.cs +++ b/StabilityMatrix/ViewModels/LaunchOptionsDialogViewModel.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using CommunityToolkit.Mvvm.ComponentModel; +using NLog; using StabilityMatrix.Helper.Cache; using StabilityMatrix.Models; @@ -12,6 +13,7 @@ namespace StabilityMatrix.ViewModels; public partial class LaunchOptionsDialogViewModel : ObservableObject { + public static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public ObservableCollection Cards { get; set; } = new(); [ObservableProperty] @@ -67,23 +69,52 @@ public partial class LaunchOptionsDialogViewModel : ObservableObject } return launchArgs; } - - /// - /// Create cards using definitions - /// - public void CardsFromDefinitions(IEnumerable definitions) + + public void Initialize(IEnumerable definitions, IEnumerable launchArgs) { + Clear(); + // During card creation, store dict of options with initial values + var initialOptions = new Dictionary(); + // Create cards foreach (var definition in definitions) { + // Check that non-bool types have exactly one option + if (definition.Type != LaunchOptionType.Bool && definition.Options.Count != 1) + { + throw new InvalidOperationException( + $"Definition: '{definition.Name}' has {definition.Options.Count} options," + + $" it must have exactly 1 option for non-bool types"); + } + // Store initial values + if (definition.InitialValue != null) + { + // For bool types, initial value can be string (single/multiple options) or bool (single option) + if (definition.Type == LaunchOptionType.Bool) + { + // For single option, check bool + if (definition.Options.Count == 1 && definition.InitialValue is bool boolValue) + { + initialOptions[definition.Options.First()] = boolValue; + } + // For single/multiple options (string only) + var option = definition.Options.FirstOrDefault(opt => opt.Equals(definition.InitialValue)); + if (option == null) + { + throw new InvalidOperationException( + $"Definition '{definition.Name}' has InitialValue of '{definition.InitialValue}', but it was not found in options:" + + $" '{string.Join(",", definition.Options)}'"); + } + initialOptions[option] = true; + } + else + { + // Otherwise store initial value for first option + initialOptions[definition.Options.First()] = definition.InitialValue; + } + } Cards.Add(new LaunchOptionCard(definition)); } - } - - /// - /// Import the current cards options from a list of strings - /// - public void LoadFromLaunchArgs(IEnumerable launchArgs) - { + // Load launch args var launchArgsDict = launchArgs.ToDictionary(launchArg => launchArg.Name); foreach (var card in Cards) { @@ -91,6 +122,17 @@ public partial class LaunchOptionsDialogViewModel : ObservableObject { var userOption = launchArgsDict.GetValueOrDefault(option.Name); var userValue = userOption?.OptionValue?.ToString(); + // If no user value, check for initial value + if (userValue == null) + { + var initialValue = initialOptions.GetValueOrDefault(option.Name); + if (initialValue != null) + { + userValue = initialValue.ToString(); + Logger.Info("Using initial value '{InitialValue}' for option '{OptionName}'", + initialValue, option.Name); + } + } option.SetValueFromString(userValue); } }