Enhance AIImages mod by adding scheduler support and updating UI for improved model and sampler selection. Localized strings in English and Russian have been updated for clarity. Update AIImages.dll to reflect changes in functionality.
This commit is contained in:
@@ -21,13 +21,7 @@ namespace AIImages
|
||||
|
||||
public static void DoSettingsWindowContents(Rect inRect, AIImagesModSettings settings)
|
||||
{
|
||||
// Инициализируем буферы при первом вызове
|
||||
if (string.IsNullOrEmpty(stepsBuffer))
|
||||
{
|
||||
stepsBuffer = settings.steps.ToString();
|
||||
widthBuffer = settings.width.ToString();
|
||||
heightBuffer = settings.height.ToString();
|
||||
}
|
||||
InitializeBuffers(settings);
|
||||
|
||||
Listing_Standard listingStandard = new Listing_Standard();
|
||||
Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1200f);
|
||||
@@ -35,7 +29,31 @@ namespace AIImages
|
||||
Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect);
|
||||
listingStandard.Begin(viewRect);
|
||||
|
||||
// === API Settings ===
|
||||
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,
|
||||
@@ -47,21 +65,66 @@ namespace AIImages
|
||||
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);
|
||||
DrawModelDropdown(listingStandard, settings);
|
||||
|
||||
// === Generation 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<FloatMenuOption> modelOptions = new List<FloatMenuOption>();
|
||||
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,
|
||||
@@ -69,7 +132,28 @@ namespace AIImages
|
||||
);
|
||||
listingStandard.GapLine();
|
||||
|
||||
// Art Style
|
||||
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(),
|
||||
@@ -87,22 +171,13 @@ namespace AIImages
|
||||
}
|
||||
Find.WindowStack.Add(new FloatMenu(styleOptions));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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))
|
||||
@@ -110,7 +185,6 @@ namespace AIImages
|
||||
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))
|
||||
@@ -118,41 +192,119 @@ namespace AIImages
|
||||
settings.height = Mathf.Clamp(height, 64, 2048);
|
||||
}
|
||||
|
||||
// Common size presets
|
||||
DrawSizePresets(listingStandard, settings);
|
||||
}
|
||||
|
||||
private static void DrawSizePresets(
|
||||
Listing_Standard listingStandard,
|
||||
AIImagesModSettings settings
|
||||
)
|
||||
{
|
||||
listingStandard.Gap(4f);
|
||||
Rect presetRect = listingStandard.GetRect(30f);
|
||||
if (Widgets.ButtonText(new Rect(presetRect.x, presetRect.y, 80f, 30f), "512x512"))
|
||||
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 = 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";
|
||||
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 (
|
||||
Widgets.ButtonText(new Rect(presetRect.x + 170f, presetRect.y, 80f, 30f), "768x768")
|
||||
listingStandard.ButtonTextLabeled(
|
||||
"AIImages.Settings.Sampler".Translate(),
|
||||
settings.selectedSampler
|
||||
)
|
||||
)
|
||||
{
|
||||
settings.width = 768;
|
||||
settings.height = 768;
|
||||
widthBuffer = "768";
|
||||
heightBuffer = "768";
|
||||
List<FloatMenuOption> samplerOptions = new List<FloatMenuOption>();
|
||||
var availableSamplers = settings.availableSamplers.Any()
|
||||
? settings.availableSamplers
|
||||
: new List<string> { settings.selectedSampler };
|
||||
|
||||
foreach (string sampler in availableSamplers)
|
||||
{
|
||||
string localSampler = sampler;
|
||||
samplerOptions.Add(
|
||||
new FloatMenuOption(sampler, () => settings.selectedSampler = localSampler)
|
||||
);
|
||||
}
|
||||
Find.WindowStack.Add(new FloatMenu(samplerOptions));
|
||||
}
|
||||
}
|
||||
|
||||
listingStandard.Gap(12f);
|
||||
private static void DrawSchedulerDropdown(
|
||||
Listing_Standard listingStandard,
|
||||
AIImagesModSettings settings
|
||||
)
|
||||
{
|
||||
if (
|
||||
listingStandard.ButtonTextLabeled(
|
||||
"AIImages.Settings.Scheduler".Translate(),
|
||||
settings.selectedScheduler
|
||||
)
|
||||
)
|
||||
{
|
||||
List<FloatMenuOption> schedulerOptions = new List<FloatMenuOption>();
|
||||
var availableSchedulers = settings.availableSchedulers.Any()
|
||||
? settings.availableSchedulers
|
||||
: new List<string> { settings.selectedScheduler };
|
||||
|
||||
// Sampler
|
||||
listingStandard.Label("AIImages.Settings.Sampler".Translate() + ":");
|
||||
settings.selectedSampler = listingStandard.TextEntry(settings.selectedSampler);
|
||||
listingStandard.Gap(12f);
|
||||
foreach (string scheduler in availableSchedulers)
|
||||
{
|
||||
string localScheduler = scheduler;
|
||||
schedulerOptions.Add(
|
||||
new FloatMenuOption(
|
||||
scheduler,
|
||||
() => settings.selectedScheduler = localScheduler
|
||||
)
|
||||
);
|
||||
}
|
||||
Find.WindowStack.Add(new FloatMenu(schedulerOptions));
|
||||
}
|
||||
}
|
||||
|
||||
// === Prompts ===
|
||||
private static void DrawPromptsSettings(
|
||||
Listing_Standard listingStandard,
|
||||
AIImagesModSettings settings
|
||||
)
|
||||
{
|
||||
listingStandard.Label(
|
||||
"AIImages.Settings.PromptsSection".Translate(),
|
||||
-1f,
|
||||
@@ -167,8 +319,13 @@ namespace AIImages
|
||||
listingStandard.Label("AIImages.Settings.BaseNegativePrompt".Translate() + ":");
|
||||
settings.baseNegativePrompt = listingStandard.TextEntry(settings.baseNegativePrompt, 3);
|
||||
listingStandard.Gap(12f);
|
||||
}
|
||||
|
||||
// === Options ===
|
||||
private static void DrawOptionsSettings(
|
||||
Listing_Standard listingStandard,
|
||||
AIImagesModSettings settings
|
||||
)
|
||||
{
|
||||
listingStandard.Label("AIImages.Settings.OptionsSection".Translate());
|
||||
listingStandard.GapLine();
|
||||
|
||||
@@ -187,12 +344,8 @@ namespace AIImages
|
||||
|
||||
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)
|
||||
@@ -231,6 +384,7 @@ namespace AIImages
|
||||
{
|
||||
Log.Message("[AI Images] Loading models from API...");
|
||||
var models = await AIImagesMod.ApiService.GetAvailableModels(settings.apiEndpoint);
|
||||
settings.availableModels = models;
|
||||
|
||||
if (models.Count > 0)
|
||||
{
|
||||
@@ -239,8 +393,13 @@ namespace AIImages
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
|
||||
// Если модель не выбрана, выбираем первую
|
||||
if (string.IsNullOrEmpty(settings.selectedModel) && models.Count > 0)
|
||||
if (
|
||||
(
|
||||
string.IsNullOrEmpty(settings.selectedModel)
|
||||
|| !models.Contains(settings.selectedModel)
|
||||
)
|
||||
&& models.Count > 0
|
||||
)
|
||||
{
|
||||
settings.selectedModel = models[0];
|
||||
}
|
||||
@@ -261,5 +420,73 @@ namespace AIImages
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user