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)
{
InitializeBuffers(settings);
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);
DrawApiSettings(listingStandard, settings);
DrawGenerationSettings(listingStandard, settings);
DrawSamplerSchedulerSettings(listingStandard, settings);
DrawPromptsSettings(listingStandard, settings);
DrawOptionsSettings(listingStandard, settings);
listingStandard.End();
Widgets.EndScrollView();
}
private static void InitializeBuffers(AIImagesModSettings settings)
{
if (string.IsNullOrEmpty(stepsBuffer))
{
stepsBuffer = settings.steps.ToString();
widthBuffer = settings.width.ToString();
heightBuffer = settings.height.ToString();
}
}
private static void DrawApiSettings(
Listing_Standard listingStandard,
AIImagesModSettings 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);
}
DrawModelDropdown(listingStandard, settings);
if (listingStandard.ButtonText("AIImages.Settings.LoadSamplersSchedulers".Translate()))
{
_ = LoadSamplersAndSchedulers(settings);
}
listingStandard.Gap(12f);
}
private static void DrawModelDropdown(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
if (
listingStandard.ButtonTextLabeled(
"AIImages.Settings.Model".Translate(),
string.IsNullOrEmpty(settings.selectedModel)
? "AIImages.Settings.NoModelSelected".Translate()
: settings.selectedModel
)
)
{
List modelOptions = new List();
if (!settings.availableModels.Any())
{
modelOptions.Add(
new FloatMenuOption("AIImages.Settings.LoadModelsFirst".Translate(), null)
);
}
else
{
foreach (string model in settings.availableModels)
{
string localModel = model;
modelOptions.Add(
new FloatMenuOption(model, () => settings.selectedModel = localModel)
);
}
}
Find.WindowStack.Add(new FloatMenu(modelOptions));
}
}
private static void DrawGenerationSettings(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
listingStandard.Label(
"AIImages.Settings.GenerationSection".Translate(),
-1f,
"AIImages.Settings.GenerationSectionTooltip".Translate()
);
listingStandard.GapLine();
DrawArtStyleDropdown(listingStandard, settings);
listingStandard.Gap(8f);
listingStandard.Label("AIImages.Settings.Steps".Translate() + $": {settings.steps}");
settings.steps = (int)listingStandard.Slider(settings.steps, 1, 150);
listingStandard.Gap(8f);
listingStandard.Label(
"AIImages.Settings.CfgScale".Translate() + $": {settings.cfgScale:F1}"
);
settings.cfgScale = listingStandard.Slider(settings.cfgScale, 1f, 30f);
listingStandard.Gap(8f);
DrawSizeSettings(listingStandard, settings);
listingStandard.Gap(12f);
}
private static void DrawArtStyleDropdown(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
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));
}
}
private static void DrawSizeSettings(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
listingStandard.Label("AIImages.Settings.Width".Translate() + ":");
widthBuffer = listingStandard.TextEntry(widthBuffer);
if (int.TryParse(widthBuffer, out int width))
{
settings.width = Mathf.Clamp(width, 64, 2048);
}
listingStandard.Label("AIImages.Settings.Height".Translate() + ":");
heightBuffer = listingStandard.TextEntry(heightBuffer);
if (int.TryParse(heightBuffer, out int height))
{
settings.height = Mathf.Clamp(height, 64, 2048);
}
DrawSizePresets(listingStandard, settings);
}
private static void DrawSizePresets(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
listingStandard.Gap(4f);
Rect presetRect1 = listingStandard.GetRect(30f);
DrawPresetButton(presetRect1, 0f, "512x512", 512, 512, settings);
DrawPresetButton(presetRect1, 85f, "512x768", 512, 768, settings);
DrawPresetButton(presetRect1, 170f, "768x768", 768, 768, settings);
listingStandard.Gap(4f);
Rect presetRect2 = listingStandard.GetRect(30f);
DrawPresetButton(presetRect2, 0f, "896x1152", 896, 1152, settings, 90f);
DrawPresetButton(presetRect2, 95f, "1024x1024", 1024, 1024, settings, 90f);
}
private static void DrawPresetButton(
Rect rect,
float xOffset,
string label,
int width,
int height,
AIImagesModSettings settings,
float buttonWidth = 80f
)
{
if (Widgets.ButtonText(new Rect(rect.x + xOffset, rect.y, buttonWidth, 30f), label))
{
settings.width = width;
settings.height = height;
widthBuffer = width.ToString();
heightBuffer = height.ToString();
}
}
private static void DrawSamplerSchedulerSettings(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
DrawSamplerDropdown(listingStandard, settings);
DrawSchedulerDropdown(listingStandard, settings);
listingStandard.Gap(12f);
}
private static void DrawSamplerDropdown(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
if (
listingStandard.ButtonTextLabeled(
"AIImages.Settings.Sampler".Translate(),
settings.selectedSampler
)
)
{
List samplerOptions = new List();
var availableSamplers = settings.availableSamplers.Any()
? settings.availableSamplers
: new List { settings.selectedSampler };
foreach (string sampler in availableSamplers)
{
string localSampler = sampler;
samplerOptions.Add(
new FloatMenuOption(sampler, () => settings.selectedSampler = localSampler)
);
}
Find.WindowStack.Add(new FloatMenu(samplerOptions));
}
}
private static void DrawSchedulerDropdown(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
if (
listingStandard.ButtonTextLabeled(
"AIImages.Settings.Scheduler".Translate(),
settings.selectedScheduler
)
)
{
List schedulerOptions = new List();
var availableSchedulers = settings.availableSchedulers.Any()
? settings.availableSchedulers
: new List { settings.selectedScheduler };
foreach (string scheduler in availableSchedulers)
{
string localScheduler = scheduler;
schedulerOptions.Add(
new FloatMenuOption(
scheduler,
() => settings.selectedScheduler = localScheduler
)
);
}
Find.WindowStack.Add(new FloatMenu(schedulerOptions));
}
}
private static void DrawPromptsSettings(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
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);
}
private static void DrawOptionsSettings(
Listing_Standard listingStandard,
AIImagesModSettings settings
)
{
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);
listingStandard.Label("AIImages.Settings.SavePath".Translate() + ":");
settings.savePath = listingStandard.TextEntry(settings.savePath);
}
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);
settings.availableModels = models;
if (models.Count > 0)
{
Messages.Message(
"AIImages.Settings.ModelsLoaded".Translate(models.Count),
MessageTypeDefOf.PositiveEvent
);
if (
(
string.IsNullOrEmpty(settings.selectedModel)
|| !models.Contains(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
);
}
}
private static async System.Threading.Tasks.Task LoadSamplersAndSchedulers(
AIImagesModSettings settings
)
{
try
{
Log.Message("[AI Images] Loading samplers and schedulers from API...");
var samplers = await AIImagesMod.ApiService.GetAvailableSamplers(
settings.apiEndpoint
);
settings.availableSamplers = samplers;
var schedulers = await AIImagesMod.ApiService.GetAvailableSchedulers(
settings.apiEndpoint
);
settings.availableSchedulers = schedulers;
int totalCount = samplers.Count + schedulers.Count;
if (totalCount > 0)
{
Messages.Message(
"AIImages.Settings.SamplersSchedulersLoaded".Translate(
samplers.Count,
schedulers.Count
),
MessageTypeDefOf.PositiveEvent
);
if (
(
string.IsNullOrEmpty(settings.selectedSampler)
|| !samplers.Contains(settings.selectedSampler)
)
&& samplers.Count > 0
)
{
settings.selectedSampler = samplers[0];
}
if (
(
string.IsNullOrEmpty(settings.selectedScheduler)
|| !schedulers.Contains(settings.selectedScheduler)
)
&& schedulers.Count > 0
)
{
settings.selectedScheduler = schedulers[0];
}
}
else
{
Messages.Message(
"AIImages.Settings.NoSamplersSchedulersFound".Translate(),
MessageTypeDefOf.RejectInput
);
}
}
catch (Exception ex)
{
Messages.Message(
$"Error loading samplers/schedulers: {ex.Message}",
MessageTypeDefOf.RejectInput
);
}
}
}
}