Refactor character information display in AIImages mod by modularizing the rendering of basic info, traits, genes, hediffs, and apparel into separate methods. Enhance height calculation logic for improved layout consistency. Update AIImages.dll to reflect these changes.

This commit is contained in:
Leonid Pershin
2025-10-31 10:13:42 +03:00
parent 1ec80a01cb
commit 731428fb44
2 changed files with 244 additions and 162 deletions

Binary file not shown.

View File

@@ -572,12 +572,25 @@ namespace AIImages
{
float contentY = startY;
float lineHeight = 22f;
contentY = DrawBasicInfo(parentRect, contentY, lineHeight);
contentY = DrawTraits(parentRect, contentY, lineHeight);
contentY = DrawGenes(parentRect, contentY, lineHeight);
contentY = DrawHediffs(parentRect, contentY, lineHeight);
DrawApparel(parentRect, contentY, lineHeight);
}
/// <summary>
/// Отрисовывает базовую информацию о персонаже
/// </summary>
private float DrawBasicInfo(Rect parentRect, float startY, float lineHeight)
{
float contentY = startY;
float labelWidth = parentRect.width * 0.45f;
float valueWidth = parentRect.width * 0.50f;
Text.Font = GameFont.Tiny;
// Базовая информация
var info = new[]
{
("AIImages.Info.Gender".Translate(), appearanceData.Gender.ToString()),
@@ -618,9 +631,19 @@ namespace AIImages
contentY += lineHeight;
}
// Черты характера
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
return contentY;
}
/// <summary>
/// Отрисовывает черты характера персонажа
/// </summary>
private float DrawTraits(Rect parentRect, float startY, float lineHeight)
{
float contentY = startY;
if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
return contentY;
contentY += 15f;
Text.Font = GameFont.Small;
Widgets.Label(
@@ -639,11 +662,20 @@ namespace AIImages
);
contentY += lineHeight;
}
return contentY;
}
// Гены
if (pawn.genes?.GenesListForReading != null && pawn.genes.GenesListForReading.Any())
/// <summary>
/// Отрисовывает гены персонажа
/// </summary>
private float DrawGenes(Rect parentRect, float startY, float lineHeight)
{
float contentY = startY;
if (pawn.genes?.GenesListForReading == null || !pawn.genes.GenesListForReading.Any())
return contentY;
contentY += 15f;
Text.Font = GameFont.Small;
Widgets.Label(
@@ -656,19 +688,7 @@ namespace AIImages
var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
foreach (var gene in activeGenes)
{
// Получаем лейбл гена (предпочитаем Label, если доступен, иначе LabelCap)
string geneLabel = gene.Label ?? gene.def.LabelCap;
// Собираем дополнительную информацию
string geneInfo = geneLabel;
// Добавляем описание, если оно есть и не слишком длинное
if (!string.IsNullOrEmpty(gene.def.description) && gene.def.description.Length < 100)
{
geneInfo += " - " + gene.def.description;
}
// Рассчитываем высоту текста
string geneInfo = BuildGeneInfo(gene);
float textHeight = Text.CalcHeight(geneInfo, parentRect.width - 25f);
Widgets.Label(
@@ -677,11 +697,41 @@ namespace AIImages
);
contentY += textHeight;
}
return contentY;
}
// Хедифы (состояния)
if (pawn.health?.hediffSet?.hediffs != null && pawn.health.hediffSet.hediffs.Any())
/// <summary>
/// Строит информационную строку для гена
/// </summary>
private string BuildGeneInfo(Gene gene)
{
string geneLabel = gene.Label ?? gene.def.LabelCap;
string geneInfo = geneLabel;
if (!string.IsNullOrEmpty(gene.def.description))
{
string description = gene.def.description;
if (description.Length > 200)
{
description = description.Substring(0, 197) + "...";
}
geneInfo += " - " + description;
}
return geneInfo;
}
/// <summary>
/// Отрисовывает хедифы (состояния здоровья) персонажа
/// </summary>
private float DrawHediffs(Rect parentRect, float startY, float lineHeight)
{
float contentY = startY;
if (pawn.health?.hediffSet?.hediffs == null || !pawn.health.hediffSet.hediffs.Any())
return contentY;
contentY += 15f;
Text.Font = GameFont.Small;
Widgets.Label(
@@ -702,12 +752,21 @@ namespace AIImages
);
contentY += lineHeight;
}
return contentY;
}
// Одежда
var apparel = pawn.apparel?.WornApparel;
if (apparel != null && apparel.Any())
/// <summary>
/// Отрисовывает одежду персонажа
/// </summary>
private void DrawApparel(Rect parentRect, float startY, float lineHeight)
{
float contentY = startY;
var apparel = pawn.apparel?.WornApparel;
if (apparel == null || !apparel.Any())
return;
contentY += 15f;
Text.Font = GameFont.Small;
Widgets.Label(
@@ -719,24 +778,16 @@ namespace AIImages
Text.Font = GameFont.Tiny;
foreach (var item in apparel)
{
var colorDesc = ColorDescriptionService.GetApparelColorDescription(
item.DrawColor
);
var colorDesc = ColorDescriptionService.GetApparelColorDescription(item.DrawColor);
string apparelLabel = $"• {colorDesc} {item.def.label}";
float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
Widgets.Label(
new Rect(
parentRect.x + 15f,
contentY,
parentRect.width - 25f,
apparelHeight
),
new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, apparelHeight),
apparelLabel
);
contentY += apparelHeight;
}
}
}
private void DrawRightColumn(Rect rect)
{
@@ -803,79 +854,110 @@ namespace AIImages
private float CalculateContentHeight()
{
float height = 0f;
float height = CalculatePortraitHeight();
height += CalculateBasicInfoHeight();
height += CalculateTraitsHeight();
height += CalculateGenesHeight();
height += CalculateHediffsHeight();
height += CalculateApparelHeight();
height += 50f; // Дополнительный отступ
return height;
}
// Портрет персонажа (если есть)
/// <summary>
/// Рассчитывает высоту портрета персонажа
/// </summary>
private float CalculatePortraitHeight()
{
if (generatedImage != null)
{
float portraitSize = 250f; // Максимальный размер портрета
height += portraitSize + 15f;
return portraitSize + 15f;
}
return 0f;
}
// Заголовок "Информация о персонаже"
height += 35f;
// Разделитель
height += 10f;
// Базовая информация (6 строк по 22px)
height += 6 * 22f;
// Черты характера (если есть)
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
/// <summary>
/// Рассчитывает высоту базовой информации
/// </summary>
private float CalculateBasicInfoHeight()
{
height += 15f; // Отступ
float height = 35f; // Заголовок "Информация о персонаже"
height += 10f; // Разделитель
height += 6 * 22f; // Базовая информация (6 строк по 22px)
return height;
}
/// <summary>
/// Рассчитывает высоту секции черт характера
/// </summary>
private float CalculateTraitsHeight()
{
if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
return 0f;
float height = 15f; // Отступ
height += 22f; // Заголовок "Черты характера"
height += 2f; // Отступ
height += pawn.story.traits.allTraits.Count * 22f; // Каждая черта
return height;
}
// Гены (если есть)
if (pawn.genes?.GenesListForReading != null && pawn.genes.GenesListForReading.Any())
/// <summary>
/// Рассчитывает высоту секции генов
/// </summary>
private float CalculateGenesHeight()
{
height += 15f; // Отступ
if (pawn.genes?.GenesListForReading == null || !pawn.genes.GenesListForReading.Any())
return 0f;
float height = 15f; // Отступ
height += 22f; // Заголовок "Гены"
height += 2f; // Отступ
// Рассчитываем высоту для каждого гена с учетом описания
Text.Font = GameFont.Tiny;
var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
float labelWidth = parentRect.width - 25f;
float approximateColumnWidth = 900f * 0.35f; // Примерная ширина левой колонки
float labelWidth = approximateColumnWidth - 25f;
foreach (var gene in activeGenes)
{
string geneLabel = gene.Label ?? gene.def.LabelCap;
string geneInfo = geneLabel;
if (!string.IsNullOrEmpty(gene.def.description) && gene.def.description.Length < 100)
{
geneInfo += " - " + gene.def.description;
}
string geneInfo = BuildGeneInfo(gene);
height += Text.CalcHeight("• " + geneInfo, labelWidth);
}
return height;
}
// Хедифы (если есть)
if (pawn.health?.hediffSet?.hediffs != null && pawn.health.hediffSet.hediffs.Any())
/// <summary>
/// Рассчитывает высоту секции хедифов
/// </summary>
private float CalculateHediffsHeight()
{
height += 15f; // Отступ
if (pawn.health?.hediffSet?.hediffs == null || !pawn.health.hediffSet.hediffs.Any())
return 0f;
float height = 15f; // Отступ
height += 22f; // Заголовок "Хедифы"
height += 2f; // Отступ
height += pawn.health.hediffSet.hediffs.Count(hediff => hediff.Visible) * 22f; // Каждый видимый хедиф
return height;
}
// Одежда (если есть)
var apparel = pawn.apparel?.WornApparel;
if (apparel != null && apparel.Any())
/// <summary>
/// Рассчитывает высоту секции одежды
/// </summary>
private float CalculateApparelHeight()
{
height += 15f; // Отступ
var apparel = pawn.apparel?.WornApparel;
if (apparel == null || !apparel.Any())
return 0f;
float height = 15f; // Отступ
height += 22f; // Заголовок "Одежда"
height += 2f; // Отступ
// Примерно по 22-30px на предмет одежды
height += apparel.Count * 26f;
}
// Дополнительный отступ
height += 50f;
height += apparel.Count * 26f; // Примерно по 22-30px на предмет одежды
return height;
}