using System; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using UnityExplorer.Core.Config; using UnityExplorer.Core.Runtime; using UnityExplorer.UI.Models; using UnityExplorer.UI.Utility; using UnityExplorer.UI.Widgets; namespace UnityExplorer.UI { public static class UIFactory { internal static Vector2 _largeElementSize = new Vector2(160f, 30f); internal static Vector2 _smallElementSize = new Vector2(160f, 20f); internal static Color _defaultTextColor = Color.white; internal static Font _defaultFont; public static void Init() { _defaultFont = Resources.GetBuiltinResource("Arial.ttf"); } public static GameObject CreateUIObject(string name, GameObject parent = null, Vector2 size = default) { if (!parent) { ExplorerCore.LogWarning("Cannot create UI object as the parent is null or destroyed! (" + name + ")"); ExplorerCore.Log(Environment.StackTrace); return null; } var obj = new GameObject(name) { layer = 5, hideFlags = HideFlags.HideAndDontSave, }; obj.transform.SetParent(parent.transform, false); RectTransform rect = obj.AddComponent(); rect.sizeDelta = size == default ? _smallElementSize : size; return obj; } internal static void SetDefaultTextValues(Text text) { text.color = _defaultTextColor; text.font = _defaultFont; text.fontSize = 14; } internal static void SetDefaultSelectableColors(Selectable selectable) { RuntimeProvider.Instance.SetColorBlock(selectable, new Color(0.2f, 0.2f, 0.2f), new Color(0.3f, 0.3f, 0.3f), new Color(0.15f, 0.15f, 0.15f)); } /// /// Get and/or Add a LayoutElement component to the GameObject, and set any of the values on it. /// public static LayoutElement SetLayoutElement(GameObject gameObject, int? minWidth = null, int? minHeight = null, int? flexibleWidth = null, int? flexibleHeight = null, int? preferredWidth = null, int? preferredHeight = null, bool? ignoreLayout = null) { var layout = gameObject.GetComponent(); if (!layout) layout = gameObject.AddComponent(); if (minWidth != null) layout.minWidth = (int)minWidth; if (minHeight != null) layout.minHeight = (int)minHeight; if (flexibleWidth != null) layout.flexibleWidth = (int)flexibleWidth; if (flexibleHeight != null) layout.flexibleHeight = (int)flexibleHeight; if (preferredWidth != null) layout.preferredWidth = (int)preferredWidth; if (preferredHeight != null) layout.preferredHeight = (int)preferredHeight; if (ignoreLayout != null) layout.ignoreLayout = (bool)ignoreLayout; return layout; } /// /// Get and/or Add a HorizontalOrVerticalLayoutGroup (must pick one) to the GameObject, and set the values on it. /// public static T SetLayoutGroup(GameObject gameObject, bool? forceWidth = null, bool? forceHeight = null, bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null, int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup { var group = gameObject.GetComponent(); if (!group) group = gameObject.AddComponent(); return SetLayoutGroup(group, forceWidth, forceHeight, childControlWidth, childControlHeight, spacing, padTop, padBottom, padLeft, padRight, childAlignment); } /// /// Set the values on a HorizontalOrVerticalLayoutGroup. /// public static T SetLayoutGroup(T group, bool? forceWidth = null, bool? forceHeight = null, bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null, int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup { if (forceWidth != null) group.childForceExpandWidth = (bool)forceWidth; if (forceHeight != null) group.childForceExpandHeight = (bool)forceHeight; if (childControlWidth != null) group.SetChildControlWidth((bool)childControlWidth); if (childControlHeight != null) group.SetChildControlHeight((bool)childControlHeight); if (spacing != null) group.spacing = (int)spacing; if (padTop != null) group.padding.top = (int)padTop; if (padBottom != null) group.padding.bottom = (int)padBottom; if (padLeft != null) group.padding.left = (int)padLeft; if (padRight != null) group.padding.right = (int)padRight; if (childAlignment != null) group.childAlignment = (TextAnchor)childAlignment; return group; } /// /// Create a Panel on the UI Canvas. /// public static GameObject CreatePanel(string name, out GameObject contentHolder, Color? bgColor = null) { var panelObj = CreateUIObject(name, UIManager.PanelHolder); SetLayoutGroup(panelObj, true, true, true, true); var rect = panelObj.GetComponent(); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.anchoredPosition = Vector2.zero; rect.sizeDelta = Vector2.zero; var maskImg = panelObj.AddComponent(); maskImg.color = Color.black; panelObj.AddComponent().showMaskGraphic = true; contentHolder = CreateUIObject("Content", panelObj); Image bgImage = contentHolder.AddComponent(); bgImage.type = Image.Type.Filled; if (bgColor == null) bgImage.color = new Color(0.07f, 0.07f, 0.07f); else bgImage.color = (Color)bgColor; SetLayoutGroup(contentHolder, true, true, true, true, 3, 3, 3, 3, 3); return panelObj; } /// /// Create a VerticalLayoutGroup object. /// public static GameObject CreateVerticalGroup(GameObject parent, string name, bool forceWidth, bool forceHeight, bool childControlWidth, bool childControlHeight, int spacing = 0, Vector4 padding = default, Color bgColor = default, TextAnchor? childAlignment = null) { GameObject groupObj = CreateUIObject(name, parent); SetLayoutGroup(groupObj, forceWidth, forceHeight, childControlWidth, childControlHeight, spacing, (int)padding.x, (int)padding.y, (int)padding.z, (int)padding.w, childAlignment); Image image = groupObj.AddComponent(); image.color = bgColor == default ? new Color(0.17f, 0.17f, 0.17f) : bgColor; return groupObj; } /// /// Create a HorizontalLayoutGroup object. /// public static GameObject CreateHorizontalGroup(GameObject parent, string name, bool forceExpandWidth, bool forceExpandHeight, bool childControlWidth, bool childControlHeight, int spacing = 0, Vector4 padding = default, Color bgColor = default, TextAnchor? childAlignment = null) { GameObject groupObj = CreateUIObject(name, parent); SetLayoutGroup(groupObj, forceExpandWidth, forceExpandHeight, childControlWidth, childControlHeight, spacing, (int)padding.x, (int)padding.y, (int)padding.z, (int)padding.w, childAlignment); Image image = groupObj.AddComponent(); image.color = bgColor == default ? new Color(0.17f, 0.17f, 0.17f) : bgColor; return groupObj; } /// /// Create a GridLayoutGroup object. /// public static GameObject CreateGridGroup(GameObject parent, string name, Vector2 cellSize, Vector2 spacing, Color bgColor = default) { var groupObj = CreateUIObject(name, parent); GridLayoutGroup gridGroup = groupObj.AddComponent(); gridGroup.childAlignment = TextAnchor.UpperLeft; gridGroup.cellSize = cellSize; gridGroup.spacing = spacing; Image image = groupObj.AddComponent(); image.color = bgColor == default ? new Color(0.17f, 0.17f, 0.17f) : bgColor; return groupObj; } /// /// Create a Label object. /// public static Text CreateLabel(GameObject parent, string name, string text, TextAnchor alignment, Color color = default, bool supportRichText = true, int fontSize = 14) { var obj = CreateUIObject(name, parent); var textComp = obj.AddComponent(); SetDefaultTextValues(textComp); textComp.text = text; textComp.color = color == default ? _defaultTextColor : color; textComp.supportRichText = supportRichText; textComp.alignment = alignment; textComp.fontSize = fontSize; return textComp; } public static ButtonRef CreateButton(GameObject parent, string name, string text, Color? normalColor = null) { var colors = new ColorBlock(); normalColor = normalColor ?? new Color(0.25f, 0.25f, 0.25f); var btn = CreateButton(parent, name, text, colors); RuntimeProvider.Instance.SetColorBlock(btn.Button, normalColor, normalColor * 1.2f, normalColor * 0.7f); return btn; } public static ButtonRef CreateButton(GameObject parent, string name, string text, ColorBlock colors) { GameObject buttonObj = CreateUIObject(name, parent, _smallElementSize); var textObj = CreateUIObject("Text", buttonObj); Image image = buttonObj.AddComponent(); image.type = Image.Type.Sliced; image.color = new Color(1, 1, 1, 1); var button = buttonObj.AddComponent