Files
MyCharacterAgent/Assets/02_Scripts/Chat/ChatUiBuilder.cs
2026-09-01 14:40:02 +09:00

137 lines
5.4 KiB
C#

using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// uGUI 조각을 코드로 만드는 공용 부품. 채팅창과 설정창이 같은 것을 쓴다.
///
/// 에셋(프리팹/스프라이트/폰트)을 하나도 만들지 않는 것이 이 프로젝트의 방침이다.
/// 이유는 ChatUiTheme 에 적어뒀다.
/// </summary>
public static class ChatUiBuilder
{
public static RectTransform NewRect(string name, Transform parent)
{
var go = new GameObject(name, typeof(RectTransform));
var rect = go.GetComponent<RectTransform>();
rect.SetParent(parent, false);
return rect;
}
/// <summary>부모를 가득 채우도록 늘린다.</summary>
public static void Stretch(RectTransform rect, float horizontal = 0f, float vertical = 0f)
{
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.offsetMin = new Vector2(horizontal, vertical);
rect.offsetMax = new Vector2(-horizontal, -vertical);
}
public static Image NewImage(string name, Transform parent, Sprite sprite, Color color)
{
var rect = NewRect(name, parent);
var image = rect.gameObject.AddComponent<Image>();
image.sprite = sprite;
if (sprite != null) image.type = Image.Type.Sliced;
image.color = color;
return image;
}
public static Text NewText(string name, Transform parent, string value, int fontSize, Color color)
{
var rect = NewRect(name, parent);
var text = rect.gameObject.AddComponent<Text>();
text.font = ChatUiTheme.Font;
text.fontSize = fontSize;
text.color = color;
text.text = value;
text.supportRichText = false;
// 글자가 스크롤 드래그나 버튼 클릭을 가로채지 않게 한다.
text.raycastTarget = false;
return text;
}
public static Button NewButton(string name, Transform parent, string label, int fontSize,
Color background, Color foreground)
{
var image = NewImage(name, parent, ChatUiTheme.RoundedSmall, background);
var rect = image.rectTransform;
var button = rect.gameObject.AddComponent<Button>();
button.targetGraphic = image;
var colors = button.colors;
colors.normalColor = Color.white;
colors.highlightedColor = new Color(1.15f, 1.15f, 1.15f, 1f);
colors.pressedColor = new Color(0.8f, 0.8f, 0.8f, 1f);
colors.disabledColor = new Color(0.6f, 0.6f, 0.6f, 0.5f);
button.colors = colors;
var text = NewText("Label", rect, label, fontSize, foreground);
text.alignment = TextAnchor.MiddleCenter;
Stretch(text.rectTransform);
return button;
}
/// <summary>
/// 입력칸 하나를 통째로 만든다. InputField 는 배경 그래픽, 본문 Text,
/// 안내문 Text 세 개가 갖춰져야 동작하므로 따로 만들면 빠뜨리기 쉽다.
/// </summary>
public static InputField NewInputField(string name, Transform parent, string placeholderText,
int fontSize, bool multiline = false)
{
var image = NewImage(name, parent, ChatUiTheme.RoundedSmall, ChatUiTheme.InputBackground);
var rect = image.rectTransform;
var text = NewText("Text", rect, string.Empty, fontSize, ChatUiTheme.PrimaryText);
text.alignment = multiline ? TextAnchor.UpperLeft : TextAnchor.MiddleLeft;
text.supportRichText = false;
Stretch(text.rectTransform, 10f, multiline ? 6f : 2f);
var placeholder = NewText("Placeholder", rect, placeholderText, fontSize, ChatUiTheme.DimText);
placeholder.alignment = text.alignment;
placeholder.supportRichText = false;
Stretch(placeholder.rectTransform, 10f, multiline ? 6f : 2f);
var field = rect.gameObject.AddComponent<InputField>();
field.targetGraphic = image;
field.textComponent = text;
field.placeholder = placeholder;
field.lineType = multiline ? InputField.LineType.MultiLineNewline : InputField.LineType.SingleLine;
field.caretColor = ChatUiTheme.PrimaryText;
field.customCaretColor = true;
return field;
}
/// <summary>설정 항목 위에 붙는 작은 제목.</summary>
public static Text NewSectionLabel(string name, Transform parent, string label)
{
var text = NewText(name, parent, label, 12, ChatUiTheme.DimText);
text.alignment = TextAnchor.LowerLeft;
return text;
}
/// <summary>가로/세로 크기를 레이아웃 그룹에 알려주는 LayoutElement 를 붙인다.</summary>
public static LayoutElement SetHeight(Transform target, float height)
{
var element = target.gameObject.AddComponent<LayoutElement>();
element.minHeight = height;
element.preferredHeight = height;
return element;
}
/// <summary>세로로 쌓는 목록 컨테이너. 설정 항목들이 여기 담긴다.</summary>
public static VerticalLayoutGroup MakeVerticalList(RectTransform rect, RectOffset padding, float spacing)
{
var layout = rect.gameObject.AddComponent<VerticalLayoutGroup>();
layout.padding = padding;
layout.spacing = spacing;
layout.childControlWidth = true;
layout.childControlHeight = true;
layout.childForceExpandWidth = true;
layout.childForceExpandHeight = false;
return layout;
}
}