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:
Binary file not shown.
@@ -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,123 +631,161 @@ namespace AIImages
|
|||||||
contentY += lineHeight;
|
contentY += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Черты характера
|
return contentY;
|
||||||
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
}
|
||||||
{
|
|
||||||
contentY += 15f;
|
|
||||||
Text.Font = GameFont.Small;
|
|
||||||
Widgets.Label(
|
|
||||||
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
|
||||||
"AIImages.Info.Traits".Translate() + ":"
|
|
||||||
);
|
|
||||||
contentY += lineHeight + 2f;
|
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
/// <summary>
|
||||||
var traitLabels = pawn.story.traits.allTraits.Select(trait => trait.LabelCap);
|
/// Отрисовывает черты характера персонажа
|
||||||
foreach (var traitLabel in traitLabels)
|
/// </summary>
|
||||||
{
|
private float DrawTraits(Rect parentRect, float startY, float lineHeight)
|
||||||
Widgets.Label(
|
{
|
||||||
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
float contentY = startY;
|
||||||
"• " + traitLabel
|
|
||||||
);
|
if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
|
||||||
contentY += lineHeight;
|
return contentY;
|
||||||
}
|
|
||||||
|
contentY += 15f;
|
||||||
|
Text.Font = GameFont.Small;
|
||||||
|
Widgets.Label(
|
||||||
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
|
"AIImages.Info.Traits".Translate() + ":"
|
||||||
|
);
|
||||||
|
contentY += lineHeight + 2f;
|
||||||
|
|
||||||
|
Text.Font = GameFont.Tiny;
|
||||||
|
var traitLabels = pawn.story.traits.allTraits.Select(trait => trait.LabelCap);
|
||||||
|
foreach (var traitLabel in traitLabels)
|
||||||
|
{
|
||||||
|
Widgets.Label(
|
||||||
|
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
||||||
|
"• " + traitLabel
|
||||||
|
);
|
||||||
|
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(
|
||||||
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
|
"AIImages.Info.Genes".Translate() + ":"
|
||||||
|
);
|
||||||
|
contentY += lineHeight + 2f;
|
||||||
|
|
||||||
|
Text.Font = GameFont.Tiny;
|
||||||
|
var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
|
||||||
|
foreach (var gene in activeGenes)
|
||||||
{
|
{
|
||||||
contentY += 15f;
|
string geneInfo = BuildGeneInfo(gene);
|
||||||
Text.Font = GameFont.Small;
|
float textHeight = Text.CalcHeight(geneInfo, parentRect.width - 25f);
|
||||||
|
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, textHeight),
|
||||||
"AIImages.Info.Genes".Translate() + ":"
|
"• " + geneInfo
|
||||||
);
|
);
|
||||||
contentY += lineHeight + 2f;
|
contentY += textHeight;
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Рассчитываем высоту текста
|
|
||||||
float textHeight = Text.CalcHeight(geneInfo, parentRect.width - 25f);
|
|
||||||
|
|
||||||
Widgets.Label(
|
|
||||||
new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, textHeight),
|
|
||||||
"• " + geneInfo
|
|
||||||
);
|
|
||||||
contentY += textHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Хедифы (состояния)
|
return contentY;
|
||||||
if (pawn.health?.hediffSet?.hediffs != null && pawn.health.hediffSet.hediffs.Any())
|
}
|
||||||
{
|
|
||||||
contentY += 15f;
|
|
||||||
Text.Font = GameFont.Small;
|
|
||||||
Widgets.Label(
|
|
||||||
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
|
||||||
"AIImages.Info.Hediffs".Translate() + ":"
|
|
||||||
);
|
|
||||||
contentY += lineHeight + 2f;
|
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
/// <summary>
|
||||||
var hediffLabels = pawn
|
/// Строит информационную строку для гена
|
||||||
.health.hediffSet.hediffs.Where(hediff => hediff.Visible)
|
/// </summary>
|
||||||
.Select(hediff => hediff.LabelCap);
|
private string BuildGeneInfo(Gene gene)
|
||||||
foreach (var hediffLabel in hediffLabels)
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
Widgets.Label(
|
description = description.Substring(0, 197) + "...";
|
||||||
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
|
||||||
"• " + hediffLabel
|
|
||||||
);
|
|
||||||
contentY += lineHeight;
|
|
||||||
}
|
}
|
||||||
|
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(
|
||||||
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
|
"AIImages.Info.Hediffs".Translate() + ":"
|
||||||
|
);
|
||||||
|
contentY += lineHeight + 2f;
|
||||||
|
|
||||||
|
Text.Font = GameFont.Tiny;
|
||||||
|
var hediffLabels = pawn
|
||||||
|
.health.hediffSet.hediffs.Where(hediff => hediff.Visible)
|
||||||
|
.Select(hediff => hediff.LabelCap);
|
||||||
|
foreach (var hediffLabel in hediffLabels)
|
||||||
|
{
|
||||||
|
Widgets.Label(
|
||||||
|
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
||||||
|
"• " + hediffLabel
|
||||||
|
);
|
||||||
|
contentY += lineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отрисовывает одежду персонажа
|
||||||
|
/// </summary>
|
||||||
|
private void DrawApparel(Rect parentRect, float startY, float lineHeight)
|
||||||
|
{
|
||||||
|
float contentY = startY;
|
||||||
var apparel = pawn.apparel?.WornApparel;
|
var apparel = pawn.apparel?.WornApparel;
|
||||||
if (apparel != null && apparel.Any())
|
|
||||||
{
|
|
||||||
contentY += 15f;
|
|
||||||
Text.Font = GameFont.Small;
|
|
||||||
Widgets.Label(
|
|
||||||
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
|
||||||
"AIImages.Info.Apparel".Translate() + ":"
|
|
||||||
);
|
|
||||||
contentY += lineHeight + 2f;
|
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
if (apparel == null || !apparel.Any())
|
||||||
foreach (var item in apparel)
|
return;
|
||||||
{
|
|
||||||
var colorDesc = ColorDescriptionService.GetApparelColorDescription(
|
contentY += 15f;
|
||||||
item.DrawColor
|
Text.Font = GameFont.Small;
|
||||||
);
|
Widgets.Label(
|
||||||
string apparelLabel = $"• {colorDesc} {item.def.label}";
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
|
"AIImages.Info.Apparel".Translate() + ":"
|
||||||
Widgets.Label(
|
);
|
||||||
new Rect(
|
contentY += lineHeight + 2f;
|
||||||
parentRect.x + 15f,
|
|
||||||
contentY,
|
Text.Font = GameFont.Tiny;
|
||||||
parentRect.width - 25f,
|
foreach (var item in apparel)
|
||||||
apparelHeight
|
{
|
||||||
),
|
var colorDesc = ColorDescriptionService.GetApparelColorDescription(item.DrawColor);
|
||||||
apparelLabel
|
string apparelLabel = $"• {colorDesc} {item.def.label}";
|
||||||
);
|
float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
|
||||||
contentY += apparelHeight;
|
Widgets.Label(
|
||||||
}
|
new Rect(parentRect.x + 15f, contentY, parentRect.width - 25f, apparelHeight),
|
||||||
|
apparelLabel
|
||||||
|
);
|
||||||
|
contentY += apparelHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
{
|
||||||
|
float height = 35f; // Заголовок "Информация о персонаже"
|
||||||
|
height += 10f; // Разделитель
|
||||||
|
height += 6 * 22f; // Базовая информация (6 строк по 22px)
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
// Разделитель
|
/// <summary>
|
||||||
height += 10f;
|
/// Рассчитывает высоту секции черт характера
|
||||||
|
/// </summary>
|
||||||
|
private float CalculateTraitsHeight()
|
||||||
|
{
|
||||||
|
if (pawn.story?.traits?.allTraits == null || !pawn.story.traits.allTraits.Any())
|
||||||
|
return 0f;
|
||||||
|
|
||||||
// Базовая информация (6 строк по 22px)
|
float height = 15f; // Отступ
|
||||||
height += 6 * 22f;
|
height += 22f; // Заголовок "Черты характера"
|
||||||
|
height += 2f; // Отступ
|
||||||
|
height += pawn.story.traits.allTraits.Count * 22f; // Каждая черта
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
// Черты характера (если есть)
|
/// <summary>
|
||||||
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
/// Рассчитывает высоту секции генов
|
||||||
|
/// </summary>
|
||||||
|
private float CalculateGenesHeight()
|
||||||
|
{
|
||||||
|
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 approximateColumnWidth = 900f * 0.35f; // Примерная ширина левой колонки
|
||||||
|
float labelWidth = approximateColumnWidth - 25f;
|
||||||
|
|
||||||
|
foreach (var gene in activeGenes)
|
||||||
{
|
{
|
||||||
height += 15f; // Отступ
|
string geneInfo = BuildGeneInfo(gene);
|
||||||
height += 22f; // Заголовок "Черты характера"
|
height += Text.CalcHeight("• " + geneInfo, labelWidth);
|
||||||
height += 2f; // Отступ
|
|
||||||
height += pawn.story.traits.allTraits.Count * 22f; // Каждая черта
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Гены (если есть)
|
return height;
|
||||||
if (pawn.genes?.GenesListForReading != null && pawn.genes.GenesListForReading.Any())
|
}
|
||||||
{
|
|
||||||
height += 15f; // Отступ
|
|
||||||
height += 22f; // Заголовок "Гены"
|
|
||||||
height += 2f; // Отступ
|
|
||||||
|
|
||||||
// Рассчитываем высоту для каждого гена с учетом описания
|
/// <summary>
|
||||||
Text.Font = GameFont.Tiny;
|
/// Рассчитывает высоту секции хедифов
|
||||||
var activeGenes = pawn.genes.GenesListForReading.Where(gene => gene.Active).ToList();
|
/// </summary>
|
||||||
float labelWidth = parentRect.width - 25f;
|
private float CalculateHediffsHeight()
|
||||||
foreach (var gene in activeGenes)
|
{
|
||||||
{
|
if (pawn.health?.hediffSet?.hediffs == null || !pawn.health.hediffSet.hediffs.Any())
|
||||||
string geneLabel = gene.Label ?? gene.def.LabelCap;
|
return 0f;
|
||||||
string geneInfo = geneLabel;
|
|
||||||
if (!string.IsNullOrEmpty(gene.def.description) && gene.def.description.Length < 100)
|
|
||||||
{
|
|
||||||
geneInfo += " - " + gene.def.description;
|
|
||||||
}
|
|
||||||
height += Text.CalcHeight("• " + geneInfo, labelWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Хедифы (если есть)
|
float height = 15f; // Отступ
|
||||||
if (pawn.health?.hediffSet?.hediffs != null && pawn.health.hediffSet.hediffs.Any())
|
height += 22f; // Заголовок "Хедифы"
|
||||||
{
|
height += 2f; // Отступ
|
||||||
height += 15f; // Отступ
|
height += pawn.health.hediffSet.hediffs.Count(hediff => hediff.Visible) * 22f; // Каждый видимый хедиф
|
||||||
height += 22f; // Заголовок "Хедифы"
|
return height;
|
||||||
height += 2f; // Отступ
|
}
|
||||||
height += pawn.health.hediffSet.hediffs.Count(hediff => hediff.Visible) * 22f; // Каждый видимый хедиф
|
|
||||||
}
|
|
||||||
|
|
||||||
// Одежда (если есть)
|
/// <summary>
|
||||||
|
/// Рассчитывает высоту секции одежды
|
||||||
|
/// </summary>
|
||||||
|
private float CalculateApparelHeight()
|
||||||
|
{
|
||||||
var apparel = pawn.apparel?.WornApparel;
|
var apparel = pawn.apparel?.WornApparel;
|
||||||
if (apparel != null && apparel.Any())
|
if (apparel == null || !apparel.Any())
|
||||||
{
|
return 0f;
|
||||||
height += 15f; // Отступ
|
|
||||||
height += 22f; // Заголовок "Одежда"
|
|
||||||
height += 2f; // Отступ
|
|
||||||
// Примерно по 22-30px на предмет одежды
|
|
||||||
height += apparel.Count * 26f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Дополнительный отступ
|
|
||||||
height += 50f;
|
|
||||||
|
|
||||||
|
float height = 15f; // Отступ
|
||||||
|
height += 22f; // Заголовок "Одежда"
|
||||||
|
height += 2f; // Отступ
|
||||||
|
height += apparel.Count * 26f; // Примерно по 22-30px на предмет одежды
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user