285 lines
10 KiB
C#
285 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AIImages.Models;
|
|
using AIImages.Settings;
|
|
using RimWorld;
|
|
using UnityEngine;
|
|
using Verse;
|
|
|
|
namespace AIImages
|
|
{
|
|
/// <summary>
|
|
/// UI для настроек мода в меню настроек RimWorld
|
|
/// </summary>
|
|
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<FloatMenuOption> styleOptions = new List<FloatMenuOption>();
|
|
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<FloatMenuOption> shotOptions = new List<FloatMenuOption>();
|
|
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
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|