Refactor AIImages mod to improve UI layout and scrolling functionality in the character information display. Update prompt generation logic to enhance gender and age representation. Adjust content height calculations for better visual consistency. Update AIImages.dll to reflect these changes.
This commit is contained in:
Binary file not shown.
@@ -59,14 +59,19 @@ namespace AIImages.Services
|
|||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Тип кадра - автоматически добавляем "portrait" для генерации персонажей
|
// 3. Тип кадра
|
||||||
prompt.Append("portrait, head and shoulders of ");
|
prompt.Append("portrait, ");
|
||||||
|
|
||||||
// 4. Базовое описание (возраст и пол)
|
// 4. Пол персонажа (в формате anime/SD теги)
|
||||||
prompt.Append(GetAgeAndGenderDescription(appearanceData));
|
string genderTag = appearanceData.Gender == Gender.Female ? "1girl" : "1boy";
|
||||||
|
prompt.Append(genderTag);
|
||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
|
|
||||||
// 5. Тип тела
|
// 5. Точный возраст
|
||||||
|
prompt.Append($"{appearanceData.Age} y.o.");
|
||||||
|
prompt.Append(", ");
|
||||||
|
|
||||||
|
// 6. Тип тела
|
||||||
string bodyType = GetBodyTypeDescription(appearanceData.BodyType);
|
string bodyType = GetBodyTypeDescription(appearanceData.BodyType);
|
||||||
if (!string.IsNullOrEmpty(bodyType))
|
if (!string.IsNullOrEmpty(bodyType))
|
||||||
{
|
{
|
||||||
@@ -74,14 +79,14 @@ namespace AIImages.Services
|
|||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Цвет кожи
|
// 7. Цвет кожи
|
||||||
string skinTone = ColorDescriptionService.GetSkinToneDescription(
|
string skinTone = ColorDescriptionService.GetSkinToneDescription(
|
||||||
appearanceData.SkinColor
|
appearanceData.SkinColor
|
||||||
);
|
);
|
||||||
prompt.Append(skinTone);
|
prompt.Append(skinTone);
|
||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
|
|
||||||
// 7. Волосы
|
// 8. Волосы
|
||||||
string hairDescription = GetHairDescription(appearanceData);
|
string hairDescription = GetHairDescription(appearanceData);
|
||||||
if (!string.IsNullOrEmpty(hairDescription))
|
if (!string.IsNullOrEmpty(hairDescription))
|
||||||
{
|
{
|
||||||
@@ -89,7 +94,7 @@ namespace AIImages.Services
|
|||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Настроение и выражение на основе черт характера
|
// 9. Настроение и выражение на основе черт характера
|
||||||
string moodDescription = GetMoodFromTraits(appearanceData.Traits);
|
string moodDescription = GetMoodFromTraits(appearanceData.Traits);
|
||||||
if (!string.IsNullOrEmpty(moodDescription))
|
if (!string.IsNullOrEmpty(moodDescription))
|
||||||
{
|
{
|
||||||
@@ -97,7 +102,7 @@ namespace AIImages.Services
|
|||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Одежда
|
// 10. Одежда
|
||||||
string apparelDescription = GetApparelDescription(appearanceData.Apparel);
|
string apparelDescription = GetApparelDescription(appearanceData.Apparel);
|
||||||
if (!string.IsNullOrEmpty(apparelDescription))
|
if (!string.IsNullOrEmpty(apparelDescription))
|
||||||
{
|
{
|
||||||
@@ -105,7 +110,7 @@ namespace AIImages.Services
|
|||||||
prompt.Append(", ");
|
prompt.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10. Качественные теги
|
// 11. Качественные теги
|
||||||
prompt.Append(GetQualityTags(settings.ArtStyleDefName));
|
prompt.Append(GetQualityTags(settings.ArtStyleDefName));
|
||||||
|
|
||||||
return prompt.ToString().Trim().TrimEnd(',');
|
return prompt.ToString().Trim().TrimEnd(',');
|
||||||
@@ -179,27 +184,6 @@ namespace AIImages.Services
|
|||||||
return description.ToString();
|
return description.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAgeAndGenderDescription(PawnAppearanceData data)
|
|
||||||
{
|
|
||||||
string ageGroup = data.Age switch
|
|
||||||
{
|
|
||||||
< 18 => "young",
|
|
||||||
< 25 => "young adult",
|
|
||||||
< 35 => "adult",
|
|
||||||
< 50 => "middle-aged",
|
|
||||||
< 65 => "mature",
|
|
||||||
_ => "elderly",
|
|
||||||
};
|
|
||||||
|
|
||||||
string genderLabel = data.Gender switch
|
|
||||||
{
|
|
||||||
Gender.Male => "man",
|
|
||||||
Gender.Female => "woman",
|
|
||||||
_ => "person",
|
|
||||||
};
|
|
||||||
return $"{ageGroup} {genderLabel}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetBodyTypeDescription(string bodyType)
|
private string GetBodyTypeDescription(string bodyType)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(bodyType))
|
if (string.IsNullOrEmpty(bodyType))
|
||||||
|
|||||||
@@ -69,16 +69,14 @@ namespace AIImages
|
|||||||
|
|
||||||
public override Vector2 InitialSize => new Vector2(900f, 800f);
|
public override Vector2 InitialSize => new Vector2(900f, 800f);
|
||||||
|
|
||||||
private Vector2 scrollPosition = Vector2.zero;
|
private Vector2 mainScrollPosition = Vector2.zero;
|
||||||
private Vector2 rightColumnScrollPosition = Vector2.zero;
|
|
||||||
private Vector2 promptScrollPosition = Vector2.zero;
|
private Vector2 promptScrollPosition = Vector2.zero;
|
||||||
private Vector2 negativePromptScrollPosition = Vector2.zero;
|
private Vector2 negativePromptScrollPosition = Vector2.zero;
|
||||||
private float copiedMessageTime = 0f;
|
private float copiedMessageTime = 0f;
|
||||||
|
|
||||||
// Состояние сворачиваемых секций
|
// Состояние сворачиваемых секций промптов
|
||||||
private bool showPositivePrompt = false;
|
private bool showPositivePrompt = false;
|
||||||
private bool showNegativePrompt = false;
|
private bool showNegativePrompt = false;
|
||||||
private bool showCharacterInfo = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновляет данные персонажа
|
/// Обновляет данные персонажа
|
||||||
@@ -342,12 +340,18 @@ namespace AIImages
|
|||||||
|
|
||||||
public override void DoWindowContents(Rect inRect)
|
public override void DoWindowContents(Rect inRect)
|
||||||
{
|
{
|
||||||
|
// Рассчитываем общую высоту контента
|
||||||
|
float totalContentHeight = CalculateTotalContentHeight();
|
||||||
|
Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, totalContentHeight);
|
||||||
|
|
||||||
|
Widgets.BeginScrollView(inRect, ref mainScrollPosition, viewRect);
|
||||||
|
|
||||||
float curY = 0f;
|
float curY = 0f;
|
||||||
|
|
||||||
// Заголовок
|
// Заголовок
|
||||||
Text.Font = GameFont.Medium;
|
Text.Font = GameFont.Medium;
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(0f, curY, inRect.width, 40f),
|
new Rect(0f, curY, viewRect.width, 40f),
|
||||||
"AIImages.Window.Title".Translate()
|
"AIImages.Window.Title".Translate()
|
||||||
);
|
);
|
||||||
curY += 45f;
|
curY += 45f;
|
||||||
@@ -355,22 +359,25 @@ namespace AIImages
|
|||||||
// Имя пешки
|
// Имя пешки
|
||||||
Text.Font = GameFont.Small;
|
Text.Font = GameFont.Small;
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(0f, curY, inRect.width, 30f),
|
new Rect(0f, curY, viewRect.width, 30f),
|
||||||
"AIImages.Window.PawnLabel".Translate(pawn.NameShortColored.Resolve())
|
"AIImages.Window.PawnLabel".Translate(pawn.NameShortColored.Resolve())
|
||||||
);
|
);
|
||||||
curY += 40f;
|
curY += 40f;
|
||||||
|
|
||||||
// Разделитель
|
// Разделитель
|
||||||
Widgets.DrawLineHorizontal(0f, curY, inRect.width);
|
Widgets.DrawLineHorizontal(0f, curY, viewRect.width);
|
||||||
curY += 10f;
|
curY += 10f;
|
||||||
|
|
||||||
// Разделяем на две колонки: левая - информация, правая - изображение
|
// Разделяем на две колонки: левая - информация, правая - изображение
|
||||||
float leftColumnWidth = inRect.width * 0.55f;
|
float leftColumnWidth = viewRect.width * 0.35f;
|
||||||
float rightColumnWidth = inRect.width * 0.42f;
|
float rightColumnWidth = viewRect.width * 0.62f;
|
||||||
float columnGap = inRect.width * 0.03f;
|
float columnGap = viewRect.width * 0.03f;
|
||||||
|
|
||||||
// Левая колонка - прокручиваемая информация
|
// Определяем высоту колонок (берем большую из двух)
|
||||||
Rect leftColumnRect = new Rect(0f, curY, leftColumnWidth, inRect.height - curY);
|
float columnHeight = Mathf.Max(CalculateContentHeight(), CalculateRightColumnHeight());
|
||||||
|
|
||||||
|
// Левая колонка - информация
|
||||||
|
Rect leftColumnRect = new Rect(0f, curY, leftColumnWidth, columnHeight);
|
||||||
DrawLeftColumn(leftColumnRect);
|
DrawLeftColumn(leftColumnRect);
|
||||||
|
|
||||||
// Правая колонка - превью и управление
|
// Правая колонка - превью и управление
|
||||||
@@ -378,24 +385,23 @@ namespace AIImages
|
|||||||
leftColumnWidth + columnGap,
|
leftColumnWidth + columnGap,
|
||||||
curY,
|
curY,
|
||||||
rightColumnWidth,
|
rightColumnWidth,
|
||||||
inRect.height - curY
|
columnHeight
|
||||||
);
|
);
|
||||||
DrawRightColumn(rightColumnRect);
|
DrawRightColumn(rightColumnRect);
|
||||||
|
|
||||||
|
Widgets.EndScrollView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawLeftColumn(Rect rect)
|
private void DrawLeftColumn(Rect rect)
|
||||||
{
|
{
|
||||||
Rect scrollViewRect = new Rect(0f, 0f, rect.width - 20f, CalculateContentHeight());
|
float contentY = rect.y;
|
||||||
Widgets.BeginScrollView(rect, ref scrollPosition, scrollViewRect);
|
|
||||||
|
|
||||||
float contentY = 0f;
|
|
||||||
|
|
||||||
// Портрет персонажа (если есть)
|
// Портрет персонажа (если есть)
|
||||||
if (generatedImage != null)
|
if (generatedImage != null)
|
||||||
{
|
{
|
||||||
float portraitSize = Mathf.Min(scrollViewRect.width - 20f, 200f);
|
float portraitSize = Mathf.Min(rect.width, 250f);
|
||||||
Rect portraitRect = new Rect(
|
Rect portraitRect = new Rect(
|
||||||
(scrollViewRect.width - portraitSize) / 2f,
|
rect.x + (rect.width - portraitSize) / 2f,
|
||||||
contentY,
|
contentY,
|
||||||
portraitSize,
|
portraitSize,
|
||||||
portraitSize
|
portraitSize
|
||||||
@@ -404,29 +410,34 @@ namespace AIImages
|
|||||||
// Рамка вокруг портрета
|
// Рамка вокруг портрета
|
||||||
Widgets.DrawBox(portraitRect);
|
Widgets.DrawBox(portraitRect);
|
||||||
GUI.DrawTexture(portraitRect.ContractedBy(2f), generatedImage);
|
GUI.DrawTexture(portraitRect.ContractedBy(2f), generatedImage);
|
||||||
contentY += portraitSize + 20f;
|
contentY += portraitSize + 15f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сворачиваемая секция "Информация о персонаже"
|
// Заголовок секции
|
||||||
DrawCollapsibleSection(
|
Text.Font = GameFont.Medium;
|
||||||
scrollViewRect,
|
Widgets.Label(
|
||||||
contentY,
|
new Rect(rect.x, contentY, rect.width, 30f),
|
||||||
"AIImages.CharacterInfo.Title".Translate(),
|
"AIImages.CharacterInfo.Title".Translate()
|
||||||
ref showCharacterInfo,
|
|
||||||
() => DrawCharacterInfoContent(scrollViewRect)
|
|
||||||
);
|
);
|
||||||
|
contentY += 35f;
|
||||||
|
|
||||||
Widgets.EndScrollView();
|
// Разделитель
|
||||||
|
Widgets.DrawLineHorizontal(rect.x, contentY, rect.width);
|
||||||
|
contentY += 10f;
|
||||||
|
|
||||||
|
// Информация о персонаже
|
||||||
|
DrawCharacterInfoContent(rect, contentY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Отрисовывает информацию о персонаже в компактном виде
|
/// Отрисовывает информацию о персонаже в компактном виде
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private float DrawCharacterInfoContent(Rect parentRect)
|
private void DrawCharacterInfoContent(Rect parentRect, float startY)
|
||||||
{
|
{
|
||||||
float contentHeight = 0f;
|
float contentY = startY;
|
||||||
float lineHeight = 24f;
|
float lineHeight = 22f;
|
||||||
float indent = 10f;
|
float labelWidth = parentRect.width * 0.45f;
|
||||||
|
float valueWidth = parentRect.width * 0.50f;
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
Text.Font = GameFont.Tiny;
|
||||||
|
|
||||||
@@ -449,47 +460,48 @@ namespace AIImages
|
|||||||
|
|
||||||
foreach (var (label, value) in info)
|
foreach (var (label, value) in info)
|
||||||
{
|
{
|
||||||
|
// Подсветка строк через одну
|
||||||
|
var infoArray = info.ToArray();
|
||||||
|
int index = Array.IndexOf(infoArray, (label, value));
|
||||||
|
if ((index % 2) == 0)
|
||||||
|
{
|
||||||
|
Widgets.DrawBoxSolid(
|
||||||
|
new Rect(parentRect.x, contentY, parentRect.width, lineHeight),
|
||||||
|
new Color(0.15f, 0.15f, 0.15f, 0.3f)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(indent, contentHeight, parentRect.width * 0.4f, lineHeight),
|
new Rect(parentRect.x + 5f, contentY, labelWidth, lineHeight),
|
||||||
label + ":"
|
label + ":"
|
||||||
);
|
);
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(
|
new Rect(parentRect.x + labelWidth + 10f, contentY, valueWidth, lineHeight),
|
||||||
parentRect.width * 0.42f,
|
|
||||||
contentHeight,
|
|
||||||
parentRect.width * 0.55f,
|
|
||||||
lineHeight
|
|
||||||
),
|
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
contentHeight += lineHeight;
|
contentY += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Черты характера
|
// Черты характера
|
||||||
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
||||||
{
|
{
|
||||||
contentHeight += 10f;
|
contentY += 15f;
|
||||||
Text.Font = GameFont.Small;
|
Text.Font = GameFont.Small;
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(indent, contentHeight, parentRect.width - indent * 2, lineHeight),
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
"AIImages.Info.Traits".Translate() + ":"
|
"AIImages.Info.Traits".Translate() + ":"
|
||||||
);
|
);
|
||||||
contentHeight += lineHeight;
|
contentY += lineHeight + 2f;
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
Text.Font = GameFont.Tiny;
|
||||||
var traitLabels = pawn.story.traits.allTraits.Select(trait => trait.LabelCap);
|
var traitLabels = pawn.story.traits.allTraits.Select(trait => trait.LabelCap);
|
||||||
foreach (var traitLabel in traitLabels)
|
foreach (var traitLabel in traitLabels)
|
||||||
{
|
{
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(
|
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
||||||
indent * 2,
|
|
||||||
contentHeight,
|
|
||||||
parentRect.width - indent * 3,
|
|
||||||
lineHeight
|
|
||||||
),
|
|
||||||
"• " + traitLabel
|
"• " + traitLabel
|
||||||
);
|
);
|
||||||
contentHeight += lineHeight;
|
contentY += lineHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,13 +509,13 @@ namespace AIImages
|
|||||||
var apparel = pawn.apparel?.WornApparel;
|
var apparel = pawn.apparel?.WornApparel;
|
||||||
if (apparel != null && apparel.Any())
|
if (apparel != null && apparel.Any())
|
||||||
{
|
{
|
||||||
contentHeight += 10f;
|
contentY += 15f;
|
||||||
Text.Font = GameFont.Small;
|
Text.Font = GameFont.Small;
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(indent, contentHeight, parentRect.width - indent * 2, lineHeight),
|
new Rect(parentRect.x + 5f, contentY, parentRect.width - 10f, lineHeight),
|
||||||
"AIImages.Info.Apparel".Translate() + ":"
|
"AIImages.Info.Apparel".Translate() + ":"
|
||||||
);
|
);
|
||||||
contentHeight += lineHeight;
|
contentY += lineHeight + 2f;
|
||||||
|
|
||||||
Text.Font = GameFont.Tiny;
|
Text.Font = GameFont.Tiny;
|
||||||
foreach (var item in apparel)
|
foreach (var item in apparel)
|
||||||
@@ -512,44 +524,33 @@ namespace AIImages
|
|||||||
item.DrawColor
|
item.DrawColor
|
||||||
);
|
);
|
||||||
string apparelLabel = $"• {colorDesc} {item.def.label}";
|
string apparelLabel = $"• {colorDesc} {item.def.label}";
|
||||||
float apparelHeight = Text.CalcHeight(
|
float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
|
||||||
apparelLabel,
|
|
||||||
parentRect.width - indent * 3
|
|
||||||
);
|
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(
|
new Rect(
|
||||||
indent * 2,
|
parentRect.x + 15f,
|
||||||
contentHeight,
|
contentY,
|
||||||
parentRect.width - indent * 3,
|
parentRect.width - 25f,
|
||||||
apparelHeight
|
apparelHeight
|
||||||
),
|
),
|
||||||
apparelLabel
|
apparelLabel
|
||||||
);
|
);
|
||||||
contentHeight += apparelHeight;
|
contentY += apparelHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contentHeight + 10f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawRightColumn(Rect rect)
|
private void DrawRightColumn(Rect rect)
|
||||||
{
|
{
|
||||||
// Рассчитываем высоту контента для скролла
|
float curY = rect.y;
|
||||||
float contentHeight = CalculateRightColumnHeight();
|
|
||||||
Rect scrollViewRect = new Rect(0f, 0f, rect.width - 20f, contentHeight);
|
|
||||||
|
|
||||||
Widgets.BeginScrollView(rect, ref rightColumnScrollPosition, scrollViewRect);
|
curY = DrawImagePreview(rect, curY);
|
||||||
|
curY = DrawGenerationStatus(rect, curY);
|
||||||
float curY = 0f;
|
curY = DrawProgressBar(rect, curY);
|
||||||
|
curY = DrawGenerationButton(rect, curY);
|
||||||
curY = DrawImagePreview(scrollViewRect, curY);
|
|
||||||
curY = DrawGenerationStatus(scrollViewRect, curY);
|
|
||||||
curY = DrawProgressBar(scrollViewRect, curY);
|
|
||||||
curY = DrawGenerationButton(scrollViewRect, curY);
|
|
||||||
|
|
||||||
// Сворачиваемая секция с позитивным промптом
|
// Сворачиваемая секция с позитивным промптом
|
||||||
curY = DrawPromptSection(
|
curY = DrawPromptSection(
|
||||||
scrollViewRect,
|
rect,
|
||||||
curY,
|
curY,
|
||||||
"AIImages.Prompt.PositiveTitle".Translate(),
|
"AIImages.Prompt.PositiveTitle".Translate(),
|
||||||
ref showPositivePrompt,
|
ref showPositivePrompt,
|
||||||
@@ -566,7 +567,7 @@ namespace AIImages
|
|||||||
|
|
||||||
// Сворачиваемая секция с негативным промптом
|
// Сворачиваемая секция с негативным промптом
|
||||||
curY = DrawPromptSection(
|
curY = DrawPromptSection(
|
||||||
scrollViewRect,
|
rect,
|
||||||
curY,
|
curY,
|
||||||
"AIImages.Prompt.NegativeTitle".Translate(),
|
"AIImages.Prompt.NegativeTitle".Translate(),
|
||||||
ref showNegativePrompt,
|
ref showNegativePrompt,
|
||||||
@@ -580,7 +581,7 @@ namespace AIImages
|
|||||||
// Кнопка обновления данных
|
// Кнопка обновления данных
|
||||||
if (
|
if (
|
||||||
Widgets.ButtonText(
|
Widgets.ButtonText(
|
||||||
new Rect(0f, curY, scrollViewRect.width, 30f),
|
new Rect(rect.x, curY, rect.width, 30f),
|
||||||
"AIImages.Window.Refresh".Translate()
|
"AIImages.Window.Refresh".Translate()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -594,13 +595,11 @@ namespace AIImages
|
|||||||
curY += 35f;
|
curY += 35f;
|
||||||
GUI.color = new Color(0f, 1f, 0f, copiedMessageTime / 2f);
|
GUI.color = new Color(0f, 1f, 0f, copiedMessageTime / 2f);
|
||||||
Widgets.Label(
|
Widgets.Label(
|
||||||
new Rect(0f, curY, scrollViewRect.width, 25f),
|
new Rect(rect.x, curY, rect.width, 25f),
|
||||||
"AIImages.Prompt.Copied".Translate()
|
"AIImages.Prompt.Copied".Translate()
|
||||||
);
|
);
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.EndScrollView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float CalculateContentHeight()
|
private float CalculateContentHeight()
|
||||||
@@ -610,26 +609,38 @@ namespace AIImages
|
|||||||
// Портрет персонажа (если есть)
|
// Портрет персонажа (если есть)
|
||||||
if (generatedImage != null)
|
if (generatedImage != null)
|
||||||
{
|
{
|
||||||
float portraitSize = Mathf.Min(400f, 200f);
|
float portraitSize = 250f; // Максимальный размер портрета
|
||||||
height += portraitSize + 15f;
|
height += portraitSize + 15f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Заголовок "Внешность"
|
// Заголовок "Информация о персонаже"
|
||||||
height += 35f;
|
height += 35f;
|
||||||
|
|
||||||
// Текст внешности
|
|
||||||
string appearanceText = pawnDescriptionService.GetAppearanceDescription(pawn);
|
|
||||||
height += Text.CalcHeight(appearanceText, 400f) + 20f;
|
|
||||||
|
|
||||||
// Разделитель
|
// Разделитель
|
||||||
height += 15f;
|
height += 10f;
|
||||||
|
|
||||||
// Заголовок "Одежда"
|
// Базовая информация (6 строк по 22px)
|
||||||
height += 35f;
|
height += 6 * 22f;
|
||||||
|
|
||||||
// Текст одежды
|
// Черты характера (если есть)
|
||||||
string apparelText = pawnDescriptionService.GetApparelDescription(pawn);
|
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
||||||
height += Text.CalcHeight(apparelText, 400f) + 20f;
|
{
|
||||||
|
height += 15f; // Отступ
|
||||||
|
height += 22f; // Заголовок "Черты характера"
|
||||||
|
height += 2f; // Отступ
|
||||||
|
height += pawn.story.traits.allTraits.Count * 22f; // Каждая черта
|
||||||
|
}
|
||||||
|
|
||||||
|
// Одежда (если есть)
|
||||||
|
var apparel = pawn.apparel?.WornApparel;
|
||||||
|
if (apparel != null && apparel.Any())
|
||||||
|
{
|
||||||
|
height += 15f; // Отступ
|
||||||
|
height += 22f; // Заголовок "Одежда"
|
||||||
|
height += 2f; // Отступ
|
||||||
|
// Примерно по 22-30px на предмет одежды
|
||||||
|
height += apparel.Count * 26f;
|
||||||
|
}
|
||||||
|
|
||||||
// Дополнительный отступ
|
// Дополнительный отступ
|
||||||
height += 50f;
|
height += 50f;
|
||||||
@@ -644,11 +655,11 @@ namespace AIImages
|
|||||||
// Превью изображения
|
// Превью изображения
|
||||||
if (generatedImage != null)
|
if (generatedImage != null)
|
||||||
{
|
{
|
||||||
height += 200f + 10f;
|
height += 410f; // 400f изображение + 10f отступ
|
||||||
}
|
}
|
||||||
else if (!isGenerating)
|
else if (!isGenerating)
|
||||||
{
|
{
|
||||||
height += 100f + 10f;
|
height += 310f; // 300f placeholder + 10f отступ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Статус генерации
|
// Статус генерации
|
||||||
@@ -667,71 +678,55 @@ namespace AIImages
|
|||||||
height += 40f;
|
height += 40f;
|
||||||
|
|
||||||
// Позитивный промпт
|
// Позитивный промпт
|
||||||
height += 35f; // Заголовок
|
height += 36f; // Заголовок (32f + 4f отступ)
|
||||||
height += 100f + 10f; // Бокс
|
if (showPositivePrompt)
|
||||||
|
{
|
||||||
|
height += 140f; // Бокс развернут (120f + 10f отступ + запас)
|
||||||
|
}
|
||||||
|
height += 5f; // Отступ между промптами
|
||||||
|
|
||||||
// Негативный промпт
|
// Негативный промпт
|
||||||
height += 35f; // Заголовок
|
height += 36f; // Заголовок (32f + 4f отступ)
|
||||||
height += 100f + 10f; // Бокс
|
if (showNegativePrompt)
|
||||||
|
{
|
||||||
// Кнопки копирования
|
height += 140f; // Бокс развернут (120f + 10f отступ + запас)
|
||||||
height += 35f;
|
}
|
||||||
|
height += 10f; // Отступ после промптов
|
||||||
|
|
||||||
// Кнопка обновления
|
// Кнопка обновления
|
||||||
height += 35f;
|
height += 40f; // Увеличено с 35f до 40f
|
||||||
|
|
||||||
// Сообщение о копировании
|
// Сообщение о копировании
|
||||||
if (copiedMessageTime > 0f)
|
if (copiedMessageTime > 0f)
|
||||||
{
|
{
|
||||||
height += 30f;
|
height += 40f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return height + 50f; // Дополнительный отступ
|
return height + 100f; // Увеличен дополнительный отступ снизу
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private float CalculateTotalContentHeight()
|
||||||
/// Отрисовывает сворачиваемую секцию с заголовком и содержимым
|
|
||||||
/// </summary>
|
|
||||||
private void DrawCollapsibleSection(
|
|
||||||
Rect parentRect,
|
|
||||||
float startY,
|
|
||||||
string title,
|
|
||||||
ref bool expanded,
|
|
||||||
System.Func<float> drawContentFunc
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
float curY = startY;
|
float height = 0f;
|
||||||
float headerHeight = 32f;
|
|
||||||
|
|
||||||
// Рисуем заголовок с фоном
|
// Заголовок и имя пешки
|
||||||
Rect headerRect = new Rect(0f, curY, parentRect.width, headerHeight);
|
height += 45f + 40f;
|
||||||
Widgets.DrawBoxSolid(headerRect, new Color(0.25f, 0.25f, 0.25f, 0.8f));
|
|
||||||
Widgets.DrawBox(headerRect);
|
|
||||||
|
|
||||||
// Иконка раскрытия (треугольник)
|
// Разделитель
|
||||||
string icon = expanded ? "▼" : "►";
|
height += 10f;
|
||||||
Text.Font = GameFont.Small;
|
|
||||||
Widgets.Label(new Rect(8f, curY + 6f, 20f, headerHeight), icon);
|
|
||||||
|
|
||||||
// Заголовок
|
// Высота колонок (берем большую)
|
||||||
Text.Font = GameFont.Small;
|
float columnHeight = Mathf.Max(CalculateContentHeight(), CalculateRightColumnHeight());
|
||||||
Widgets.Label(new Rect(30f, curY + 6f, parentRect.width - 40f, headerHeight), title);
|
height += columnHeight;
|
||||||
|
|
||||||
// Клик для раскрытия/сворачивания
|
// Дополнительный отступ снизу
|
||||||
if (Widgets.ButtonInvisible(headerRect))
|
height += 30f;
|
||||||
{
|
|
||||||
expanded = !expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Рисуем содержимое если развернуто
|
return height;
|
||||||
if (expanded)
|
|
||||||
{
|
|
||||||
drawContentFunc();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Отрисовывает секцию с промптом
|
/// /// Отрисовывает секцию с промптом
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private float DrawPromptSection(
|
private float DrawPromptSection(
|
||||||
Rect parentRect,
|
Rect parentRect,
|
||||||
@@ -750,20 +745,28 @@ namespace AIImages
|
|||||||
string prompt = getPromptFunc();
|
string prompt = getPromptFunc();
|
||||||
|
|
||||||
// Рисуем заголовок с фоном
|
// Рисуем заголовок с фоном
|
||||||
Rect headerRect = new Rect(0f, curY, parentRect.width, headerHeight);
|
Rect headerRect = new Rect(parentRect.x, curY, parentRect.width, headerHeight);
|
||||||
Widgets.DrawBoxSolid(headerRect, new Color(0.25f, 0.25f, 0.25f, 0.8f));
|
Widgets.DrawBoxSolid(headerRect, new Color(0.25f, 0.25f, 0.25f, 0.8f));
|
||||||
Widgets.DrawBox(headerRect);
|
Widgets.DrawBox(headerRect);
|
||||||
|
|
||||||
// Иконка раскрытия
|
// Иконка раскрытия
|
||||||
string icon = expanded ? "▼" : "►";
|
string icon = expanded ? "▼" : "►";
|
||||||
Text.Font = GameFont.Small;
|
Text.Font = GameFont.Small;
|
||||||
Widgets.Label(new Rect(8f, curY + 6f, 20f, headerHeight), icon);
|
Widgets.Label(new Rect(parentRect.x + 8f, curY + 6f, 20f, headerHeight), icon);
|
||||||
|
|
||||||
// Заголовок
|
// Заголовок
|
||||||
Widgets.Label(new Rect(30f, curY + 6f, parentRect.width - 80f, headerHeight), title);
|
Widgets.Label(
|
||||||
|
new Rect(parentRect.x + 30f, curY + 6f, parentRect.width - 110f, headerHeight),
|
||||||
|
title
|
||||||
|
);
|
||||||
|
|
||||||
// Кнопка копирования в заголовке
|
// Кнопка копирования в заголовке (увеличена ширина)
|
||||||
Rect copyButtonRect = new Rect(parentRect.width - 70f, curY + 4f, 65f, 24f);
|
Rect copyButtonRect = new Rect(
|
||||||
|
parentRect.x + parentRect.width - 100f,
|
||||||
|
curY + 4f,
|
||||||
|
95f,
|
||||||
|
24f
|
||||||
|
);
|
||||||
if (Widgets.ButtonText(copyButtonRect, "📋 " + "AIImages.Copy".Translate()))
|
if (Widgets.ButtonText(copyButtonRect, "📋 " + "AIImages.Copy".Translate()))
|
||||||
{
|
{
|
||||||
GUIUtility.systemCopyBuffer = prompt;
|
GUIUtility.systemCopyBuffer = prompt;
|
||||||
@@ -771,7 +774,12 @@ namespace AIImages
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Клик на остальной области для раскрытия/сворачивания
|
// Клик на остальной области для раскрытия/сворачивания
|
||||||
Rect clickableHeaderRect = new Rect(0f, curY, parentRect.width - 75f, headerHeight);
|
Rect clickableHeaderRect = new Rect(
|
||||||
|
parentRect.x,
|
||||||
|
curY,
|
||||||
|
parentRect.width - 105f,
|
||||||
|
headerHeight
|
||||||
|
);
|
||||||
if (Widgets.ButtonInvisible(clickableHeaderRect))
|
if (Widgets.ButtonInvisible(clickableHeaderRect))
|
||||||
{
|
{
|
||||||
expanded = !expanded;
|
expanded = !expanded;
|
||||||
@@ -786,7 +794,12 @@ namespace AIImages
|
|||||||
Text.Font = GameFont.Tiny;
|
Text.Font = GameFont.Tiny;
|
||||||
float actualPromptHeight = Text.CalcHeight(prompt, parentRect.width - 20f);
|
float actualPromptHeight = Text.CalcHeight(prompt, parentRect.width - 20f);
|
||||||
|
|
||||||
Rect promptOuterRect = new Rect(0f, curY, parentRect.width, promptBoxHeight);
|
Rect promptOuterRect = new Rect(
|
||||||
|
parentRect.x,
|
||||||
|
curY,
|
||||||
|
parentRect.width,
|
||||||
|
promptBoxHeight
|
||||||
|
);
|
||||||
Rect promptViewRect = new Rect(0f, 0f, parentRect.width - 20f, actualPromptHeight);
|
Rect promptViewRect = new Rect(0f, 0f, parentRect.width - 20f, actualPromptHeight);
|
||||||
|
|
||||||
// Рисуем фон
|
// Рисуем фон
|
||||||
@@ -827,7 +840,7 @@ namespace AIImages
|
|||||||
float imageSize = Mathf.Min(rect.width, 400f);
|
float imageSize = Mathf.Min(rect.width, 400f);
|
||||||
Rect imageRect = new Rect(
|
Rect imageRect = new Rect(
|
||||||
rect.x + (rect.width - imageSize) / 2f,
|
rect.x + (rect.width - imageSize) / 2f,
|
||||||
rect.y + curY,
|
curY,
|
||||||
imageSize,
|
imageSize,
|
||||||
imageSize
|
imageSize
|
||||||
);
|
);
|
||||||
@@ -838,7 +851,7 @@ namespace AIImages
|
|||||||
float placeholderSize = Mathf.Min(rect.width, 300f);
|
float placeholderSize = Mathf.Min(rect.width, 300f);
|
||||||
Rect placeholderRect = new Rect(
|
Rect placeholderRect = new Rect(
|
||||||
rect.x + (rect.width - placeholderSize) / 2f,
|
rect.x + (rect.width - placeholderSize) / 2f,
|
||||||
rect.y + curY,
|
curY,
|
||||||
placeholderSize,
|
placeholderSize,
|
||||||
placeholderSize
|
placeholderSize
|
||||||
);
|
);
|
||||||
@@ -856,10 +869,7 @@ namespace AIImages
|
|||||||
|
|
||||||
Text.Font = GameFont.Small;
|
Text.Font = GameFont.Small;
|
||||||
float statusHeight = Text.CalcHeight(generationStatus, rect.width);
|
float statusHeight = Text.CalcHeight(generationStatus, rect.width);
|
||||||
Widgets.Label(
|
Widgets.Label(new Rect(rect.x, curY, rect.width, statusHeight), generationStatus);
|
||||||
new Rect(rect.x, rect.y + curY, rect.width, statusHeight),
|
|
||||||
generationStatus
|
|
||||||
);
|
|
||||||
return curY + statusHeight + 10f;
|
return curY + statusHeight + 10f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,7 +878,7 @@ namespace AIImages
|
|||||||
if (!isGenerating || generationProgress <= 0.0)
|
if (!isGenerating || generationProgress <= 0.0)
|
||||||
return curY;
|
return curY;
|
||||||
|
|
||||||
Rect progressBarRect = new Rect(rect.x, rect.y + curY, rect.width, 24f);
|
Rect progressBarRect = new Rect(rect.x, curY, rect.width, 24f);
|
||||||
|
|
||||||
string progressText;
|
string progressText;
|
||||||
if (totalSteps > 0)
|
if (totalSteps > 0)
|
||||||
@@ -900,7 +910,7 @@ namespace AIImages
|
|||||||
? "AIImages.Generation.Cancel".Translate()
|
? "AIImages.Generation.Cancel".Translate()
|
||||||
: "AIImages.Generation.Generate".Translate();
|
: "AIImages.Generation.Generate".Translate();
|
||||||
|
|
||||||
if (Widgets.ButtonText(new Rect(rect.x, rect.y + curY, rect.width, 35f), buttonLabel))
|
if (Widgets.ButtonText(new Rect(rect.x, curY, rect.width, 35f), buttonLabel))
|
||||||
{
|
{
|
||||||
if (isGenerating)
|
if (isGenerating)
|
||||||
CancelGeneration();
|
CancelGeneration();
|
||||||
|
|||||||
Reference in New Issue
Block a user