using System; using System.Collections.Generic; using System.Linq; using AIImages.Models; using AIImages.Settings; using RimWorld; using UnityEngine; using Verse; namespace AIImages { /// /// UI для настроек мода в меню настроек RimWorld /// public static class AIImagesSettingsUI { private static Vector2 scrollPosition = Vector2.zero; private static string stepsBuffer; private static string widthBuffer; private static string heightBuffer; public static void DoSettingsWindowContents(Rect inRect, AIImagesModSettings settings) { // Инициализируем буферы при первом вызове if (string.IsNullOrEmpty(stepsBuffer)) { stepsBuffer = settings.steps.ToString(); widthBuffer = settings.width.ToString(); heightBuffer = settings.height.ToString(); } Listing_Standard listingStandard = new Listing_Standard(); Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1200f); Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect); listingStandard.Begin(viewRect); // === API Settings === listingStandard.Label( "AIImages.Settings.ApiSection".Translate(), -1f, "AIImages.Settings.ApiSectionTooltip".Translate() ); listingStandard.GapLine(); listingStandard.Label("AIImages.Settings.ApiEndpoint".Translate() + ":"); settings.apiEndpoint = listingStandard.TextEntry(settings.apiEndpoint); listingStandard.Gap(8f); // Кнопка проверки подключения if (listingStandard.ButtonText("AIImages.Settings.TestConnection".Translate())) { _ = TestApiConnection(settings.apiEndpoint); } // Кнопка загрузки моделей if (listingStandard.ButtonText("AIImages.Settings.LoadModels".Translate())) { _ = LoadModelsFromApi(settings); } listingStandard.Gap(12f); // === Generation Settings === listingStandard.Label( "AIImages.Settings.GenerationSection".Translate(), -1f, "AIImages.Settings.GenerationSectionTooltip".Translate() ); listingStandard.GapLine(); // Art Style if ( listingStandard.ButtonTextLabeled( "AIImages.Settings.ArtStyle".Translate(), settings.artStyle.ToString() ) ) { List styleOptions = new List(); foreach (ArtStyle style in Enum.GetValues(typeof(ArtStyle))) { ArtStyle localStyle = style; styleOptions.Add( new FloatMenuOption(style.ToString(), () => settings.artStyle = localStyle) ); } Find.WindowStack.Add(new FloatMenu(styleOptions)); } // Shot Type if ( listingStandard.ButtonTextLabeled( "AIImages.Settings.ShotType".Translate(), settings.shotType.ToString() ) ) { List shotOptions = new List(); foreach (ShotType shot in Enum.GetValues(typeof(ShotType))) { ShotType localShot = shot; shotOptions.Add( new FloatMenuOption(shot.ToString(), () => settings.shotType = localShot) ); } Find.WindowStack.Add(new FloatMenu(shotOptions)); } listingStandard.Gap(8f); // Steps listingStandard.Label("AIImages.Settings.Steps".Translate() + $": {settings.steps}"); settings.steps = (int)listingStandard.Slider(settings.steps, 1, 150); listingStandard.Gap(8f); // CFG Scale listingStandard.Label( "AIImages.Settings.CfgScale".Translate() + $": {settings.cfgScale:F1}" ); settings.cfgScale = listingStandard.Slider(settings.cfgScale, 1f, 30f); listingStandard.Gap(8f); // Width listingStandard.Label("AIImages.Settings.Width".Translate() + ":"); widthBuffer = listingStandard.TextEntry(widthBuffer); if (int.TryParse(widthBuffer, out int width)) { settings.width = Mathf.Clamp(width, 64, 2048); } // Height listingStandard.Label("AIImages.Settings.Height".Translate() + ":"); heightBuffer = listingStandard.TextEntry(heightBuffer); if (int.TryParse(heightBuffer, out int height)) { settings.height = Mathf.Clamp(height, 64, 2048); } // Common size presets listingStandard.Gap(4f); Rect presetRect = listingStandard.GetRect(30f); if (Widgets.ButtonText(new Rect(presetRect.x, presetRect.y, 80f, 30f), "512x512")) { settings.width = 512; settings.height = 512; widthBuffer = "512"; heightBuffer = "512"; } if (Widgets.ButtonText(new Rect(presetRect.x + 85f, presetRect.y, 80f, 30f), "512x768")) { settings.width = 512; settings.height = 768; widthBuffer = "512"; heightBuffer = "768"; } if ( Widgets.ButtonText(new Rect(presetRect.x + 170f, presetRect.y, 80f, 30f), "768x768") ) { settings.width = 768; settings.height = 768; widthBuffer = "768"; heightBuffer = "768"; } listingStandard.Gap(12f); // Sampler listingStandard.Label("AIImages.Settings.Sampler".Translate() + ":"); settings.selectedSampler = listingStandard.TextEntry(settings.selectedSampler); listingStandard.Gap(12f); // === Prompts === listingStandard.Label( "AIImages.Settings.PromptsSection".Translate(), -1f, "AIImages.Settings.PromptsSectionTooltip".Translate() ); listingStandard.GapLine(); listingStandard.Label("AIImages.Settings.BasePositivePrompt".Translate() + ":"); settings.basePositivePrompt = listingStandard.TextEntry(settings.basePositivePrompt, 3); listingStandard.Gap(8f); listingStandard.Label("AIImages.Settings.BaseNegativePrompt".Translate() + ":"); settings.baseNegativePrompt = listingStandard.TextEntry(settings.baseNegativePrompt, 3); listingStandard.Gap(12f); // === Options === listingStandard.Label("AIImages.Settings.OptionsSection".Translate()); listingStandard.GapLine(); listingStandard.CheckboxLabeled( "AIImages.Settings.AutoLoadModels".Translate(), ref settings.autoLoadModels ); listingStandard.CheckboxLabeled( "AIImages.Settings.ShowTechnicalInfo".Translate(), ref settings.showTechnicalInfo ); listingStandard.CheckboxLabeled( "AIImages.Settings.SaveHistory".Translate(), ref settings.saveGenerationHistory ); listingStandard.Gap(12f); // Save path listingStandard.Label("AIImages.Settings.SavePath".Translate() + ":"); settings.savePath = listingStandard.TextEntry(settings.savePath); listingStandard.End(); Widgets.EndScrollView(); } private static async System.Threading.Tasks.Task TestApiConnection(string endpoint) { try { Log.Message($"[AI Images] Testing connection to {endpoint}..."); bool available = await AIImagesMod.ApiService.CheckApiAvailability(endpoint); if (available) { Messages.Message( "AIImages.Settings.ConnectionSuccess".Translate(), MessageTypeDefOf.PositiveEvent ); } else { Messages.Message( "AIImages.Settings.ConnectionFailed".Translate(), MessageTypeDefOf.RejectInput ); } } catch (Exception ex) { Messages.Message($"Error: {ex.Message}", MessageTypeDefOf.RejectInput); } } private static async System.Threading.Tasks.Task LoadModelsFromApi( AIImagesModSettings settings ) { try { Log.Message("[AI Images] Loading models from API..."); var models = await AIImagesMod.ApiService.GetAvailableModels(settings.apiEndpoint); if (models.Count > 0) { Messages.Message( "AIImages.Settings.ModelsLoaded".Translate(models.Count), MessageTypeDefOf.PositiveEvent ); // Если модель не выбрана, выбираем первую if (string.IsNullOrEmpty(settings.selectedModel) && models.Count > 0) { settings.selectedModel = models[0]; } } else { Messages.Message( "AIImages.Settings.NoModelsFound".Translate(), MessageTypeDefOf.RejectInput ); } } catch (Exception ex) { Messages.Message( $"Error loading models: {ex.Message}", MessageTypeDefOf.RejectInput ); } } } }