315 lines
16 KiB
C#
315 lines
16 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
using Invector.vItemManager;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Beyond
|
|
{
|
|
public class TrinketUIGenerator : MonoBehaviour
|
|
{
|
|
[MenuItem("Beyond/Generate Trinket UI")]
|
|
public static void CreateTrinketUI()
|
|
{
|
|
try
|
|
{
|
|
// 1. Create Dedicated Canvas
|
|
GameObject canvasObj = new GameObject("Trinket_UI_Canvas");
|
|
Canvas c = canvasObj.AddComponent<Canvas>();
|
|
c.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
c.sortingOrder = 99;
|
|
|
|
CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
|
scaler.matchWidthOrHeight = 0.5f; // Balanced scaling
|
|
|
|
canvasObj.AddComponent<GraphicRaycaster>();
|
|
|
|
// Add Controller
|
|
TrinketUIController uiController = canvasObj.AddComponent<TrinketUIController>();
|
|
uiController.mainCanvas = c;
|
|
//uiController.trinketType = bItemType.Trinkets;
|
|
|
|
// 2. Main Panel Background
|
|
GameObject mainPanel = CreateUIObject("Main_Panel", canvasObj.transform);
|
|
Image panelImg = mainPanel.AddComponent<Image>();
|
|
panelImg.color = new Color(0.05f, 0.05f, 0.05f, 0.95f);
|
|
StretchToFill(mainPanel.GetComponent<RectTransform>());
|
|
|
|
// 3. Layout Container (The Parent of Left/Right)
|
|
GameObject contentContainer = CreateUIObject("Content_Container", mainPanel.transform);
|
|
StretchToFill(contentContainer.GetComponent<RectTransform>());
|
|
RectTransform containerRect = contentContainer.GetComponent<RectTransform>();
|
|
// Add margins so it doesn't touch screen edges
|
|
containerRect.offsetMin = new Vector2(100, 100);
|
|
containerRect.offsetMax = new Vector2(-100, -100);
|
|
|
|
HorizontalLayoutGroup hLayout = contentContainer.AddComponent<HorizontalLayoutGroup>();
|
|
hLayout.childControlWidth = true;
|
|
hLayout.childControlHeight = true;
|
|
hLayout.childForceExpandWidth = true; // FORCE 50/50 SPLIT
|
|
hLayout.childForceExpandHeight = true;
|
|
hLayout.spacing = 50;
|
|
|
|
// =========================================================
|
|
// LEFT SIDE: EQUIP AREA
|
|
// =========================================================
|
|
GameObject leftPanel = CreateUIObject("Left_EquipArea", contentContainer.transform);
|
|
leftPanel.AddComponent<Image>().color = new Color(1, 1, 1, 0.05f);
|
|
|
|
bEquipArea equipArea = leftPanel.AddComponent<bEquipArea>();
|
|
equipArea.equipSlots = new List<bEquipSlot>();
|
|
equipArea.itemTypes = new List<bItemType>() { bItemType.Trinkets };
|
|
|
|
// Vertical Layout for the Left Panel itself
|
|
VerticalLayoutGroup leftVL = leftPanel.AddComponent<VerticalLayoutGroup>();
|
|
leftVL.padding = new RectOffset(20, 20, 20, 20);
|
|
leftVL.spacing = 20;
|
|
leftVL.childControlHeight = true;
|
|
leftVL.childControlWidth = true;
|
|
leftVL.childForceExpandHeight = false;
|
|
|
|
// Title
|
|
TMP_Text titleTxt = CreateTMPObject("Equip_Title", leftPanel.transform, "Equipped Trinkets");
|
|
titleTxt.rectTransform.sizeDelta = new Vector2(0, 60); // Fixed height for title
|
|
|
|
// References (Hidden Text)
|
|
equipArea.displayNameText = CreateTextObject("EA_Name", "", leftPanel.transform);
|
|
equipArea.displayDescriptionText = CreateTextObject("EA_Desc", "", leftPanel.transform);
|
|
|
|
// Slot Container (Centered)
|
|
GameObject slotsContainer = CreateUIObject("Slots_Container", leftPanel.transform);
|
|
// Make slots container take up remaining space but center its children
|
|
LayoutElement slotsLE = slotsContainer.AddComponent<LayoutElement>();
|
|
slotsLE.flexibleHeight = 1;
|
|
|
|
HorizontalLayoutGroup slotsLayout = slotsContainer.AddComponent<HorizontalLayoutGroup>();
|
|
slotsLayout.childAlignment = TextAnchor.MiddleCenter;
|
|
slotsLayout.spacing = 40;
|
|
slotsLayout.childControlWidth = false; // Don't stretch slots
|
|
slotsLayout.childControlHeight = false;
|
|
|
|
// Create 3 Equip Slots
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
GameObject slotObj = CreateUIObject($"EquipSlot_{i}", slotsContainer.transform);
|
|
Image slotImg = slotObj.AddComponent<Image>();
|
|
slotImg.color = new Color(0.2f, 0.2f, 0.2f, 1f);
|
|
slotObj.GetComponent<RectTransform>().sizeDelta = new Vector2(120, 120);
|
|
|
|
slotObj.AddComponent<CanvasGroup>();
|
|
bEquipSlot equipSlot = slotObj.AddComponent<bEquipSlot>();
|
|
equipSlot.itemType = new List<bItemType>() { bItemType.Trinkets };
|
|
|
|
GameObject iconObj = CreateUIObject("Icon", slotObj.transform);
|
|
StretchToFill(iconObj.GetComponent<RectTransform>());
|
|
Image iconImg = iconObj.AddComponent<Image>();
|
|
iconImg.raycastTarget = false;
|
|
iconImg.color = Color.clear; // Relies on bItemSlot to turn alpha back to 1
|
|
|
|
equipSlot.icon = iconImg;
|
|
equipArea.equipSlots.Add(equipSlot);
|
|
}
|
|
|
|
// =========================================================
|
|
// RIGHT SIDE: ITEM WINDOW
|
|
// =========================================================
|
|
GameObject rightPanel = CreateUIObject("Right_ItemWindow", contentContainer.transform);
|
|
rightPanel.AddComponent<Image>().color = new Color(1, 1, 1, 0.05f);
|
|
|
|
bItemWindow itemWindow = rightPanel.AddComponent<bItemWindow>();
|
|
|
|
// Vertical Layout for Right Panel
|
|
VerticalLayoutGroup rightVL = rightPanel.AddComponent<VerticalLayoutGroup>();
|
|
rightVL.padding = new RectOffset(20, 20, 20, 20);
|
|
rightVL.spacing = 20;
|
|
rightVL.childControlWidth = true;
|
|
rightVL.childControlHeight = true;
|
|
|
|
// 1. Scroll View (Takes up flexible space)
|
|
GameObject scrollView = CreateUIObject("Scroll_View", rightPanel.transform);
|
|
LayoutElement svLE = scrollView.AddComponent<LayoutElement>();
|
|
svLE.flexibleHeight = 1; // Take available space
|
|
|
|
ScrollRect scrollRect = scrollView.AddComponent<ScrollRect>();
|
|
GameObject viewport = CreateUIObject("Viewport", scrollView.transform);
|
|
StretchToFill(viewport.GetComponent<RectTransform>());
|
|
viewport.AddComponent<Mask>();
|
|
viewport.AddComponent<Image>().color = new Color(1,1,1,0.01f);
|
|
|
|
GameObject content = CreateUIObject("Content", viewport.transform);
|
|
RectTransform contentRT = content.GetComponent<RectTransform>();
|
|
contentRT.anchorMin = new Vector2(0, 1);
|
|
contentRT.anchorMax = new Vector2(1, 1);
|
|
contentRT.pivot = new Vector2(0.5f, 1);
|
|
|
|
GridLayoutGroup grid = content.AddComponent<GridLayoutGroup>();
|
|
grid.cellSize = new Vector2(100, 100);
|
|
grid.spacing = new Vector2(15, 15);
|
|
|
|
ContentSizeFitter csf = content.AddComponent<ContentSizeFitter>();
|
|
csf.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
|
|
scrollRect.content = contentRT;
|
|
scrollRect.viewport = viewport.GetComponent<RectTransform>();
|
|
itemWindow.contentWindow = contentRT;
|
|
|
|
// 2. Details Panel (Fixed Height at bottom)
|
|
GameObject detailsPanel = CreateUIObject("Details_Panel", rightPanel.transform);
|
|
LayoutElement detailsLE = detailsPanel.AddComponent<LayoutElement>();
|
|
detailsLE.minHeight = 300;
|
|
detailsLE.preferredHeight = 300;
|
|
|
|
VerticalLayoutGroup detailsLayout = detailsPanel.AddComponent<VerticalLayoutGroup>();
|
|
detailsLayout.spacing = 5;
|
|
detailsLayout.childControlHeight = true;
|
|
detailsLayout.childForceExpandHeight = false;
|
|
|
|
// Details Components (Auto-Sizing Text)
|
|
itemWindow.displayNameText = CreateTMPObject("Name_Text", detailsPanel.transform, "Item Name");
|
|
itemWindow.displayNameText.fontStyle = FontStyles.Bold;
|
|
|
|
itemWindow.displayTypeText = CreateTextObject("Type_Text", "Item Type", detailsPanel.transform);
|
|
itemWindow.displayAttributesText = CreateTextObject("Attributes_Text", "Stats...", detailsPanel.transform);
|
|
itemWindow.displayAmountText = CreateTextObject("Amount_Text", "", detailsPanel.transform);
|
|
|
|
// Description
|
|
GameObject descContainer = CreateUIObject("Desc_Container", detailsPanel.transform);
|
|
LayoutElement descLE = descContainer.AddComponent<LayoutElement>();
|
|
descLE.flexibleHeight = 1; // Description expands to fill gap
|
|
|
|
descContainer.AddComponent<VerticalLayoutGroup>();
|
|
itemWindow.displayDescriptionText = CreateTMPObject("Desc_Text", descContainer.transform, "Description...");
|
|
itemWindow.displayDescriptionText.alignment = TextAlignmentOptions.TopLeft;
|
|
itemWindow.descriptionTransform = descContainer.GetComponent<RectTransform>();
|
|
|
|
// Submit Button
|
|
GameObject btnObj = CreateUIObject("Submit_Button", detailsPanel.transform);
|
|
LayoutElement btnLE = btnObj.AddComponent<LayoutElement>();
|
|
btnLE.minHeight = 50;
|
|
btnLE.preferredHeight = 50;
|
|
|
|
btnObj.AddComponent<Image>().color = new Color(0, 0.6f, 0, 1);
|
|
Button submitBtn = btnObj.AddComponent<Button>();
|
|
|
|
TMP_Text btnText = CreateTMPObject("Btn_Text", btnObj.transform, "EQUIP");
|
|
StretchToFill(btnText.rectTransform);
|
|
|
|
// Serialization
|
|
SerializedObject so = new SerializedObject(itemWindow);
|
|
so.Update();
|
|
|
|
SerializedProperty propBtn = so.FindProperty("button");
|
|
if (propBtn != null && btnObj != null) propBtn.objectReferenceValue = btnObj;
|
|
|
|
SerializedProperty propBtnText = so.FindProperty("submitButtonText");
|
|
if (propBtnText != null && btnText != null) propBtnText.objectReferenceValue = btnText;
|
|
|
|
SerializedProperty propConsumeBtn = so.FindProperty("consumeButton");
|
|
if (propConsumeBtn != null && btnObj != null) propConsumeBtn.objectReferenceValue = btnObj;
|
|
|
|
// Need to assign Image for serialization, even if we don't use it in UI layout much
|
|
GameObject dummyImg = CreateUIObject("DummyImg", detailsPanel.transform);
|
|
dummyImg.SetActive(false); // Hide it
|
|
itemWindow.displayItemImage = dummyImg.AddComponent<Image>();
|
|
|
|
so.ApplyModifiedProperties();
|
|
|
|
// =========================================================
|
|
// TEMPLATE SLOT PREFAB
|
|
// =========================================================
|
|
GameObject slotTemplate = CreateUIObject("Slot_Template_Prefab", canvasObj.transform);
|
|
Image templateBg = slotTemplate.AddComponent<Image>();
|
|
templateBg.color = new Color(0.3f, 0.3f, 0.3f);
|
|
|
|
slotTemplate.AddComponent<CanvasGroup>();
|
|
bItemSlot itemSlotScript = slotTemplate.AddComponent<bItemSlot>();
|
|
|
|
GameObject tIcon = CreateUIObject("Icon", slotTemplate.transform);
|
|
StretchToFill(tIcon.GetComponent<RectTransform>());
|
|
itemSlotScript.icon = tIcon.AddComponent<Image>();
|
|
itemSlotScript.icon.raycastTarget = false;
|
|
itemSlotScript.icon.color = Color.clear;
|
|
|
|
GameObject tCheck = CreateUIObject("CheckIcon", slotTemplate.transform);
|
|
RectTransform checkRT = tCheck.GetComponent<RectTransform>();
|
|
checkRT.anchorMin = new Vector2(1,1);
|
|
checkRT.anchorMax = new Vector2(1,1);
|
|
checkRT.sizeDelta = new Vector2(25,25);
|
|
checkRT.anchoredPosition = new Vector2(-10, -10);
|
|
itemSlotScript.checkIcon = tCheck.AddComponent<Image>();
|
|
itemSlotScript.checkIcon.color = Color.green;
|
|
tCheck.SetActive(false);
|
|
|
|
itemWindow.slotPrefab = itemSlotScript;
|
|
slotTemplate.SetActive(false);
|
|
|
|
// Final Wiring
|
|
equipArea.itemPicker = itemWindow;
|
|
uiController.trinketEquipArea = equipArea;
|
|
uiController.trinketItemWindow = itemWindow;
|
|
|
|
c.enabled = false;
|
|
Selection.activeGameObject = canvasObj;
|
|
Debug.Log("Trinket UI (Layout Fixed) Created Successfully.");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogError("Error generating UI: " + ex.Message + "\n" + ex.StackTrace);
|
|
}
|
|
}
|
|
|
|
// --- Helpers ---
|
|
private static GameObject CreateUIObject(string name, Transform parent)
|
|
{
|
|
GameObject go = new GameObject(name);
|
|
go.AddComponent<RectTransform>();
|
|
if(parent != null) go.transform.SetParent(parent, false);
|
|
return go;
|
|
}
|
|
|
|
private static TMP_Text CreateTMPObject(string name, Transform parent, string text)
|
|
{
|
|
GameObject go = CreateUIObject(name, parent);
|
|
TMP_Text tmp = go.AddComponent<TextMeshProUGUI>();
|
|
if (tmp != null)
|
|
{
|
|
tmp.text = text;
|
|
tmp.alignment = TextAlignmentOptions.Center;
|
|
tmp.color = Color.white;
|
|
// AUTO SIZING IS KEY for fixing your issue
|
|
tmp.enableAutoSizing = true;
|
|
tmp.fontSizeMin = 12;
|
|
tmp.fontSizeMax = 72;
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
private static Text CreateTextObject(string name, string text, Transform parent)
|
|
{
|
|
GameObject go = CreateUIObject(name, parent);
|
|
Text txt = go.AddComponent<Text>();
|
|
txt.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
|
if(txt.font == null) txt.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
|
txt.text = text;
|
|
txt.alignment = TextAnchor.MiddleCenter;
|
|
txt.color = Color.white;
|
|
txt.resizeTextForBestFit = true; // Auto size for legacy text
|
|
txt.resizeTextMinSize = 10;
|
|
txt.resizeTextMaxSize = 60;
|
|
return txt;
|
|
}
|
|
|
|
private static void StretchToFill(RectTransform rt)
|
|
{
|
|
rt.anchorMin = Vector2.zero;
|
|
rt.anchorMax = Vector2.one;
|
|
rt.offsetMin = Vector2.zero;
|
|
rt.offsetMax = Vector2.zero;
|
|
}
|
|
}
|
|
}
|
|
#endif |