Implement AI Images gallery feature in RimWorld mod, allowing users to view, delete, and manage generated images. Update UI components to include a gallery button and enhance image management functionality. Add localization strings for gallery features in English and Russian. Update AIImages.dll to reflect these changes.

This commit is contained in:
Leonid Pershin
2025-10-31 18:20:39 +03:00
parent 1b35cb6a44
commit a99fa16763
8 changed files with 799 additions and 36 deletions

View File

@@ -1,22 +1,84 @@
using System.Collections.Generic;
using System.Linq;
using AIImages.Helpers;
using Verse;
namespace AIImages.Components
{
/// <summary>
/// Компонент для хранения данных AI-сгенерированного портрета пешки
/// Компонент для хранения данных AI-сгенерированных портретов пешки
/// </summary>
public class PawnPortraitComp : ThingComp
{
/// <summary>
/// Путь к сохраненному портрету
/// Список путей к сохраненным портретам (галерея)
/// </summary>
public string PortraitPath { get; set; }
private List<string> portraitPaths = new List<string>();
/// <summary>
/// Есть ли сохраненный портрет
/// Есть ли сохраненные портреты
/// </summary>
public bool HasPortrait => !string.IsNullOrEmpty(PortraitPath);
public bool HasPortrait => portraitPaths != null && portraitPaths.Count > 0;
/// <summary>
/// Количество портретов в галерее
/// </summary>
public int PortraitCount => portraitPaths?.Count ?? 0;
/// <summary>
/// Получить все пути к портретам
/// </summary>
public List<string> GetAllPortraits() => portraitPaths?.ToList() ?? new List<string>();
/// <summary>
/// Получить последний портрет (для обратной совместимости)
/// </summary>
public string PortraitPath => HasPortrait ? portraitPaths.Last() : null;
/// <summary>
/// Добавить новый портрет в галерею
/// </summary>
public void AddPortrait(string path)
{
if (string.IsNullOrEmpty(path))
return;
if (portraitPaths == null)
portraitPaths = new List<string>();
portraitPaths.Add(path);
DebugLogger.Log($"[AI Images] Added portrait to gallery: {path}");
}
/// <summary>
/// Удалить портрет из галереи
/// </summary>
public bool RemovePortrait(string path)
{
if (portraitPaths == null || string.IsNullOrEmpty(path))
return false;
bool removed = portraitPaths.Remove(path);
if (removed)
{
DebugLogger.Log($"[AI Images] Removed portrait from gallery: {path}");
}
return removed;
}
/// <summary>
/// Очистить все портреты
/// </summary>
public void ClearPortraits()
{
if (portraitPaths != null)
{
int count = portraitPaths.Count;
portraitPaths.Clear();
DebugLogger.Log($"[AI Images] Cleared {count} portraits from gallery");
}
}
/// <summary>
/// Сохранение/загрузка данных
@@ -25,33 +87,30 @@ namespace AIImages.Components
{
base.PostExposeData();
string portraitPath = PortraitPath;
bool isSaving = Scribe.mode == LoadSaveMode.Saving;
bool isLoading = Scribe.mode == LoadSaveMode.LoadingVars;
DebugLogger.Log(
$"[AI Images] PostExposeData for {parent?.LabelShort} - Mode: {Scribe.mode}, Current path: '{PortraitPath}'"
$"[AI Images] PostExposeData for {parent?.LabelShort} - Mode: {Scribe.mode}, Portrait count: {PortraitCount}"
);
Scribe_Values.Look(ref portraitPath, "aiPortraitPath", null);
// Сохраняем список портретов
Scribe_Collections.Look(ref portraitPaths, "aiPortraitPaths", LookMode.Value);
if (isSaving)
// Обратная совместимость: если есть старый формат с одним портретом, добавляем его в список
if (isLoading && (portraitPaths == null || portraitPaths.Count == 0))
{
DebugLogger.Log(
$"[AI Images] Saving portrait path for {parent?.LabelShort}: '{portraitPath}'"
);
string oldPortraitPath = null;
Scribe_Values.Look(ref oldPortraitPath, "aiPortraitPath", null);
if (!string.IsNullOrEmpty(oldPortraitPath))
{
portraitPaths = new List<string> { oldPortraitPath };
DebugLogger.Log($"[AI Images] Migrated old single portrait to gallery: {oldPortraitPath}");
}
}
else if (isLoading)
{
DebugLogger.Log(
$"[AI Images] Loading portrait path for {parent?.LabelShort}: '{portraitPath}'"
);
}
PortraitPath = portraitPath;
DebugLogger.Log(
$"[AI Images] PostExposeData completed for {parent?.LabelShort} - Final path: '{PortraitPath}', HasPortrait: {HasPortrait}"
$"[AI Images] PostExposeData completed for {parent?.LabelShort} - Portrait count: {PortraitCount}, HasPortrait: {HasPortrait}"
);
}
}