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