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:
Binary file not shown.
@@ -45,10 +45,16 @@
|
|||||||
<AIImages.Settings.ApiEndpoint>API Endpoint</AIImages.Settings.ApiEndpoint>
|
<AIImages.Settings.ApiEndpoint>API Endpoint</AIImages.Settings.ApiEndpoint>
|
||||||
<AIImages.Settings.TestConnection>Test Connection</AIImages.Settings.TestConnection>
|
<AIImages.Settings.TestConnection>Test Connection</AIImages.Settings.TestConnection>
|
||||||
<AIImages.Settings.LoadModels>Load Available Models</AIImages.Settings.LoadModels>
|
<AIImages.Settings.LoadModels>Load Available Models</AIImages.Settings.LoadModels>
|
||||||
|
<AIImages.Settings.Model>Model</AIImages.Settings.Model>
|
||||||
|
<AIImages.Settings.NoModelSelected>No model selected</AIImages.Settings.NoModelSelected>
|
||||||
|
<AIImages.Settings.LoadModelsFirst>Load models first</AIImages.Settings.LoadModelsFirst>
|
||||||
|
<AIImages.Settings.LoadSamplersSchedulers>Load Samplers & Schedulers</AIImages.Settings.LoadSamplersSchedulers>
|
||||||
<AIImages.Settings.ConnectionSuccess>Successfully connected to API!</AIImages.Settings.ConnectionSuccess>
|
<AIImages.Settings.ConnectionSuccess>Successfully connected to API!</AIImages.Settings.ConnectionSuccess>
|
||||||
<AIImages.Settings.ConnectionFailed>Failed to connect to API. Check endpoint and ensure Stable Diffusion WebUI is running.</AIImages.Settings.ConnectionFailed>
|
<AIImages.Settings.ConnectionFailed>Failed to connect to API. Check endpoint and ensure Stable Diffusion WebUI is running.</AIImages.Settings.ConnectionFailed>
|
||||||
<AIImages.Settings.ModelsLoaded>Loaded {0} models from API</AIImages.Settings.ModelsLoaded>
|
<AIImages.Settings.ModelsLoaded>Loaded {0} models from API</AIImages.Settings.ModelsLoaded>
|
||||||
<AIImages.Settings.NoModelsFound>No models found. Check API connection.</AIImages.Settings.NoModelsFound>
|
<AIImages.Settings.NoModelsFound>No models found. Check API connection.</AIImages.Settings.NoModelsFound>
|
||||||
|
<AIImages.Settings.SamplersSchedulersLoaded>Loaded {0} samplers and {1} schedulers from API</AIImages.Settings.SamplersSchedulersLoaded>
|
||||||
|
<AIImages.Settings.NoSamplersSchedulersFound>No samplers or schedulers found. Check API connection.</AIImages.Settings.NoSamplersSchedulersFound>
|
||||||
<AIImages.Settings.GenerationSection>Generation Settings</AIImages.Settings.GenerationSection>
|
<AIImages.Settings.GenerationSection>Generation Settings</AIImages.Settings.GenerationSection>
|
||||||
<AIImages.Settings.GenerationSectionTooltip>Configure image generation parameters</AIImages.Settings.GenerationSectionTooltip>
|
<AIImages.Settings.GenerationSectionTooltip>Configure image generation parameters</AIImages.Settings.GenerationSectionTooltip>
|
||||||
<AIImages.Settings.ArtStyle>Art Style</AIImages.Settings.ArtStyle>
|
<AIImages.Settings.ArtStyle>Art Style</AIImages.Settings.ArtStyle>
|
||||||
@@ -58,6 +64,7 @@
|
|||||||
<AIImages.Settings.Width>Width</AIImages.Settings.Width>
|
<AIImages.Settings.Width>Width</AIImages.Settings.Width>
|
||||||
<AIImages.Settings.Height>Height</AIImages.Settings.Height>
|
<AIImages.Settings.Height>Height</AIImages.Settings.Height>
|
||||||
<AIImages.Settings.Sampler>Sampler</AIImages.Settings.Sampler>
|
<AIImages.Settings.Sampler>Sampler</AIImages.Settings.Sampler>
|
||||||
|
<AIImages.Settings.Scheduler>Schedule Type</AIImages.Settings.Scheduler>
|
||||||
<AIImages.Settings.PromptsSection>Prompts</AIImages.Settings.PromptsSection>
|
<AIImages.Settings.PromptsSection>Prompts</AIImages.Settings.PromptsSection>
|
||||||
<AIImages.Settings.PromptsSectionTooltip>Base prompts that will be added to all generations</AIImages.Settings.PromptsSectionTooltip>
|
<AIImages.Settings.PromptsSectionTooltip>Base prompts that will be added to all generations</AIImages.Settings.PromptsSectionTooltip>
|
||||||
<AIImages.Settings.BasePositivePrompt>Base Positive Prompt</AIImages.Settings.BasePositivePrompt>
|
<AIImages.Settings.BasePositivePrompt>Base Positive Prompt</AIImages.Settings.BasePositivePrompt>
|
||||||
|
|||||||
@@ -45,10 +45,16 @@
|
|||||||
<AIImages.Settings.ApiEndpoint>Адрес API</AIImages.Settings.ApiEndpoint>
|
<AIImages.Settings.ApiEndpoint>Адрес API</AIImages.Settings.ApiEndpoint>
|
||||||
<AIImages.Settings.TestConnection>Проверить соединение</AIImages.Settings.TestConnection>
|
<AIImages.Settings.TestConnection>Проверить соединение</AIImages.Settings.TestConnection>
|
||||||
<AIImages.Settings.LoadModels>Загрузить доступные модели</AIImages.Settings.LoadModels>
|
<AIImages.Settings.LoadModels>Загрузить доступные модели</AIImages.Settings.LoadModels>
|
||||||
|
<AIImages.Settings.Model>Модель</AIImages.Settings.Model>
|
||||||
|
<AIImages.Settings.NoModelSelected>Модель не выбрана</AIImages.Settings.NoModelSelected>
|
||||||
|
<AIImages.Settings.LoadModelsFirst>Сначала загрузите модели</AIImages.Settings.LoadModelsFirst>
|
||||||
|
<AIImages.Settings.LoadSamplersSchedulers>Загрузить сэмплеры и планировщики</AIImages.Settings.LoadSamplersSchedulers>
|
||||||
<AIImages.Settings.ConnectionSuccess>Успешное подключение к API!</AIImages.Settings.ConnectionSuccess>
|
<AIImages.Settings.ConnectionSuccess>Успешное подключение к API!</AIImages.Settings.ConnectionSuccess>
|
||||||
<AIImages.Settings.ConnectionFailed>Не удалось подключиться к API. Проверьте адрес и убедитесь, что Stable Diffusion WebUI запущен.</AIImages.Settings.ConnectionFailed>
|
<AIImages.Settings.ConnectionFailed>Не удалось подключиться к API. Проверьте адрес и убедитесь, что Stable Diffusion WebUI запущен.</AIImages.Settings.ConnectionFailed>
|
||||||
<AIImages.Settings.ModelsLoaded>Загружено {0} моделей из API</AIImages.Settings.ModelsLoaded>
|
<AIImages.Settings.ModelsLoaded>Загружено {0} моделей из API</AIImages.Settings.ModelsLoaded>
|
||||||
<AIImages.Settings.NoModelsFound>Модели не найдены. Проверьте подключение к API.</AIImages.Settings.NoModelsFound>
|
<AIImages.Settings.NoModelsFound>Модели не найдены. Проверьте подключение к API.</AIImages.Settings.NoModelsFound>
|
||||||
|
<AIImages.Settings.SamplersSchedulersLoaded>Загружено {0} сэмплеров и {1} планировщиков из API</AIImages.Settings.SamplersSchedulersLoaded>
|
||||||
|
<AIImages.Settings.NoSamplersSchedulersFound>Сэмплеры и планировщики не найдены. Проверьте подключение к API.</AIImages.Settings.NoSamplersSchedulersFound>
|
||||||
<AIImages.Settings.GenerationSection>Настройки генерации</AIImages.Settings.GenerationSection>
|
<AIImages.Settings.GenerationSection>Настройки генерации</AIImages.Settings.GenerationSection>
|
||||||
<AIImages.Settings.GenerationSectionTooltip>Настройка параметров генерации изображений</AIImages.Settings.GenerationSectionTooltip>
|
<AIImages.Settings.GenerationSectionTooltip>Настройка параметров генерации изображений</AIImages.Settings.GenerationSectionTooltip>
|
||||||
<AIImages.Settings.ArtStyle>Художественный стиль</AIImages.Settings.ArtStyle>
|
<AIImages.Settings.ArtStyle>Художественный стиль</AIImages.Settings.ArtStyle>
|
||||||
@@ -58,6 +64,7 @@
|
|||||||
<AIImages.Settings.Width>Ширина</AIImages.Settings.Width>
|
<AIImages.Settings.Width>Ширина</AIImages.Settings.Width>
|
||||||
<AIImages.Settings.Height>Высота</AIImages.Settings.Height>
|
<AIImages.Settings.Height>Высота</AIImages.Settings.Height>
|
||||||
<AIImages.Settings.Sampler>Сэмплер</AIImages.Settings.Sampler>
|
<AIImages.Settings.Sampler>Сэмплер</AIImages.Settings.Sampler>
|
||||||
|
<AIImages.Settings.Scheduler>Тип планировщика</AIImages.Settings.Scheduler>
|
||||||
<AIImages.Settings.PromptsSection>Промпты</AIImages.Settings.PromptsSection>
|
<AIImages.Settings.PromptsSection>Промпты</AIImages.Settings.PromptsSection>
|
||||||
<AIImages.Settings.PromptsSectionTooltip>Базовые промпты, которые будут добавлены ко всем генерациям</AIImages.Settings.PromptsSectionTooltip>
|
<AIImages.Settings.PromptsSectionTooltip>Базовые промпты, которые будут добавлены ко всем генерациям</AIImages.Settings.PromptsSectionTooltip>
|
||||||
<AIImages.Settings.BasePositivePrompt>Базовый позитивный промпт</AIImages.Settings.BasePositivePrompt>
|
<AIImages.Settings.BasePositivePrompt>Базовый позитивный промпт</AIImages.Settings.BasePositivePrompt>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace AIImages.Models
|
|||||||
public int Width { get; set; }
|
public int Width { get; set; }
|
||||||
public int Height { get; set; }
|
public int Height { get; set; }
|
||||||
public string Sampler { get; set; }
|
public string Sampler { get; set; }
|
||||||
|
public string Scheduler { get; set; }
|
||||||
public int Seed { get; set; }
|
public int Seed { get; set; }
|
||||||
public string Model { get; set; }
|
public string Model { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace AIImages.Models
|
|||||||
public int Width { get; set; }
|
public int Width { get; set; }
|
||||||
public int Height { get; set; }
|
public int Height { get; set; }
|
||||||
public string Sampler { get; set; }
|
public string Sampler { get; set; }
|
||||||
|
public string Scheduler { get; set; }
|
||||||
public int Seed { get; set; }
|
public int Seed { get; set; }
|
||||||
public string Model { get; set; }
|
public string Model { get; set; }
|
||||||
public ArtStyle ArtStyle { get; set; }
|
public ArtStyle ArtStyle { get; set; }
|
||||||
@@ -24,6 +25,7 @@ namespace AIImages.Models
|
|||||||
Width = 512;
|
Width = 512;
|
||||||
Height = 768;
|
Height = 768;
|
||||||
Sampler = "Euler a";
|
Sampler = "Euler a";
|
||||||
|
Scheduler = "Automatic";
|
||||||
Seed = -1; // Случайный seed
|
Seed = -1; // Случайный seed
|
||||||
ArtStyle = ArtStyle.Realistic;
|
ArtStyle = ArtStyle.Realistic;
|
||||||
PositivePrompt = "";
|
PositivePrompt = "";
|
||||||
|
|||||||
@@ -28,5 +28,10 @@ namespace AIImages.Services
|
|||||||
/// Получает список доступных сэмплеров
|
/// Получает список доступных сэмплеров
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<List<string>> GetAvailableSamplers(string apiEndpoint);
|
Task<List<string>> GetAvailableSamplers(string apiEndpoint);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает список доступных schedulers
|
||||||
|
/// </summary>
|
||||||
|
Task<List<string>> GetAvailableSchedulers(string apiEndpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ namespace AIImages.Services
|
|||||||
width = request.Width,
|
width = request.Width,
|
||||||
height = request.Height,
|
height = request.Height,
|
||||||
sampler_name = request.Sampler,
|
sampler_name = request.Sampler,
|
||||||
|
scheduler = request.Scheduler,
|
||||||
seed = request.Seed,
|
seed = request.Seed,
|
||||||
save_images = false,
|
save_images = false,
|
||||||
send_images = true,
|
send_images = true,
|
||||||
@@ -186,6 +187,38 @@ namespace AIImages.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<string>> GetAvailableSchedulers(string apiEndpoint)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string endpoint = $"{apiEndpoint}/sdapi/v1/schedulers";
|
||||||
|
HttpResponseMessage response = await httpClient.GetAsync(endpoint);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
return GetDefaultSchedulers();
|
||||||
|
|
||||||
|
string jsonResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var schedulers = JsonConvert.DeserializeObject<List<SdScheduler>>(jsonResponse);
|
||||||
|
|
||||||
|
var schedulerNames = new List<string>();
|
||||||
|
if (schedulers != null)
|
||||||
|
{
|
||||||
|
foreach (var scheduler in schedulers)
|
||||||
|
{
|
||||||
|
schedulerNames.Add(scheduler.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Message($"[AI Images] Found {schedulerNames.Count} schedulers");
|
||||||
|
return schedulerNames;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning($"[AI Images] Failed to load schedulers: {ex.Message}");
|
||||||
|
return GetDefaultSchedulers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<string> GetDefaultSamplers()
|
private List<string> GetDefaultSamplers()
|
||||||
{
|
{
|
||||||
return new List<string>
|
return new List<string>
|
||||||
@@ -212,6 +245,19 @@ namespace AIImages.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<string> GetDefaultSchedulers()
|
||||||
|
{
|
||||||
|
return new List<string>
|
||||||
|
{
|
||||||
|
"Automatic",
|
||||||
|
"Uniform",
|
||||||
|
"Karras",
|
||||||
|
"Exponential",
|
||||||
|
"Polyexponential",
|
||||||
|
"SGM Uniform",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Вспомогательные классы для десериализации JSON ответов
|
// Вспомогательные классы для десериализации JSON ответов
|
||||||
#pragma warning disable S3459, S1144 // Properties set by JSON deserializer
|
#pragma warning disable S3459, S1144 // Properties set by JSON deserializer
|
||||||
private sealed class Txt2ImgResponse
|
private sealed class Txt2ImgResponse
|
||||||
@@ -229,6 +275,11 @@ namespace AIImages.Services
|
|||||||
{
|
{
|
||||||
public string name { get; set; }
|
public string name { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class SdScheduler
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
}
|
||||||
#pragma warning restore S3459, S1144
|
#pragma warning restore S3459, S1144
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using AIImages.Models;
|
using AIImages.Models;
|
||||||
using Verse;
|
using Verse;
|
||||||
|
|
||||||
@@ -13,6 +14,17 @@ namespace AIImages.Settings
|
|||||||
public string apiEndpoint = "http://127.0.0.1:7860";
|
public string apiEndpoint = "http://127.0.0.1:7860";
|
||||||
public string selectedModel = "";
|
public string selectedModel = "";
|
||||||
public string selectedSampler = "Euler a";
|
public string selectedSampler = "Euler a";
|
||||||
|
public string selectedScheduler = "Automatic";
|
||||||
|
|
||||||
|
// Кэшированные списки из API (не сохраняются)
|
||||||
|
[Unsaved]
|
||||||
|
public List<string> availableModels = new List<string>();
|
||||||
|
|
||||||
|
[Unsaved]
|
||||||
|
public List<string> availableSamplers = new List<string>();
|
||||||
|
|
||||||
|
[Unsaved]
|
||||||
|
public List<string> availableSchedulers = new List<string>();
|
||||||
|
|
||||||
// Настройки генерации
|
// Настройки генерации
|
||||||
public int steps = 30;
|
public int steps = 30;
|
||||||
@@ -42,6 +54,7 @@ namespace AIImages.Settings
|
|||||||
Scribe_Values.Look(ref apiEndpoint, "apiEndpoint", "http://127.0.0.1:7860");
|
Scribe_Values.Look(ref apiEndpoint, "apiEndpoint", "http://127.0.0.1:7860");
|
||||||
Scribe_Values.Look(ref selectedModel, "selectedModel", "");
|
Scribe_Values.Look(ref selectedModel, "selectedModel", "");
|
||||||
Scribe_Values.Look(ref selectedSampler, "selectedSampler", "Euler a");
|
Scribe_Values.Look(ref selectedSampler, "selectedSampler", "Euler a");
|
||||||
|
Scribe_Values.Look(ref selectedScheduler, "selectedScheduler", "Automatic");
|
||||||
|
|
||||||
Scribe_Values.Look(ref steps, "steps", 30);
|
Scribe_Values.Look(ref steps, "steps", 30);
|
||||||
Scribe_Values.Look(ref cfgScale, "cfgScale", 7.5f);
|
Scribe_Values.Look(ref cfgScale, "cfgScale", 7.5f);
|
||||||
@@ -79,6 +92,7 @@ namespace AIImages.Settings
|
|||||||
Width = width,
|
Width = width,
|
||||||
Height = height,
|
Height = height,
|
||||||
Sampler = selectedSampler,
|
Sampler = selectedSampler,
|
||||||
|
Scheduler = selectedScheduler,
|
||||||
Seed = seed,
|
Seed = seed,
|
||||||
Model = selectedModel,
|
Model = selectedModel,
|
||||||
ArtStyle = artStyle,
|
ArtStyle = artStyle,
|
||||||
|
|||||||
@@ -21,13 +21,7 @@ namespace AIImages
|
|||||||
|
|
||||||
public static void DoSettingsWindowContents(Rect inRect, AIImagesModSettings settings)
|
public static void DoSettingsWindowContents(Rect inRect, AIImagesModSettings settings)
|
||||||
{
|
{
|
||||||
// Инициализируем буферы при первом вызове
|
InitializeBuffers(settings);
|
||||||
if (string.IsNullOrEmpty(stepsBuffer))
|
|
||||||
{
|
|
||||||
stepsBuffer = settings.steps.ToString();
|
|
||||||
widthBuffer = settings.width.ToString();
|
|
||||||
heightBuffer = settings.height.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Listing_Standard listingStandard = new Listing_Standard();
|
Listing_Standard listingStandard = new Listing_Standard();
|
||||||
Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1200f);
|
Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1200f);
|
||||||
@@ -35,7 +29,31 @@ namespace AIImages
|
|||||||
Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect);
|
Widgets.BeginScrollView(inRect, ref scrollPosition, viewRect);
|
||||||
listingStandard.Begin(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(
|
listingStandard.Label(
|
||||||
"AIImages.Settings.ApiSection".Translate(),
|
"AIImages.Settings.ApiSection".Translate(),
|
||||||
-1f,
|
-1f,
|
||||||
@@ -47,21 +65,66 @@ namespace AIImages
|
|||||||
settings.apiEndpoint = listingStandard.TextEntry(settings.apiEndpoint);
|
settings.apiEndpoint = listingStandard.TextEntry(settings.apiEndpoint);
|
||||||
listingStandard.Gap(8f);
|
listingStandard.Gap(8f);
|
||||||
|
|
||||||
// Кнопка проверки подключения
|
|
||||||
if (listingStandard.ButtonText("AIImages.Settings.TestConnection".Translate()))
|
if (listingStandard.ButtonText("AIImages.Settings.TestConnection".Translate()))
|
||||||
{
|
{
|
||||||
_ = TestApiConnection(settings.apiEndpoint);
|
_ = TestApiConnection(settings.apiEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Кнопка загрузки моделей
|
|
||||||
if (listingStandard.ButtonText("AIImages.Settings.LoadModels".Translate()))
|
if (listingStandard.ButtonText("AIImages.Settings.LoadModels".Translate()))
|
||||||
{
|
{
|
||||||
_ = LoadModelsFromApi(settings);
|
_ = 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(
|
listingStandard.Label(
|
||||||
"AIImages.Settings.GenerationSection".Translate(),
|
"AIImages.Settings.GenerationSection".Translate(),
|
||||||
-1f,
|
-1f,
|
||||||
@@ -69,7 +132,28 @@ namespace AIImages
|
|||||||
);
|
);
|
||||||
listingStandard.GapLine();
|
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 (
|
if (
|
||||||
listingStandard.ButtonTextLabeled(
|
listingStandard.ButtonTextLabeled(
|
||||||
"AIImages.Settings.ArtStyle".Translate(),
|
"AIImages.Settings.ArtStyle".Translate(),
|
||||||
@@ -87,22 +171,13 @@ namespace AIImages
|
|||||||
}
|
}
|
||||||
Find.WindowStack.Add(new FloatMenu(styleOptions));
|
Find.WindowStack.Add(new FloatMenu(styleOptions));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listingStandard.Gap(8f);
|
private static void DrawSizeSettings(
|
||||||
|
Listing_Standard listingStandard,
|
||||||
// Steps
|
AIImagesModSettings settings
|
||||||
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() + ":");
|
listingStandard.Label("AIImages.Settings.Width".Translate() + ":");
|
||||||
widthBuffer = listingStandard.TextEntry(widthBuffer);
|
widthBuffer = listingStandard.TextEntry(widthBuffer);
|
||||||
if (int.TryParse(widthBuffer, out int width))
|
if (int.TryParse(widthBuffer, out int width))
|
||||||
@@ -110,7 +185,6 @@ namespace AIImages
|
|||||||
settings.width = Mathf.Clamp(width, 64, 2048);
|
settings.width = Mathf.Clamp(width, 64, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Height
|
|
||||||
listingStandard.Label("AIImages.Settings.Height".Translate() + ":");
|
listingStandard.Label("AIImages.Settings.Height".Translate() + ":");
|
||||||
heightBuffer = listingStandard.TextEntry(heightBuffer);
|
heightBuffer = listingStandard.TextEntry(heightBuffer);
|
||||||
if (int.TryParse(heightBuffer, out int height))
|
if (int.TryParse(heightBuffer, out int height))
|
||||||
@@ -118,41 +192,119 @@ namespace AIImages
|
|||||||
settings.height = Mathf.Clamp(height, 64, 2048);
|
settings.height = Mathf.Clamp(height, 64, 2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common size presets
|
DrawSizePresets(listingStandard, settings);
|
||||||
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"))
|
|
||||||
{
|
private static void DrawSizePresets(
|
||||||
settings.width = 512;
|
Listing_Standard listingStandard,
|
||||||
settings.height = 768;
|
AIImagesModSettings settings
|
||||||
widthBuffer = "512";
|
|
||||||
heightBuffer = "768";
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
Widgets.ButtonText(new Rect(presetRect.x + 170f, presetRect.y, 80f, 30f), "768x768")
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
settings.width = 768;
|
listingStandard.Gap(4f);
|
||||||
settings.height = 768;
|
Rect presetRect1 = listingStandard.GetRect(30f);
|
||||||
widthBuffer = "768";
|
DrawPresetButton(presetRect1, 0f, "512x512", 512, 512, settings);
|
||||||
heightBuffer = "768";
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
listingStandard.Gap(12f);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sampler
|
private static void DrawSamplerSchedulerSettings(
|
||||||
listingStandard.Label("AIImages.Settings.Sampler".Translate() + ":");
|
Listing_Standard listingStandard,
|
||||||
settings.selectedSampler = listingStandard.TextEntry(settings.selectedSampler);
|
AIImagesModSettings settings
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DrawSamplerDropdown(listingStandard, settings);
|
||||||
|
DrawSchedulerDropdown(listingStandard, settings);
|
||||||
listingStandard.Gap(12f);
|
listingStandard.Gap(12f);
|
||||||
|
}
|
||||||
|
|
||||||
// === Prompts ===
|
private static void DrawSamplerDropdown(
|
||||||
|
Listing_Standard listingStandard,
|
||||||
|
AIImagesModSettings settings
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
listingStandard.ButtonTextLabeled(
|
||||||
|
"AIImages.Settings.Sampler".Translate(),
|
||||||
|
settings.selectedSampler
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
|
||||||
|
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(
|
listingStandard.Label(
|
||||||
"AIImages.Settings.PromptsSection".Translate(),
|
"AIImages.Settings.PromptsSection".Translate(),
|
||||||
-1f,
|
-1f,
|
||||||
@@ -167,8 +319,13 @@ namespace AIImages
|
|||||||
listingStandard.Label("AIImages.Settings.BaseNegativePrompt".Translate() + ":");
|
listingStandard.Label("AIImages.Settings.BaseNegativePrompt".Translate() + ":");
|
||||||
settings.baseNegativePrompt = listingStandard.TextEntry(settings.baseNegativePrompt, 3);
|
settings.baseNegativePrompt = listingStandard.TextEntry(settings.baseNegativePrompt, 3);
|
||||||
listingStandard.Gap(12f);
|
listingStandard.Gap(12f);
|
||||||
|
}
|
||||||
|
|
||||||
// === Options ===
|
private static void DrawOptionsSettings(
|
||||||
|
Listing_Standard listingStandard,
|
||||||
|
AIImagesModSettings settings
|
||||||
|
)
|
||||||
|
{
|
||||||
listingStandard.Label("AIImages.Settings.OptionsSection".Translate());
|
listingStandard.Label("AIImages.Settings.OptionsSection".Translate());
|
||||||
listingStandard.GapLine();
|
listingStandard.GapLine();
|
||||||
|
|
||||||
@@ -187,12 +344,8 @@ namespace AIImages
|
|||||||
|
|
||||||
listingStandard.Gap(12f);
|
listingStandard.Gap(12f);
|
||||||
|
|
||||||
// Save path
|
|
||||||
listingStandard.Label("AIImages.Settings.SavePath".Translate() + ":");
|
listingStandard.Label("AIImages.Settings.SavePath".Translate() + ":");
|
||||||
settings.savePath = listingStandard.TextEntry(settings.savePath);
|
settings.savePath = listingStandard.TextEntry(settings.savePath);
|
||||||
|
|
||||||
listingStandard.End();
|
|
||||||
Widgets.EndScrollView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async System.Threading.Tasks.Task TestApiConnection(string endpoint)
|
private static async System.Threading.Tasks.Task TestApiConnection(string endpoint)
|
||||||
@@ -231,6 +384,7 @@ namespace AIImages
|
|||||||
{
|
{
|
||||||
Log.Message("[AI Images] Loading models from API...");
|
Log.Message("[AI Images] Loading models from API...");
|
||||||
var models = await AIImagesMod.ApiService.GetAvailableModels(settings.apiEndpoint);
|
var models = await AIImagesMod.ApiService.GetAvailableModels(settings.apiEndpoint);
|
||||||
|
settings.availableModels = models;
|
||||||
|
|
||||||
if (models.Count > 0)
|
if (models.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -239,8 +393,13 @@ namespace AIImages
|
|||||||
MessageTypeDefOf.PositiveEvent
|
MessageTypeDefOf.PositiveEvent
|
||||||
);
|
);
|
||||||
|
|
||||||
// Если модель не выбрана, выбираем первую
|
if (
|
||||||
if (string.IsNullOrEmpty(settings.selectedModel) && models.Count > 0)
|
(
|
||||||
|
string.IsNullOrEmpty(settings.selectedModel)
|
||||||
|
|| !models.Contains(settings.selectedModel)
|
||||||
|
)
|
||||||
|
&& models.Count > 0
|
||||||
|
)
|
||||||
{
|
{
|
||||||
settings.selectedModel = models[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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ namespace AIImages
|
|||||||
Width = generationSettings.Width,
|
Width = generationSettings.Width,
|
||||||
Height = generationSettings.Height,
|
Height = generationSettings.Height,
|
||||||
Sampler = generationSettings.Sampler,
|
Sampler = generationSettings.Sampler,
|
||||||
|
Scheduler = generationSettings.Scheduler,
|
||||||
Seed = generationSettings.Seed,
|
Seed = generationSettings.Seed,
|
||||||
Model = AIImagesMod.Settings.apiEndpoint,
|
Model = AIImagesMod.Settings.apiEndpoint,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user