Implement progress monitoring for image generation in AIImages mod, enhancing user experience with real-time updates. Add localized strings for new features in English and Russian. Refactor UI components for better organization and clarity. Update AIImages.dll to reflect these changes.

This commit is contained in:
Leonid Pershin
2025-10-26 22:56:38 +03:00
parent b9d7ea0c04
commit d67ec8c0ac
11 changed files with 470 additions and 94 deletions

View File

@@ -63,7 +63,14 @@ namespace AIImages.Services
StringBuilder prompt = new StringBuilder();
// 1. Художественный стиль
// 1. Базовый пользовательский промпт (если указан) - идет первым
if (!string.IsNullOrEmpty(settings.PositivePrompt))
{
prompt.Append(settings.PositivePrompt);
prompt.Append(", ");
}
// 2. Художественный стиль
if (
ArtStylePrompts.TryGetValue(settings.ArtStyle, out string stylePrompt)
&& !string.IsNullOrEmpty(stylePrompt)
@@ -73,14 +80,14 @@ namespace AIImages.Services
prompt.Append(", ");
}
// 2. Тип кадра - автоматически добавляем "portrait" для генерации персонажей
// 3. Тип кадра - автоматически добавляем "portrait" для генерации персонажей
prompt.Append("portrait, head and shoulders of ");
// 3. Базовое описание (возраст и пол)
// 4. Базовое описание (возраст и пол)
prompt.Append(GetAgeAndGenderDescription(appearanceData));
prompt.Append(", ");
// 4. Тип тела
// 5. Тип тела
string bodyType = GetBodyTypeDescription(appearanceData.BodyType);
if (!string.IsNullOrEmpty(bodyType))
{
@@ -88,14 +95,14 @@ namespace AIImages.Services
prompt.Append(", ");
}
// 5. Цвет кожи
// 6. Цвет кожи
string skinTone = ColorDescriptionService.GetSkinToneDescription(
appearanceData.SkinColor
);
prompt.Append(skinTone);
prompt.Append(", ");
// 6. Волосы
// 7. Волосы
string hairDescription = GetHairDescription(appearanceData);
if (!string.IsNullOrEmpty(hairDescription))
{
@@ -103,7 +110,7 @@ namespace AIImages.Services
prompt.Append(", ");
}
// 7. Настроение и выражение на основе черт характера
// 8. Настроение и выражение на основе черт характера
string moodDescription = GetMoodFromTraits(appearanceData.Traits);
if (!string.IsNullOrEmpty(moodDescription))
{
@@ -111,7 +118,7 @@ namespace AIImages.Services
prompt.Append(", ");
}
// 8. Одежда
// 9. Одежда
string apparelDescription = GetApparelDescription(appearanceData.Apparel);
if (!string.IsNullOrEmpty(apparelDescription))
{
@@ -119,13 +126,6 @@ namespace AIImages.Services
prompt.Append(", ");
}
// 9. Базовый пользовательский промпт (если указан)
if (!string.IsNullOrEmpty(settings.PositivePrompt))
{
prompt.Append(settings.PositivePrompt);
prompt.Append(", ");
}
// 10. Качественные теги
prompt.Append(GetQualityTags(settings.ArtStyle));
@@ -136,7 +136,14 @@ namespace AIImages.Services
{
StringBuilder negativePrompt = new StringBuilder();
// Базовые негативные промпты
// 1. Пользовательский негативный промпт (если указан) - идет первым
if (!string.IsNullOrEmpty(settings.NegativePrompt))
{
negativePrompt.Append(settings.NegativePrompt);
negativePrompt.Append(", ");
}
// 2. Базовые негативные промпты
negativePrompt.Append(
"ugly, deformed, low quality, blurry, bad anatomy, worst quality, "
);
@@ -144,7 +151,7 @@ namespace AIImages.Services
"mutated, disfigured, bad proportions, extra limbs, missing limbs, "
);
// Специфичные для стиля негативы
// 3. Специфичные для стиля негативы
switch (settings.ArtStyle)
{
case ArtStyle.Realistic:
@@ -159,12 +166,6 @@ namespace AIImages.Services
break;
}
// Пользовательский негативный промпт
if (!string.IsNullOrEmpty(settings.NegativePrompt))
{
negativePrompt.Append(settings.NegativePrompt);
}
return negativePrompt.ToString().Trim().TrimEnd(',');
}

View File

@@ -18,6 +18,11 @@ namespace AIImages.Services
CancellationToken cancellationToken = default
);
/// <summary>
/// Получает прогресс текущей генерации
/// </summary>
Task<GenerationProgress> GetProgressAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Проверяет доступность API
/// </summary>

View File

@@ -137,6 +137,42 @@ namespace AIImages.Services
}
}
public async Task<GenerationProgress> GetProgressAsync(
CancellationToken cancellationToken = default
)
{
ThrowIfDisposed();
try
{
// Используем Progress сервис библиотеки
var progress = await _client.Progress.GetProgressAsync(cancellationToken);
// Маппируем на наш тип
return new GenerationProgress
{
Progress = progress.Progress,
CurrentStep = progress.State?.SamplingStep ?? 0,
TotalSteps = progress.State?.SamplingSteps ?? 0,
EtaRelative = progress.EtaRelative,
IsActive = progress.Progress > 0 && progress.Progress < 1.0,
};
}
catch (Exception ex)
{
Log.Warning($"[AI Images] Failed to get progress: {ex.Message}");
// Возвращаем пустой прогресс при ошибке
return new GenerationProgress
{
Progress = 0,
CurrentStep = 0,
TotalSteps = 0,
EtaRelative = 0,
IsActive = false,
};
}
}
public async Task<bool> CheckApiAvailability(
string apiEndpoint,
CancellationToken cancellationToken = default