Enhance AIImages mod by adding debug logging functionality to various components, improving troubleshooting capabilities. Introduce a new setting to enable or disable debug logs in the UI, with localized strings in English and Russian. Update StableDiffusionNet.Core dependency to version 1.1.5. Update AIImages.dll to reflect these changes.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -92,6 +92,8 @@
|
||||
<AIImages.Settings.SaveHistory>Save generation history</AIImages.Settings.SaveHistory>
|
||||
<AIImages.Settings.SaveImagesToServer>Save images to server</AIImages.Settings.SaveImagesToServer>
|
||||
<AIImages.Settings.SaveImagesToServerTooltip>When enabled, images will also be saved to the Stable Diffusion server's output folder (in addition to the local save folder)</AIImages.Settings.SaveImagesToServerTooltip>
|
||||
<AIImages.Settings.EnableDebugLogs>Enable debug logs</AIImages.Settings.EnableDebugLogs>
|
||||
<AIImages.Settings.EnableDebugLogsTooltip>When enabled, detailed debug information will be logged to help troubleshoot issues</AIImages.Settings.EnableDebugLogsTooltip>
|
||||
<AIImages.Settings.SavePath>Save Path</AIImages.Settings.SavePath>
|
||||
<AIImages.Settings.ClearAllImages>Clear All Generated Images</AIImages.Settings.ClearAllImages>
|
||||
<AIImages.Settings.ClearAllImagesConfirm>Are you sure you want to delete all generated portrait images? This action cannot be undone.</AIImages.Settings.ClearAllImagesConfirm>
|
||||
|
||||
@@ -92,6 +92,8 @@
|
||||
<AIImages.Settings.SaveHistory>Сохранять историю генераций</AIImages.Settings.SaveHistory>
|
||||
<AIImages.Settings.SaveImagesToServer>Сохранять изображения на сервере</AIImages.Settings.SaveImagesToServer>
|
||||
<AIImages.Settings.SaveImagesToServerTooltip>Если включено, изображения также будут сохранены в папке вывода сервера Stable Diffusion (помимо локальной папки сохранения)</AIImages.Settings.SaveImagesToServerTooltip>
|
||||
<AIImages.Settings.EnableDebugLogs>Включить отладочные логи</AIImages.Settings.EnableDebugLogs>
|
||||
<AIImages.Settings.EnableDebugLogsTooltip>При включении будет выводиться подробная отладочная информация для помощи в решении проблем</AIImages.Settings.EnableDebugLogsTooltip>
|
||||
<AIImages.Settings.SavePath>Путь для сохранения</AIImages.Settings.SavePath>
|
||||
<AIImages.Settings.ClearAllImages>Очистить все сгенерированные изображения</AIImages.Settings.ClearAllImages>
|
||||
<AIImages.Settings.ClearAllImagesConfirm>Вы уверены, что хотите удалить все сгенерированные портреты? Это действие нельзя отменить.</AIImages.Settings.ClearAllImagesConfirm>
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4566" />
|
||||
<PackageReference Include="Lib.Harmony" Version="2.4.1" />
|
||||
<PackageReference Include="StableDiffusionNet.Core" Version="1.1.2" />
|
||||
<PackageReference Include="StableDiffusionNet.Core" Version="1.1.5" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using AIImages.Helpers;
|
||||
using Verse;
|
||||
|
||||
namespace AIImages.Components
|
||||
@@ -23,9 +24,35 @@ namespace AIImages.Components
|
||||
public override void PostExposeData()
|
||||
{
|
||||
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}'"
|
||||
);
|
||||
|
||||
Scribe_Values.Look(ref portraitPath, "aiPortraitPath", null);
|
||||
|
||||
if (isSaving)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Saving portrait path for {parent?.LabelShort}: '{portraitPath}'"
|
||||
);
|
||||
}
|
||||
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}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
Source/AIImages/Helpers/DebugLogger.cs
Normal file
43
Source/AIImages/Helpers/DebugLogger.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Verse;
|
||||
|
||||
namespace AIImages.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Вспомогательный класс для условного отладочного логирования
|
||||
/// </summary>
|
||||
public static class DebugLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Логирует сообщение только если включены отладочные логи
|
||||
/// </summary>
|
||||
public static void Log(string message)
|
||||
{
|
||||
if (AIImagesMod.Settings?.enableDebugLogs == true)
|
||||
{
|
||||
Verse.Log.Message(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Логирует предупреждение только если включены отладочные логи
|
||||
/// </summary>
|
||||
public static void Warning(string message)
|
||||
{
|
||||
if (AIImagesMod.Settings?.enableDebugLogs == true)
|
||||
{
|
||||
Verse.Log.Warning(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Логирует ошибку только если включены отладочные логи
|
||||
/// </summary>
|
||||
public static void Error(string message)
|
||||
{
|
||||
if (AIImagesMod.Settings?.enableDebugLogs == true)
|
||||
{
|
||||
Verse.Log.Error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using AIImages.Components;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
@@ -15,7 +16,17 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static PawnPortraitComp GetPortraitComp(Pawn pawn)
|
||||
{
|
||||
return pawn?.TryGetComp<PawnPortraitComp>();
|
||||
if (pawn == null)
|
||||
{
|
||||
DebugLogger.Warning("[AI Images] GetPortraitComp called with null pawn");
|
||||
return null;
|
||||
}
|
||||
|
||||
var comp = pawn.TryGetComp<PawnPortraitComp>();
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] GetPortraitComp for {pawn.Name}: {(comp != null ? "Found" : "Not found")}"
|
||||
);
|
||||
return comp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -23,11 +34,25 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static void SavePortraitPath(Pawn pawn, string path)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] SavePortraitPath called for {pawn?.Name} with path: {path}"
|
||||
);
|
||||
|
||||
var comp = GetPortraitComp(pawn);
|
||||
if (comp != null)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Found portrait component for {pawn.Name}, setting path from '{comp.PortraitPath}' to '{path}'"
|
||||
);
|
||||
comp.PortraitPath = path;
|
||||
Log.Message($"[AI Images] Saved portrait path for {pawn.Name}: {path}");
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Successfully saved portrait path for {pawn.Name}: {path}"
|
||||
);
|
||||
DebugLogger.Log($"[AI Images] Component now has portrait: {comp.HasPortrait}");
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Error($"[AI Images] Failed to get portrait component for {pawn?.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +61,19 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static string GetPortraitPath(Pawn pawn)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] GetPortraitPath called for {pawn?.Name}");
|
||||
|
||||
var comp = GetPortraitComp(pawn);
|
||||
return comp?.PortraitPath;
|
||||
if (comp == null)
|
||||
{
|
||||
DebugLogger.Warning($"[AI Images] No portrait component found for {pawn?.Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Portrait component found for {pawn?.Name}, path: '{comp.PortraitPath}'"
|
||||
);
|
||||
return comp.PortraitPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -45,8 +81,20 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static bool HasPortrait(Pawn pawn)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] HasPortrait called for {pawn?.Name}");
|
||||
|
||||
var comp = GetPortraitComp(pawn);
|
||||
return comp != null && comp.HasPortrait;
|
||||
if (comp == null)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] No portrait component found for {pawn?.Name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasPortrait = comp.HasPortrait;
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Portrait component for {pawn?.Name} has portrait: {hasPortrait} (path: '{comp.PortraitPath}')"
|
||||
);
|
||||
return hasPortrait;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,23 +102,46 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static Texture2D LoadPortrait(Pawn pawn)
|
||||
{
|
||||
string path = GetPortraitPath(pawn);
|
||||
DebugLogger.Log($"[AI Images] LoadPortrait called for {pawn?.Name}");
|
||||
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path))
|
||||
string path = GetPortraitPath(pawn);
|
||||
DebugLogger.Log($"[AI Images] Retrieved path for {pawn?.Name}: '{path}'");
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] No portrait path found for {pawn?.Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
DebugLogger.Warning(
|
||||
$"[AI Images] Portrait file does not exist for {pawn?.Name}: {path}"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
DebugLogger.Log($"[AI Images] Portrait file exists for {pawn?.Name}: {path}");
|
||||
|
||||
try
|
||||
{
|
||||
byte[] imageData = File.ReadAllBytes(path);
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Successfully read {imageData.Length} bytes from {path}"
|
||||
);
|
||||
|
||||
Texture2D texture = new Texture2D(2, 2);
|
||||
texture.LoadImage(imageData);
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Successfully loaded texture for {pawn?.Name}, size: {texture.width}x{texture.height}"
|
||||
);
|
||||
return texture;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"[AI Images] Failed to load portrait for {pawn.Name}: {ex.Message}");
|
||||
DebugLogger.Warning(
|
||||
$"[AI Images] Failed to load portrait for {pawn?.Name}: {ex.Message}"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -92,53 +163,62 @@ namespace AIImages.Helpers
|
||||
/// </summary>
|
||||
public static int ClearAllPortraits(string savePath)
|
||||
{
|
||||
int deletedCount = 0;
|
||||
ClearPawnComponents();
|
||||
return DeletePortraitFiles(savePath);
|
||||
}
|
||||
|
||||
// Очищаем компоненты всех пешек
|
||||
if (Current.Game != null && Current.Game.Maps != null)
|
||||
private static void ClearPawnComponents()
|
||||
{
|
||||
if (Current.Game?.Maps == null)
|
||||
return;
|
||||
|
||||
foreach (var map in Current.Game.Maps)
|
||||
{
|
||||
foreach (var map in Current.Game.Maps)
|
||||
foreach (var pawn in map.mapPawns.AllPawns)
|
||||
{
|
||||
foreach (var pawn in map.mapPawns.AllPawns)
|
||||
var comp = GetPortraitComp(pawn);
|
||||
if (comp != null && comp.HasPortrait)
|
||||
{
|
||||
var comp = GetPortraitComp(pawn);
|
||||
if (comp != null && comp.HasPortrait)
|
||||
{
|
||||
comp.PortraitPath = null;
|
||||
}
|
||||
comp.PortraitPath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Удаляем файлы из директории
|
||||
private static int DeletePortraitFiles(string savePath)
|
||||
{
|
||||
int deletedCount = 0;
|
||||
string fullPath = Path.Combine(GenFilePaths.SaveDataFolderPath, savePath);
|
||||
|
||||
if (Directory.Exists(fullPath))
|
||||
if (!Directory.Exists(fullPath))
|
||||
return deletedCount;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = Directory.GetFiles(fullPath, "*.png");
|
||||
foreach (var file in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(file);
|
||||
deletedCount++;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"[AI Images] Failed to delete file {file}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
Log.Message($"[AI Images] Deleted {deletedCount} portrait files");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Error($"[AI Images] Error cleaning portraits directory: {ex.Message}");
|
||||
}
|
||||
var files = Directory.GetFiles(fullPath, "*.png");
|
||||
deletedCount = files.Count(TryDeleteFile);
|
||||
Log.Message($"[AI Images] Deleted {deletedCount} portrait files");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Error($"[AI Images] Error cleaning portraits directory: {ex.Message}");
|
||||
}
|
||||
|
||||
return deletedCount;
|
||||
}
|
||||
|
||||
private static bool TryDeleteFile(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(file);
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"[AI Images] Failed to delete file {file}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using AIImages.Components;
|
||||
using AIImages.Helpers;
|
||||
using HarmonyLib;
|
||||
using Verse;
|
||||
|
||||
@@ -24,6 +25,8 @@ namespace AIImages.Patches
|
||||
&& pawn.GetComp<PawnPortraitComp>() == null
|
||||
)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] Adding portrait component to {pawn.Name}");
|
||||
|
||||
// Создаем компонент
|
||||
var comp = new PawnPortraitComp { parent = pawn };
|
||||
|
||||
@@ -35,6 +38,26 @@ namespace AIImages.Patches
|
||||
if (compsList != null)
|
||||
{
|
||||
compsList.Add(comp);
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Successfully added portrait component to {pawn.Name}"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Error($"[AI Images] Failed to get comps list for {pawn.Name}");
|
||||
}
|
||||
}
|
||||
else if (__instance is Pawn pawn2)
|
||||
{
|
||||
if (pawn2.RaceProps?.Humanlike != true)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] Skipping non-humanlike pawn: {pawn2.Name}");
|
||||
}
|
||||
else if (pawn2.GetComp<PawnPortraitComp>() != null)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Portrait component already exists for {pawn2.Name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace AIImages.Services
|
||||
// Цвет волос
|
||||
string hairColor = ColorDescriptionService.GetHairColorDescription(data.HairColor);
|
||||
hair.Append(hairColor);
|
||||
hair.Append(" ");
|
||||
hair.Append(" hair, ");
|
||||
|
||||
// Стиль прически - используем DefName для английского названия
|
||||
string style = CleanDefName(data.HairDefName)
|
||||
|
||||
@@ -183,8 +183,9 @@ namespace AIImages.Services
|
||||
|
||||
try
|
||||
{
|
||||
// Используем встроенный метод PingAsync библиотеки
|
||||
return await _client.PingAsync(cancellationToken);
|
||||
// Используем встроенный метод HealthCheckAsync библиотеки
|
||||
var healthCheck = await _client.HealthCheckAsync(cancellationToken);
|
||||
return healthCheck.IsHealthy;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -240,7 +241,10 @@ namespace AIImages.Services
|
||||
var samplerNames = new List<string>();
|
||||
if (samplers != null)
|
||||
{
|
||||
samplerNames.AddRange(samplers);
|
||||
foreach (var sampler in samplers)
|
||||
{
|
||||
samplerNames.Add(sampler.Name);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Message($"[AI Images] Found {samplerNames.Count} samplers");
|
||||
@@ -268,7 +272,10 @@ namespace AIImages.Services
|
||||
var schedulerNames = new List<string>();
|
||||
if (schedulers != null)
|
||||
{
|
||||
schedulerNames.AddRange(schedulers);
|
||||
foreach (var scheduler in schedulers)
|
||||
{
|
||||
schedulerNames.Add(scheduler.Name);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Message($"[AI Images] Found {schedulerNames.Count} schedulers");
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace AIImages.Settings
|
||||
public bool showTechnicalInfo = true;
|
||||
public bool saveGenerationHistory = true;
|
||||
public bool saveImagesToServer = false;
|
||||
public bool enableDebugLogs = false;
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
@@ -78,6 +79,7 @@ namespace AIImages.Settings
|
||||
Scribe_Values.Look(ref showTechnicalInfo, "showTechnicalInfo", true);
|
||||
Scribe_Values.Look(ref saveGenerationHistory, "saveGenerationHistory", true);
|
||||
Scribe_Values.Look(ref saveImagesToServer, "saveImagesToServer", false);
|
||||
Scribe_Values.Look(ref enableDebugLogs, "enableDebugLogs", false);
|
||||
|
||||
base.ExposeData();
|
||||
}
|
||||
|
||||
@@ -395,6 +395,11 @@ namespace AIImages
|
||||
ref settings.saveImagesToServer,
|
||||
"AIImages.Settings.SaveImagesToServerTooltip".Translate()
|
||||
);
|
||||
listingStandard.CheckboxLabeled(
|
||||
"AIImages.Settings.EnableDebugLogs".Translate(),
|
||||
ref settings.enableDebugLogs,
|
||||
"AIImages.Settings.EnableDebugLogsTooltip".Translate()
|
||||
);
|
||||
|
||||
listingStandard.Gap(12f);
|
||||
|
||||
|
||||
@@ -83,11 +83,15 @@ namespace AIImages
|
||||
/// </summary>
|
||||
private void RefreshPawnData()
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] RefreshPawnData called for {pawn?.Name}");
|
||||
|
||||
appearanceData = pawnDescriptionService.ExtractAppearanceData(pawn);
|
||||
generationSettings = AIImagesMod.Settings.ToStableDiffusionSettings();
|
||||
|
||||
// Загружаем сохраненный портрет, если есть
|
||||
LoadSavedPortrait();
|
||||
|
||||
DebugLogger.Log($"[AI Images] RefreshPawnData completed for {pawn?.Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,13 +99,30 @@ namespace AIImages
|
||||
/// </summary>
|
||||
private void LoadSavedPortrait()
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] LoadSavedPortrait called for {pawn?.Name}");
|
||||
|
||||
if (PawnPortraitHelper.HasPortrait(pawn))
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] Portrait found for {pawn?.Name}, loading...");
|
||||
generatedImage = PawnPortraitHelper.LoadPortrait(pawn);
|
||||
if (generatedImage != null)
|
||||
{
|
||||
generationStatus = "AIImages.Generation.LoadedFromSave".Translate();
|
||||
DebugLogger.Log($"[AI Images] Successfully loaded portrait for {pawn?.Name}");
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] generatedImage is now set: {generatedImage != null}, size: {generatedImage.width}x{generatedImage.height}"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Warning(
|
||||
$"[AI Images] Failed to load portrait texture for {pawn?.Name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] No saved portrait found for {pawn?.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,13 +148,36 @@ namespace AIImages
|
||||
/// </summary>
|
||||
public void UpdatePawn(Pawn newPawn)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] UpdatePawn called - switching from {pawn?.Name} to {newPawn?.Name}"
|
||||
);
|
||||
|
||||
this.pawn = newPawn;
|
||||
RefreshPawnData();
|
||||
|
||||
// Очищаем старое изображение при смене персонажа
|
||||
generatedImage = null;
|
||||
generationStatus = "";
|
||||
generationProgress = 0.0;
|
||||
currentStep = 0;
|
||||
totalSteps = 0;
|
||||
etaSeconds = 0.0;
|
||||
|
||||
// Сбрасываем состояние сворачиваемых секций
|
||||
showPositivePrompt = false;
|
||||
showNegativePrompt = false;
|
||||
|
||||
// Обновляем данные персонажа (включая загрузку портрета)
|
||||
RefreshPawnData();
|
||||
|
||||
// Принудительно обновляем окно
|
||||
this.windowRect = new Rect(
|
||||
this.windowRect.x,
|
||||
this.windowRect.y,
|
||||
this.InitialSize.x,
|
||||
this.InitialSize.y
|
||||
);
|
||||
|
||||
DebugLogger.Log($"[AI Images] UpdatePawn completed for {newPawn?.Name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,6 +185,80 @@ namespace AIImages
|
||||
/// </summary>
|
||||
public Pawn CurrentPawn => pawn;
|
||||
|
||||
/// <summary>
|
||||
/// Отладочный метод для проверки состояния всех пешек
|
||||
/// </summary>
|
||||
public static void DebugAllPawns()
|
||||
{
|
||||
DebugLogger.Log("[AI Images] === DEBUG: Checking all pawns ===");
|
||||
|
||||
if (Current.Game?.Maps == null)
|
||||
{
|
||||
DebugLogger.Log("[AI Images] No game or maps available");
|
||||
return;
|
||||
}
|
||||
|
||||
int totalPawns = 0;
|
||||
int pawnsWithComponents = 0;
|
||||
int pawnsWithPortraits = 0;
|
||||
|
||||
foreach (var map in Current.Game.Maps)
|
||||
{
|
||||
foreach (var pawn in map.mapPawns.AllPawns)
|
||||
{
|
||||
if (pawn.RaceProps?.Humanlike == true)
|
||||
{
|
||||
totalPawns++;
|
||||
var (hasComponent, hasPortrait) = CheckPawnPortraitStatus(pawn);
|
||||
if (hasComponent)
|
||||
pawnsWithComponents++;
|
||||
if (hasPortrait)
|
||||
pawnsWithPortraits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogDebugSummary(totalPawns, pawnsWithComponents, pawnsWithPortraits);
|
||||
}
|
||||
|
||||
private static (bool hasComponent, bool hasPortrait) CheckPawnPortraitStatus(Pawn pawn)
|
||||
{
|
||||
var comp = PawnPortraitHelper.GetPortraitComp(pawn);
|
||||
if (comp != null)
|
||||
{
|
||||
if (comp.HasPortrait)
|
||||
{
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] {pawn.Name}: Has component with portrait '{comp.PortraitPath}'"
|
||||
);
|
||||
return (true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] {pawn.Name}: Has component but no portrait");
|
||||
return (true, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugLogger.Warning($"[AI Images] {pawn.Name}: No portrait component found!");
|
||||
return (false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogDebugSummary(
|
||||
int totalPawns,
|
||||
int pawnsWithComponents,
|
||||
int pawnsWithPortraits
|
||||
)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] === DEBUG SUMMARY ===");
|
||||
DebugLogger.Log($"[AI Images] Total humanlike pawns: {totalPawns}");
|
||||
DebugLogger.Log($"[AI Images] Pawns with components: {pawnsWithComponents}");
|
||||
DebugLogger.Log($"[AI Images] Pawns with portraits: {pawnsWithPortraits}");
|
||||
DebugLogger.Log($"[AI Images] === END DEBUG ===");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается каждый кадр для обновления окна
|
||||
/// </summary>
|
||||
@@ -238,6 +356,12 @@ namespace AIImages
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
DebugLogger.Log($"[AI Images] Generation successful for {pawn?.Name}");
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Image data size: {result.ImageData?.Length ?? 0} bytes"
|
||||
);
|
||||
DebugLogger.Log($"[AI Images] Saved path: {result.SavedPath}");
|
||||
|
||||
// Загружаем текстуру
|
||||
generatedImage = new Texture2D(2, 2);
|
||||
generatedImage.LoadImage(result.ImageData);
|
||||
@@ -245,12 +369,19 @@ namespace AIImages
|
||||
generationProgress = 1.0;
|
||||
|
||||
// Сохраняем путь к портрету на персонаже
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] About to save portrait path for {pawn?.Name}: {result.SavedPath}"
|
||||
);
|
||||
PawnPortraitHelper.SavePortraitPath(pawn, result.SavedPath);
|
||||
|
||||
Messages.Message(
|
||||
"AIImages.Generation.SavedTo".Translate(result.SavedPath),
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Portrait generation and saving completed for {pawn?.Name}"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -262,12 +393,12 @@ namespace AIImages
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
generationStatus = "AIImages.Generation.Cancelled".Translate();
|
||||
Log.Message("[AI Images] Generation cancelled by user");
|
||||
DebugLogger.Log("[AI Images] Generation cancelled by user");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
generationStatus = $"Error: {ex.Message}";
|
||||
Log.Error($"[AI Images] Generation error: {ex}");
|
||||
DebugLogger.Error($"[AI Images] Generation error: {ex}");
|
||||
Messages.Message(
|
||||
$"AIImages.Generation.Error".Translate() + ": {ex.Message}",
|
||||
MessageTypeDefOf.RejectInput
|
||||
@@ -299,7 +430,7 @@ namespace AIImages
|
||||
totalSteps = progress.TotalSteps;
|
||||
etaSeconds = progress.EtaRelative;
|
||||
|
||||
Log.Message(
|
||||
DebugLogger.Log(
|
||||
$"[AI Images] Progress: {progress.Progress:P} - Step {progress.CurrentStep}/{progress.TotalSteps} - ETA: {progress.EtaRelative:F1}s"
|
||||
);
|
||||
}
|
||||
@@ -314,7 +445,7 @@ namespace AIImages
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning($"[AI Images] Progress monitoring error: {ex.Message}");
|
||||
DebugLogger.Warning($"[AI Images] Progress monitoring error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -910,13 +1041,24 @@ namespace AIImages
|
||||
? "AIImages.Generation.Cancel".Translate()
|
||||
: "AIImages.Generation.Generate".Translate();
|
||||
|
||||
if (Widgets.ButtonText(new Rect(rect.x, curY, rect.width, 35f), buttonLabel))
|
||||
// Основная кнопка генерации (занимает 70% ширины)
|
||||
float buttonWidth = rect.width * 0.7f;
|
||||
if (Widgets.ButtonText(new Rect(rect.x, curY, buttonWidth, 35f), buttonLabel))
|
||||
{
|
||||
if (isGenerating)
|
||||
CancelGeneration();
|
||||
else
|
||||
StartGeneration();
|
||||
}
|
||||
|
||||
// Отладочная кнопка (занимает 25% ширины)
|
||||
float debugButtonWidth = rect.width * 0.25f;
|
||||
float debugButtonX = rect.x + buttonWidth + 10f;
|
||||
if (Widgets.ButtonText(new Rect(debugButtonX, curY, debugButtonWidth, 35f), "Debug"))
|
||||
{
|
||||
DebugAllPawns();
|
||||
}
|
||||
|
||||
return curY + 40f;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user