Enhance AIImages mod by adding cancellation support for image generation, improving user experience with localized strings for cancellation actions in English and Russian. Refactor service integration for better dependency management and update AIImages.dll to reflect these changes.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AIImages.Helpers;
|
||||
using AIImages.Models;
|
||||
using AIImages.Services;
|
||||
using AIImages.Settings;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
@@ -19,7 +21,11 @@ namespace AIImages
|
||||
private static string widthBuffer;
|
||||
private static string heightBuffer;
|
||||
|
||||
public static void DoSettingsWindowContents(Rect inRect, AIImagesModSettings settings)
|
||||
public static void DoSettingsWindowContents(
|
||||
Rect inRect,
|
||||
AIImagesModSettings settings,
|
||||
ServiceContainer serviceContainer
|
||||
)
|
||||
{
|
||||
InitializeBuffers(settings);
|
||||
|
||||
@@ -29,7 +35,7 @@ namespace AIImages
|
||||
Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect);
|
||||
listingStandard.Begin(viewRect);
|
||||
|
||||
DrawApiSettings(listingStandard, settings);
|
||||
DrawApiSettings(listingStandard, settings, serviceContainer);
|
||||
DrawGenerationSettings(listingStandard, settings);
|
||||
DrawSamplerSchedulerSettings(listingStandard, settings);
|
||||
DrawPromptsSettings(listingStandard, settings);
|
||||
@@ -51,7 +57,8 @@ namespace AIImages
|
||||
|
||||
private static void DrawApiSettings(
|
||||
Listing_Standard listingStandard,
|
||||
AIImagesModSettings settings
|
||||
AIImagesModSettings settings,
|
||||
ServiceContainer serviceContainer
|
||||
)
|
||||
{
|
||||
listingStandard.Label(
|
||||
@@ -61,18 +68,36 @@ namespace AIImages
|
||||
);
|
||||
listingStandard.GapLine();
|
||||
|
||||
string oldEndpoint = settings.apiEndpoint;
|
||||
listingStandard.Label("AIImages.Settings.ApiEndpoint".Translate() + ":");
|
||||
settings.apiEndpoint = listingStandard.TextEntry(settings.apiEndpoint);
|
||||
listingStandard.Gap(8f);
|
||||
|
||||
// Если endpoint изменился, пересоздаем API сервис
|
||||
if (oldEndpoint != settings.apiEndpoint)
|
||||
{
|
||||
try
|
||||
{
|
||||
serviceContainer.RecreateApiService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"[AI Images] Failed to recreate API service: {ex.Message}");
|
||||
Messages.Message(
|
||||
"Failed to update API endpoint. Check the log.",
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (listingStandard.ButtonText("AIImages.Settings.TestConnection".Translate()))
|
||||
{
|
||||
_ = TestApiConnection(settings.apiEndpoint);
|
||||
TestApiConnection(serviceContainer.ApiService, settings.apiEndpoint);
|
||||
}
|
||||
|
||||
if (listingStandard.ButtonText("AIImages.Settings.LoadFromApi".Translate()))
|
||||
{
|
||||
_ = LoadAllFromApi(settings);
|
||||
LoadAllFromApi(serviceContainer.ApiService, settings);
|
||||
}
|
||||
|
||||
DrawModelDropdown(listingStandard, settings);
|
||||
@@ -343,120 +368,112 @@ namespace AIImages
|
||||
settings.savePath = listingStandard.TextEntry(settings.savePath);
|
||||
}
|
||||
|
||||
private static async System.Threading.Tasks.Task TestApiConnection(string endpoint)
|
||||
private static void TestApiConnection(
|
||||
IStableDiffusionApiService apiService,
|
||||
string endpoint
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Message($"[AI Images] Testing connection to {endpoint}...");
|
||||
bool available = await AIImagesMod.ApiService.CheckApiAvailability(endpoint);
|
||||
_ = AsyncHelper.RunAsync(
|
||||
async () =>
|
||||
{
|
||||
Log.Message($"[AI Images] Testing connection to {endpoint}...");
|
||||
bool available = await 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);
|
||||
}
|
||||
if (available)
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.ConnectionSuccess".Translate(),
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.ConnectionFailed".Translate(),
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
}
|
||||
},
|
||||
"API Connection Test"
|
||||
);
|
||||
}
|
||||
|
||||
private static async System.Threading.Tasks.Task LoadAllFromApi(
|
||||
private static void LoadAllFromApi(
|
||||
IStableDiffusionApiService apiService,
|
||||
AIImagesModSettings settings
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Message("[AI Images] Loading models, samplers and schedulers from API...");
|
||||
|
||||
// Загружаем модели
|
||||
var models = await AIImagesMod.ApiService.GetAvailableModels(settings.apiEndpoint);
|
||||
settings.availableModels = models;
|
||||
|
||||
// Загружаем семплеры
|
||||
var samplers = await AIImagesMod.ApiService.GetAvailableSamplers(
|
||||
settings.apiEndpoint
|
||||
);
|
||||
settings.availableSamplers = samplers;
|
||||
|
||||
// Загружаем schedulers
|
||||
var schedulers = await AIImagesMod.ApiService.GetAvailableSchedulers(
|
||||
settings.apiEndpoint
|
||||
);
|
||||
settings.availableSchedulers = schedulers;
|
||||
|
||||
int totalCount = models.Count + samplers.Count + schedulers.Count;
|
||||
if (totalCount > 0)
|
||||
_ = AsyncHelper.RunAsync(
|
||||
async () =>
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.AllLoaded".Translate(
|
||||
models.Count,
|
||||
samplers.Count,
|
||||
schedulers.Count
|
||||
),
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
Log.Message("[AI Images] Loading models, samplers and schedulers from API...");
|
||||
|
||||
// Автовыбор модели
|
||||
if (
|
||||
(
|
||||
string.IsNullOrEmpty(settings.selectedModel)
|
||||
|| !models.Contains(settings.selectedModel)
|
||||
)
|
||||
&& models.Count > 0
|
||||
)
|
||||
{
|
||||
settings.selectedModel = models[0];
|
||||
}
|
||||
// Загружаем модели
|
||||
var models = await apiService.GetAvailableModels(settings.apiEndpoint);
|
||||
settings.availableModels = models;
|
||||
|
||||
// Автовыбор семплера
|
||||
if (
|
||||
(
|
||||
string.IsNullOrEmpty(settings.selectedSampler)
|
||||
|| !samplers.Contains(settings.selectedSampler)
|
||||
)
|
||||
&& samplers.Count > 0
|
||||
)
|
||||
{
|
||||
settings.selectedSampler = samplers[0];
|
||||
}
|
||||
// Загружаем семплеры
|
||||
var samplers = await apiService.GetAvailableSamplers(settings.apiEndpoint);
|
||||
settings.availableSamplers = samplers;
|
||||
|
||||
// Автовыбор scheduler
|
||||
if (
|
||||
(
|
||||
string.IsNullOrEmpty(settings.selectedScheduler)
|
||||
|| !schedulers.Contains(settings.selectedScheduler)
|
||||
)
|
||||
&& schedulers.Count > 0
|
||||
)
|
||||
// Загружаем schedulers
|
||||
var schedulers = await apiService.GetAvailableSchedulers(settings.apiEndpoint);
|
||||
settings.availableSchedulers = schedulers;
|
||||
|
||||
int totalCount = models.Count + samplers.Count + schedulers.Count;
|
||||
if (totalCount > 0)
|
||||
{
|
||||
settings.selectedScheduler = schedulers[0];
|
||||
ShowSuccessMessage(models.Count, samplers.Count, schedulers.Count);
|
||||
AutoSelectDefaults(settings, models, samplers, schedulers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.NothingLoaded".Translate(),
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.NothingLoaded".Translate(),
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
}
|
||||
},
|
||||
"Load API Data"
|
||||
);
|
||||
}
|
||||
|
||||
private static void ShowSuccessMessage(int modelCount, int samplerCount, int schedulerCount)
|
||||
{
|
||||
Messages.Message(
|
||||
"AIImages.Settings.AllLoaded".Translate(modelCount, samplerCount, schedulerCount),
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
}
|
||||
|
||||
private static void AutoSelectDefaults(
|
||||
AIImagesModSettings settings,
|
||||
List<string> models,
|
||||
List<string> samplers,
|
||||
List<string> schedulers
|
||||
)
|
||||
{
|
||||
AutoSelectIfNeeded(ref settings.selectedModel, models, settings.selectedModel);
|
||||
AutoSelectIfNeeded(ref settings.selectedSampler, samplers, settings.selectedSampler);
|
||||
AutoSelectIfNeeded(
|
||||
ref settings.selectedScheduler,
|
||||
schedulers,
|
||||
settings.selectedScheduler
|
||||
);
|
||||
}
|
||||
|
||||
private static void AutoSelectIfNeeded(
|
||||
ref string selectedValue,
|
||||
List<string> availableValues,
|
||||
string currentValue
|
||||
)
|
||||
{
|
||||
bool needsSelection =
|
||||
string.IsNullOrEmpty(currentValue) || !availableValues.Contains(currentValue);
|
||||
|
||||
if (needsSelection && availableValues.Count > 0)
|
||||
{
|
||||
Messages.Message(
|
||||
$"Error loading from API: {ex.Message}",
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
selectedValue = availableValues[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user