137 lines
5.4 KiB
C#
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;
|
|
}
|
|
}
|