Add log entry functionality to AIImages. Introduce event description handling in PawnAppearanceData and update prompt generation logic to include event context. Enhance Window_AIImage to display log entries and allow image generation from log events, improving user interaction and character representation.
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m45s
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m45s
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using AIImages.Helpers;
|
||||
using AIImages.Models;
|
||||
using AIImages.Patches;
|
||||
using AIImages.Services;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
@@ -72,11 +73,13 @@ namespace AIImages
|
||||
private Vector2 mainScrollPosition = Vector2.zero;
|
||||
private Vector2 promptScrollPosition = Vector2.zero;
|
||||
private Vector2 negativePromptScrollPosition = Vector2.zero;
|
||||
private Vector2 logEntriesScrollPosition = Vector2.zero;
|
||||
private float copiedMessageTime = 0f;
|
||||
|
||||
// Состояние сворачиваемых секций промптов
|
||||
private bool showPositivePrompt = false;
|
||||
private bool showNegativePrompt = false;
|
||||
private bool showLogEntries = true; // Развёрнута по умолчанию
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет данные персонажа
|
||||
@@ -190,6 +193,24 @@ namespace AIImages
|
||||
/// </summary>
|
||||
public Pawn CurrentPawn => pawn;
|
||||
|
||||
/// <summary>
|
||||
/// Генерирует изображение для пешки с описанием события
|
||||
/// </summary>
|
||||
public void GenerateImageForEvent(string eventDescription)
|
||||
{
|
||||
if (pawn == null || isGenerating)
|
||||
return;
|
||||
|
||||
// Устанавливаем описание события
|
||||
if (appearanceData != null)
|
||||
{
|
||||
appearanceData.EventDescription = eventDescription;
|
||||
}
|
||||
|
||||
// Запускаем генерацию
|
||||
StartGeneration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отладочный метод для проверки состояния всех пешек
|
||||
/// </summary>
|
||||
@@ -307,11 +328,24 @@ namespace AIImages
|
||||
|
||||
try
|
||||
{
|
||||
// Генерируем промпты
|
||||
string positivePrompt = promptGeneratorService.GeneratePositivePrompt(
|
||||
appearanceData,
|
||||
generationSettings
|
||||
);
|
||||
// Генерируем промпты - если есть описание события, используем его
|
||||
string positivePrompt;
|
||||
if (!string.IsNullOrEmpty(appearanceData?.EventDescription))
|
||||
{
|
||||
positivePrompt = promptGeneratorService.GeneratePositivePromptWithEvent(
|
||||
appearanceData,
|
||||
generationSettings,
|
||||
appearanceData.EventDescription
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
positivePrompt = promptGeneratorService.GeneratePositivePrompt(
|
||||
appearanceData,
|
||||
generationSettings
|
||||
);
|
||||
}
|
||||
|
||||
string negativePrompt = promptGeneratorService.GenerateNegativePrompt(
|
||||
generationSettings
|
||||
);
|
||||
@@ -575,7 +609,8 @@ namespace AIImages
|
||||
contentY = DrawTraits(parentRect, contentY, lineHeight);
|
||||
contentY = DrawGenes(parentRect, contentY, lineHeight);
|
||||
contentY = DrawHediffs(parentRect, contentY, lineHeight);
|
||||
DrawApparel(parentRect, contentY, lineHeight);
|
||||
contentY = DrawApparel(parentRect, contentY, lineHeight);
|
||||
contentY = DrawLogEntries(parentRect, contentY, lineHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -757,13 +792,13 @@ namespace AIImages
|
||||
/// <summary>
|
||||
/// Отрисовывает одежду персонажа
|
||||
/// </summary>
|
||||
private void DrawApparel(Rect parentRect, float startY, float lineHeight)
|
||||
private float DrawApparel(Rect parentRect, float startY, float lineHeight)
|
||||
{
|
||||
float contentY = startY;
|
||||
var apparel = pawn.apparel?.WornApparel;
|
||||
|
||||
if (apparel == null || !apparel.Any())
|
||||
return;
|
||||
return contentY;
|
||||
|
||||
contentY += 15f;
|
||||
Text.Font = GameFont.Small;
|
||||
@@ -785,6 +820,141 @@ namespace AIImages
|
||||
);
|
||||
contentY += apparelHeight;
|
||||
}
|
||||
|
||||
return contentY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовывает список записей лога пешки
|
||||
/// </summary>
|
||||
private float DrawLogEntries(Rect parentRect, float startY, float lineHeight)
|
||||
{
|
||||
float contentY = startY;
|
||||
|
||||
// Получаем записи лога
|
||||
var entries = PawnLogPatch.GetAllLogEntries(pawn).ToList();
|
||||
int entriesCount = entries?.Count ?? 0;
|
||||
|
||||
// Отладочная информация (временно)
|
||||
if (entriesCount == 0 && pawn != null)
|
||||
{
|
||||
// Пробуем проверить, есть ли вообще доступ к логам
|
||||
try
|
||||
{
|
||||
var logsProp = HarmonyLib.AccessTools.Property(typeof(Pawn), "logs");
|
||||
var hasLogs = logsProp != null;
|
||||
|
||||
// Выводим в консоль для отладки
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Log entries count: {entriesCount}, Has logs property: {hasLogs}, Pawn: {pawn?.Name}"
|
||||
);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
DebugLogger.Warning($"[AI Images] Debug error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
contentY += 15f;
|
||||
|
||||
// Заголовок секции - всегда показываем, даже если записей нет
|
||||
Text.Font = GameFont.Small;
|
||||
Rect headerRect = new Rect(
|
||||
parentRect.x + 5f,
|
||||
contentY,
|
||||
parentRect.width - 10f,
|
||||
lineHeight + 5f
|
||||
);
|
||||
|
||||
// Кнопка сворачивания/разворачивания
|
||||
string headerText = "AIImages.Log.Entries".Translate() + $" ({entriesCount})";
|
||||
if (Widgets.ButtonText(headerRect, headerText))
|
||||
{
|
||||
showLogEntries = !showLogEntries;
|
||||
}
|
||||
contentY += lineHeight + 10f;
|
||||
|
||||
// Разделитель
|
||||
Widgets.DrawLineHorizontal(parentRect.x, contentY, parentRect.width);
|
||||
contentY += 10f;
|
||||
|
||||
// Список записей (если развёрнуто и есть записи)
|
||||
if (showLogEntries && entries != null && entries.Any())
|
||||
{
|
||||
float entryWidth = parentRect.width - 25f;
|
||||
float scrollViewHeight = Mathf.Min(entries.Count * 30f + 20f, 300f);
|
||||
|
||||
Rect scrollViewRect = new Rect(
|
||||
parentRect.x + 5f,
|
||||
contentY,
|
||||
entryWidth + 15f,
|
||||
scrollViewHeight
|
||||
);
|
||||
|
||||
Rect viewRect = new Rect(0f, 0f, entryWidth, entries.Count * 30f);
|
||||
|
||||
Widgets.BeginScrollView(scrollViewRect, ref logEntriesScrollPosition, viewRect);
|
||||
|
||||
Text.Font = GameFont.Tiny;
|
||||
float entryY = 0f;
|
||||
const float entryHeight = 28f;
|
||||
const float buttonSize = 20f;
|
||||
|
||||
foreach (var entry in entries.Take(50)) // Ограничиваем для производительности
|
||||
{
|
||||
string entryText = entry.ToGameStringFromPOV(pawn);
|
||||
if (string.IsNullOrEmpty(entryText))
|
||||
continue;
|
||||
|
||||
// Обрезаем длинный текст
|
||||
string shortText =
|
||||
entryText.Length > 60 ? entryText.Substring(0, 57) + "..." : entryText;
|
||||
|
||||
Rect entryRect = new Rect(
|
||||
0f,
|
||||
entryY,
|
||||
entryWidth - buttonSize - 5f,
|
||||
entryHeight
|
||||
);
|
||||
Rect buttonRect = new Rect(
|
||||
entryWidth - buttonSize,
|
||||
entryY + (entryHeight - buttonSize) / 2f,
|
||||
buttonSize,
|
||||
buttonSize
|
||||
);
|
||||
|
||||
// Фон записи
|
||||
Widgets.DrawBoxSolid(entryRect, new Color(0.15f, 0.15f, 0.15f, 0.3f));
|
||||
|
||||
// Текст записи
|
||||
Widgets.Label(entryRect.ContractedBy(3f), shortText);
|
||||
|
||||
// Кнопка генерации изображения
|
||||
Texture2D iconTexture = ContentFinder<Texture2D>.Get(
|
||||
"UI/Commands/AIImage",
|
||||
true
|
||||
);
|
||||
if (iconTexture != null)
|
||||
{
|
||||
if (Widgets.ButtonImage(buttonRect, iconTexture))
|
||||
{
|
||||
GenerateImageForEvent(entryText);
|
||||
}
|
||||
|
||||
TooltipHandler.TipRegion(
|
||||
buttonRect,
|
||||
"AIImages.Log.GenerateImage".Translate()
|
||||
);
|
||||
}
|
||||
|
||||
entryY += entryHeight;
|
||||
}
|
||||
|
||||
Widgets.EndScrollView();
|
||||
contentY += scrollViewHeight + 10f;
|
||||
}
|
||||
|
||||
return contentY;
|
||||
}
|
||||
|
||||
private void DrawRightColumn(Rect rect)
|
||||
@@ -1311,7 +1481,12 @@ namespace AIImages
|
||||
galleryLabel += " " + "AIImages.Gallery.ImagesCount".Translate(imageCount);
|
||||
}
|
||||
|
||||
if (Widgets.ButtonText(new Rect(galleryButtonX, curY, galleryButtonWidth, 35f), galleryLabel))
|
||||
if (
|
||||
Widgets.ButtonText(
|
||||
new Rect(galleryButtonX, curY, galleryButtonWidth, 35f),
|
||||
galleryLabel
|
||||
)
|
||||
)
|
||||
{
|
||||
var galleryWindow = new Window_AIGallery(pawn);
|
||||
Find.WindowStack.Add(galleryWindow);
|
||||
|
||||
Reference in New Issue
Block a user