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:
@@ -59,14 +59,19 @@ namespace AIImages.Services
|
||||
prompt.Append(", ");
|
||||
}
|
||||
|
||||
// 3. Тип кадра - автоматически добавляем "portrait" для генерации персонажей
|
||||
prompt.Append("portrait, head and shoulders of ");
|
||||
// 3. Тип кадра
|
||||
prompt.Append("portrait, ");
|
||||
|
||||
// 4. Базовое описание (возраст и пол)
|
||||
prompt.Append(GetAgeAndGenderDescription(appearanceData));
|
||||
// 4. Пол персонажа (в формате anime/SD теги)
|
||||
string genderTag = appearanceData.Gender == Gender.Female ? "1girl" : "1boy";
|
||||
prompt.Append(genderTag);
|
||||
prompt.Append(", ");
|
||||
|
||||
// 5. Тип тела
|
||||
// 5. Точный возраст
|
||||
prompt.Append($"{appearanceData.Age} y.o.");
|
||||
prompt.Append(", ");
|
||||
|
||||
// 6. Тип тела
|
||||
string bodyType = GetBodyTypeDescription(appearanceData.BodyType);
|
||||
if (!string.IsNullOrEmpty(bodyType))
|
||||
{
|
||||
@@ -74,14 +79,14 @@ namespace AIImages.Services
|
||||
prompt.Append(", ");
|
||||
}
|
||||
|
||||
// 6. Цвет кожи
|
||||
// 7. Цвет кожи
|
||||
string skinTone = ColorDescriptionService.GetSkinToneDescription(
|
||||
appearanceData.SkinColor
|
||||
);
|
||||
prompt.Append(skinTone);
|
||||
prompt.Append(", ");
|
||||
|
||||
// 7. Волосы
|
||||
// 8. Волосы
|
||||
string hairDescription = GetHairDescription(appearanceData);
|
||||
if (!string.IsNullOrEmpty(hairDescription))
|
||||
{
|
||||
@@ -89,7 +94,7 @@ namespace AIImages.Services
|
||||
prompt.Append(", ");
|
||||
}
|
||||
|
||||
// 8. Настроение и выражение на основе черт характера
|
||||
// 9. Настроение и выражение на основе черт характера
|
||||
string moodDescription = GetMoodFromTraits(appearanceData.Traits);
|
||||
if (!string.IsNullOrEmpty(moodDescription))
|
||||
{
|
||||
@@ -97,7 +102,7 @@ namespace AIImages.Services
|
||||
prompt.Append(", ");
|
||||
}
|
||||
|
||||
// 9. Одежда
|
||||
// 10. Одежда
|
||||
string apparelDescription = GetApparelDescription(appearanceData.Apparel);
|
||||
if (!string.IsNullOrEmpty(apparelDescription))
|
||||
{
|
||||
@@ -105,7 +110,7 @@ namespace AIImages.Services
|
||||
prompt.Append(", ");
|
||||
}
|
||||
|
||||
// 10. Качественные теги
|
||||
// 11. Качественные теги
|
||||
prompt.Append(GetQualityTags(settings.ArtStyleDefName));
|
||||
|
||||
return prompt.ToString().Trim().TrimEnd(',');
|
||||
@@ -179,27 +184,6 @@ namespace AIImages.Services
|
||||
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)
|
||||
{
|
||||
if (string.IsNullOrEmpty(bodyType))
|
||||
|
||||
@@ -69,16 +69,14 @@ namespace AIImages
|
||||
|
||||
public override Vector2 InitialSize => new Vector2(900f, 800f);
|
||||
|
||||
private Vector2 scrollPosition = Vector2.zero;
|
||||
private Vector2 rightColumnScrollPosition = Vector2.zero;
|
||||
private Vector2 mainScrollPosition = Vector2.zero;
|
||||
private Vector2 promptScrollPosition = Vector2.zero;
|
||||
private Vector2 negativePromptScrollPosition = Vector2.zero;
|
||||
private float copiedMessageTime = 0f;
|
||||
|
||||
// Состояние сворачиваемых секций
|
||||
// Состояние сворачиваемых секций промптов
|
||||
private bool showPositivePrompt = false;
|
||||
private bool showNegativePrompt = false;
|
||||
private bool showCharacterInfo = true;
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет данные персонажа
|
||||
@@ -342,12 +340,18 @@ namespace AIImages
|
||||
|
||||
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;
|
||||
|
||||
// Заголовок
|
||||
Text.Font = GameFont.Medium;
|
||||
Widgets.Label(
|
||||
new Rect(0f, curY, inRect.width, 40f),
|
||||
new Rect(0f, curY, viewRect.width, 40f),
|
||||
"AIImages.Window.Title".Translate()
|
||||
);
|
||||
curY += 45f;
|
||||
@@ -355,22 +359,25 @@ namespace AIImages
|
||||
// Имя пешки
|
||||
Text.Font = GameFont.Small;
|
||||
Widgets.Label(
|
||||
new Rect(0f, curY, inRect.width, 30f),
|
||||
new Rect(0f, curY, viewRect.width, 30f),
|
||||
"AIImages.Window.PawnLabel".Translate(pawn.NameShortColored.Resolve())
|
||||
);
|
||||
curY += 40f;
|
||||
|
||||
// Разделитель
|
||||
Widgets.DrawLineHorizontal(0f, curY, inRect.width);
|
||||
Widgets.DrawLineHorizontal(0f, curY, viewRect.width);
|
||||
curY += 10f;
|
||||
|
||||
// Разделяем на две колонки: левая - информация, правая - изображение
|
||||
float leftColumnWidth = inRect.width * 0.55f;
|
||||
float rightColumnWidth = inRect.width * 0.42f;
|
||||
float columnGap = inRect.width * 0.03f;
|
||||
float leftColumnWidth = viewRect.width * 0.35f;
|
||||
float rightColumnWidth = viewRect.width * 0.62f;
|
||||
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);
|
||||
|
||||
// Правая колонка - превью и управление
|
||||
@@ -378,24 +385,23 @@ namespace AIImages
|
||||
leftColumnWidth + columnGap,
|
||||
curY,
|
||||
rightColumnWidth,
|
||||
inRect.height - curY
|
||||
columnHeight
|
||||
);
|
||||
DrawRightColumn(rightColumnRect);
|
||||
|
||||
Widgets.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawLeftColumn(Rect rect)
|
||||
{
|
||||
Rect scrollViewRect = new Rect(0f, 0f, rect.width - 20f, CalculateContentHeight());
|
||||
Widgets.BeginScrollView(rect, ref scrollPosition, scrollViewRect);
|
||||
|
||||
float contentY = 0f;
|
||||
float contentY = rect.y;
|
||||
|
||||
// Портрет персонажа (если есть)
|
||||
if (generatedImage != null)
|
||||
{
|
||||
float portraitSize = Mathf.Min(scrollViewRect.width - 20f, 200f);
|
||||
float portraitSize = Mathf.Min(rect.width, 250f);
|
||||
Rect portraitRect = new Rect(
|
||||
(scrollViewRect.width - portraitSize) / 2f,
|
||||
rect.x + (rect.width - portraitSize) / 2f,
|
||||
contentY,
|
||||
portraitSize,
|
||||
portraitSize
|
||||
@@ -404,29 +410,34 @@ namespace AIImages
|
||||
// Рамка вокруг портрета
|
||||
Widgets.DrawBox(portraitRect);
|
||||
GUI.DrawTexture(portraitRect.ContractedBy(2f), generatedImage);
|
||||
contentY += portraitSize + 20f;
|
||||
contentY += portraitSize + 15f;
|
||||
}
|
||||
|
||||
// Сворачиваемая секция "Информация о персонаже"
|
||||
DrawCollapsibleSection(
|
||||
scrollViewRect,
|
||||
contentY,
|
||||
"AIImages.CharacterInfo.Title".Translate(),
|
||||
ref showCharacterInfo,
|
||||
() => DrawCharacterInfoContent(scrollViewRect)
|
||||
// Заголовок секции
|
||||
Text.Font = GameFont.Medium;
|
||||
Widgets.Label(
|
||||
new Rect(rect.x, contentY, rect.width, 30f),
|
||||
"AIImages.CharacterInfo.Title".Translate()
|
||||
);
|
||||
contentY += 35f;
|
||||
|
||||
Widgets.EndScrollView();
|
||||
// Разделитель
|
||||
Widgets.DrawLineHorizontal(rect.x, contentY, rect.width);
|
||||
contentY += 10f;
|
||||
|
||||
// Информация о персонаже
|
||||
DrawCharacterInfoContent(rect, contentY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовывает информацию о персонаже в компактном виде
|
||||
/// </summary>
|
||||
private float DrawCharacterInfoContent(Rect parentRect)
|
||||
private void DrawCharacterInfoContent(Rect parentRect, float startY)
|
||||
{
|
||||
float contentHeight = 0f;
|
||||
float lineHeight = 24f;
|
||||
float indent = 10f;
|
||||
float contentY = startY;
|
||||
float lineHeight = 22f;
|
||||
float labelWidth = parentRect.width * 0.45f;
|
||||
float valueWidth = parentRect.width * 0.50f;
|
||||
|
||||
Text.Font = GameFont.Tiny;
|
||||
|
||||
@@ -449,47 +460,48 @@ namespace AIImages
|
||||
|
||||
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(
|
||||
new Rect(indent, contentHeight, parentRect.width * 0.4f, lineHeight),
|
||||
new Rect(parentRect.x + 5f, contentY, labelWidth, lineHeight),
|
||||
label + ":"
|
||||
);
|
||||
Widgets.Label(
|
||||
new Rect(
|
||||
parentRect.width * 0.42f,
|
||||
contentHeight,
|
||||
parentRect.width * 0.55f,
|
||||
lineHeight
|
||||
),
|
||||
new Rect(parentRect.x + labelWidth + 10f, contentY, valueWidth, lineHeight),
|
||||
value
|
||||
);
|
||||
contentHeight += lineHeight;
|
||||
contentY += lineHeight;
|
||||
}
|
||||
|
||||
// Черты характера
|
||||
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
||||
{
|
||||
contentHeight += 10f;
|
||||
contentY += 15f;
|
||||
Text.Font = GameFont.Small;
|
||||
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() + ":"
|
||||
);
|
||||
contentHeight += lineHeight;
|
||||
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(
|
||||
indent * 2,
|
||||
contentHeight,
|
||||
parentRect.width - indent * 3,
|
||||
lineHeight
|
||||
),
|
||||
new Rect(parentRect.x + 15f, contentY, parentRect.width - 20f, lineHeight),
|
||||
"• " + traitLabel
|
||||
);
|
||||
contentHeight += lineHeight;
|
||||
contentY += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,13 +509,13 @@ namespace AIImages
|
||||
var apparel = pawn.apparel?.WornApparel;
|
||||
if (apparel != null && apparel.Any())
|
||||
{
|
||||
contentHeight += 10f;
|
||||
contentY += 15f;
|
||||
Text.Font = GameFont.Small;
|
||||
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() + ":"
|
||||
);
|
||||
contentHeight += lineHeight;
|
||||
contentY += lineHeight + 2f;
|
||||
|
||||
Text.Font = GameFont.Tiny;
|
||||
foreach (var item in apparel)
|
||||
@@ -512,44 +524,33 @@ namespace AIImages
|
||||
item.DrawColor
|
||||
);
|
||||
string apparelLabel = $"• {colorDesc} {item.def.label}";
|
||||
float apparelHeight = Text.CalcHeight(
|
||||
apparelLabel,
|
||||
parentRect.width - indent * 3
|
||||
);
|
||||
float apparelHeight = Text.CalcHeight(apparelLabel, parentRect.width - 25f);
|
||||
Widgets.Label(
|
||||
new Rect(
|
||||
indent * 2,
|
||||
contentHeight,
|
||||
parentRect.width - indent * 3,
|
||||
parentRect.x + 15f,
|
||||
contentY,
|
||||
parentRect.width - 25f,
|
||||
apparelHeight
|
||||
),
|
||||
apparelLabel
|
||||
);
|
||||
contentHeight += apparelHeight;
|
||||
contentY += apparelHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return contentHeight + 10f;
|
||||
}
|
||||
|
||||
private void DrawRightColumn(Rect rect)
|
||||
{
|
||||
// Рассчитываем высоту контента для скролла
|
||||
float contentHeight = CalculateRightColumnHeight();
|
||||
Rect scrollViewRect = new Rect(0f, 0f, rect.width - 20f, contentHeight);
|
||||
float curY = rect.y;
|
||||
|
||||
Widgets.BeginScrollView(rect, ref rightColumnScrollPosition, scrollViewRect);
|
||||
|
||||
float curY = 0f;
|
||||
|
||||
curY = DrawImagePreview(scrollViewRect, curY);
|
||||
curY = DrawGenerationStatus(scrollViewRect, curY);
|
||||
curY = DrawProgressBar(scrollViewRect, curY);
|
||||
curY = DrawGenerationButton(scrollViewRect, curY);
|
||||
curY = DrawImagePreview(rect, curY);
|
||||
curY = DrawGenerationStatus(rect, curY);
|
||||
curY = DrawProgressBar(rect, curY);
|
||||
curY = DrawGenerationButton(rect, curY);
|
||||
|
||||
// Сворачиваемая секция с позитивным промптом
|
||||
curY = DrawPromptSection(
|
||||
scrollViewRect,
|
||||
rect,
|
||||
curY,
|
||||
"AIImages.Prompt.PositiveTitle".Translate(),
|
||||
ref showPositivePrompt,
|
||||
@@ -566,7 +567,7 @@ namespace AIImages
|
||||
|
||||
// Сворачиваемая секция с негативным промптом
|
||||
curY = DrawPromptSection(
|
||||
scrollViewRect,
|
||||
rect,
|
||||
curY,
|
||||
"AIImages.Prompt.NegativeTitle".Translate(),
|
||||
ref showNegativePrompt,
|
||||
@@ -580,7 +581,7 @@ namespace AIImages
|
||||
// Кнопка обновления данных
|
||||
if (
|
||||
Widgets.ButtonText(
|
||||
new Rect(0f, curY, scrollViewRect.width, 30f),
|
||||
new Rect(rect.x, curY, rect.width, 30f),
|
||||
"AIImages.Window.Refresh".Translate()
|
||||
)
|
||||
)
|
||||
@@ -594,13 +595,11 @@ namespace AIImages
|
||||
curY += 35f;
|
||||
GUI.color = new Color(0f, 1f, 0f, copiedMessageTime / 2f);
|
||||
Widgets.Label(
|
||||
new Rect(0f, curY, scrollViewRect.width, 25f),
|
||||
new Rect(rect.x, curY, rect.width, 25f),
|
||||
"AIImages.Prompt.Copied".Translate()
|
||||
);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
Widgets.EndScrollView();
|
||||
}
|
||||
|
||||
private float CalculateContentHeight()
|
||||
@@ -610,26 +609,38 @@ namespace AIImages
|
||||
// Портрет персонажа (если есть)
|
||||
if (generatedImage != null)
|
||||
{
|
||||
float portraitSize = Mathf.Min(400f, 200f);
|
||||
float portraitSize = 250f; // Максимальный размер портрета
|
||||
height += portraitSize + 15f;
|
||||
}
|
||||
|
||||
// Заголовок "Внешность"
|
||||
// Заголовок "Информация о персонаже"
|
||||
height += 35f;
|
||||
|
||||
// Текст внешности
|
||||
string appearanceText = pawnDescriptionService.GetAppearanceDescription(pawn);
|
||||
height += Text.CalcHeight(appearanceText, 400f) + 20f;
|
||||
|
||||
// Разделитель
|
||||
height += 15f;
|
||||
height += 10f;
|
||||
|
||||
// Заголовок "Одежда"
|
||||
height += 35f;
|
||||
// Базовая информация (6 строк по 22px)
|
||||
height += 6 * 22f;
|
||||
|
||||
// Текст одежды
|
||||
string apparelText = pawnDescriptionService.GetApparelDescription(pawn);
|
||||
height += Text.CalcHeight(apparelText, 400f) + 20f;
|
||||
// Черты характера (если есть)
|
||||
if (pawn.story?.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
||||
{
|
||||
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;
|
||||
@@ -644,11 +655,11 @@ namespace AIImages
|
||||
// Превью изображения
|
||||
if (generatedImage != null)
|
||||
{
|
||||
height += 200f + 10f;
|
||||
height += 410f; // 400f изображение + 10f отступ
|
||||
}
|
||||
else if (!isGenerating)
|
||||
{
|
||||
height += 100f + 10f;
|
||||
height += 310f; // 300f placeholder + 10f отступ
|
||||
}
|
||||
|
||||
// Статус генерации
|
||||
@@ -667,71 +678,55 @@ namespace AIImages
|
||||
height += 40f;
|
||||
|
||||
// Позитивный промпт
|
||||
height += 35f; // Заголовок
|
||||
height += 100f + 10f; // Бокс
|
||||
height += 36f; // Заголовок (32f + 4f отступ)
|
||||
if (showPositivePrompt)
|
||||
{
|
||||
height += 140f; // Бокс развернут (120f + 10f отступ + запас)
|
||||
}
|
||||
height += 5f; // Отступ между промптами
|
||||
|
||||
// Негативный промпт
|
||||
height += 35f; // Заголовок
|
||||
height += 100f + 10f; // Бокс
|
||||
|
||||
// Кнопки копирования
|
||||
height += 35f;
|
||||
height += 36f; // Заголовок (32f + 4f отступ)
|
||||
if (showNegativePrompt)
|
||||
{
|
||||
height += 140f; // Бокс развернут (120f + 10f отступ + запас)
|
||||
}
|
||||
height += 10f; // Отступ после промптов
|
||||
|
||||
// Кнопка обновления
|
||||
height += 35f;
|
||||
height += 40f; // Увеличено с 35f до 40f
|
||||
|
||||
// Сообщение о копировании
|
||||
if (copiedMessageTime > 0f)
|
||||
{
|
||||
height += 30f;
|
||||
height += 40f;
|
||||
}
|
||||
|
||||
return height + 50f; // Дополнительный отступ
|
||||
return height + 100f; // Увеличен дополнительный отступ снизу
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовывает сворачиваемую секцию с заголовком и содержимым
|
||||
/// </summary>
|
||||
private void DrawCollapsibleSection(
|
||||
Rect parentRect,
|
||||
float startY,
|
||||
string title,
|
||||
ref bool expanded,
|
||||
System.Func<float> drawContentFunc
|
||||
)
|
||||
private float CalculateTotalContentHeight()
|
||||
{
|
||||
float curY = startY;
|
||||
float headerHeight = 32f;
|
||||
float height = 0f;
|
||||
|
||||
// Рисуем заголовок с фоном
|
||||
Rect headerRect = new Rect(0f, curY, parentRect.width, headerHeight);
|
||||
Widgets.DrawBoxSolid(headerRect, new Color(0.25f, 0.25f, 0.25f, 0.8f));
|
||||
Widgets.DrawBox(headerRect);
|
||||
// Заголовок и имя пешки
|
||||
height += 45f + 40f;
|
||||
|
||||
// Иконка раскрытия (треугольник)
|
||||
string icon = expanded ? "▼" : "►";
|
||||
Text.Font = GameFont.Small;
|
||||
Widgets.Label(new Rect(8f, curY + 6f, 20f, headerHeight), icon);
|
||||
// Разделитель
|
||||
height += 10f;
|
||||
|
||||
// Заголовок
|
||||
Text.Font = GameFont.Small;
|
||||
Widgets.Label(new Rect(30f, curY + 6f, parentRect.width - 40f, headerHeight), title);
|
||||
// Высота колонок (берем большую)
|
||||
float columnHeight = Mathf.Max(CalculateContentHeight(), CalculateRightColumnHeight());
|
||||
height += columnHeight;
|
||||
|
||||
// Клик для раскрытия/сворачивания
|
||||
if (Widgets.ButtonInvisible(headerRect))
|
||||
{
|
||||
expanded = !expanded;
|
||||
}
|
||||
// Дополнительный отступ снизу
|
||||
height += 30f;
|
||||
|
||||
// Рисуем содержимое если развернуто
|
||||
if (expanded)
|
||||
{
|
||||
drawContentFunc();
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отрисовывает секцию с промптом
|
||||
/// /// Отрисовывает секцию с промптом
|
||||
/// </summary>
|
||||
private float DrawPromptSection(
|
||||
Rect parentRect,
|
||||
@@ -750,20 +745,28 @@ namespace AIImages
|
||||
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.DrawBox(headerRect);
|
||||
|
||||
// Иконка раскрытия
|
||||
string icon = expanded ? "▼" : "►";
|
||||
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()))
|
||||
{
|
||||
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))
|
||||
{
|
||||
expanded = !expanded;
|
||||
@@ -786,7 +794,12 @@ namespace AIImages
|
||||
Text.Font = GameFont.Tiny;
|
||||
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);
|
||||
|
||||
// Рисуем фон
|
||||
@@ -827,7 +840,7 @@ namespace AIImages
|
||||
float imageSize = Mathf.Min(rect.width, 400f);
|
||||
Rect imageRect = new Rect(
|
||||
rect.x + (rect.width - imageSize) / 2f,
|
||||
rect.y + curY,
|
||||
curY,
|
||||
imageSize,
|
||||
imageSize
|
||||
);
|
||||
@@ -838,7 +851,7 @@ namespace AIImages
|
||||
float placeholderSize = Mathf.Min(rect.width, 300f);
|
||||
Rect placeholderRect = new Rect(
|
||||
rect.x + (rect.width - placeholderSize) / 2f,
|
||||
rect.y + curY,
|
||||
curY,
|
||||
placeholderSize,
|
||||
placeholderSize
|
||||
);
|
||||
@@ -856,10 +869,7 @@ namespace AIImages
|
||||
|
||||
Text.Font = GameFont.Small;
|
||||
float statusHeight = Text.CalcHeight(generationStatus, rect.width);
|
||||
Widgets.Label(
|
||||
new Rect(rect.x, rect.y + curY, rect.width, statusHeight),
|
||||
generationStatus
|
||||
);
|
||||
Widgets.Label(new Rect(rect.x, curY, rect.width, statusHeight), generationStatus);
|
||||
return curY + statusHeight + 10f;
|
||||
}
|
||||
|
||||
@@ -868,7 +878,7 @@ namespace AIImages
|
||||
if (!isGenerating || generationProgress <= 0.0)
|
||||
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;
|
||||
if (totalSteps > 0)
|
||||
@@ -900,7 +910,7 @@ namespace AIImages
|
||||
? "AIImages.Generation.Cancel".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)
|
||||
CancelGeneration();
|
||||
|
||||
Reference in New Issue
Block a user