#if UNITY_EDITOR using UnityEngine; using UnityEngine.UI; using UnityEditor; using UnityEditor.SceneManagement; using TMPro; using System.Reflection; using System.Linq; public static class CreateDeckBuilderScene { [MenuItem("Tools/Create DeckBuilder Scene")] public static void Create() { var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single); // Services var services = new GameObject("[Services]"); services.AddComponent(); services.AddComponent(); // Canvas var canvasGo = new GameObject("Canvas"); var canvas = canvasGo.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; var scaler = canvasGo.AddComponent(); scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(1920, 1080); canvasGo.AddComponent(); if (Object.FindObjectOfType() == null) { var es = new GameObject("EventSystem"); es.AddComponent(); es.AddComponent(); } // Background var bg = CreatePanel(canvasGo.transform, "Background", new Color(0.08f, 0.08f, 0.12f), stretch: true); // Header var header = CreatePanel(canvasGo.transform, "Header", new Color(0.12f, 0.12f, 0.18f, 0.95f)); SetAnchors(header.GetComponent(), new Vector2(0f, 0.93f), new Vector2(1f, 1f)); var backBtn = CreateTMPButton(header.transform, "BackButton", "< Back", new Color(0.2f, 0.2f, 0.3f)); SetAnchors(backBtn.GetComponent(), new Vector2(0.01f, 0.1f), new Vector2(0.07f, 0.9f)); var titleTxt = CreateTMPText(header.transform, "TitleText", "Deck Builder", 28, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(titleTxt.GetComponent(), new Vector2(0.3f, 0.1f), new Vector2(0.7f, 0.9f)); var exportBtn = CreateTMPButton(header.transform, "ExportToSimButton", "Export to Sim", new Color(0.2f, 0.45f, 0.7f)); SetAnchors(exportBtn.GetComponent(), new Vector2(0.88f, 0.1f), new Vector2(0.99f, 0.9f)); // ── LEFT: Deck List Panel ────────────────────────────────────── var leftPanel = CreatePanel(canvasGo.transform, "DeckListPanel", new Color(0.1f, 0.1f, 0.16f, 0.97f)); SetAnchors(leftPanel.GetComponent(), new Vector2(0f, 0.06f), new Vector2(0.22f, 0.93f)); var deckNameInput = CreateTMPInputField(leftPanel.transform, "DeckNameInput", "New deck name..."); SetAnchors(deckNameInput.GetComponent(), new Vector2(0.02f, 0.91f), new Vector2(0.75f, 0.98f)); var newDeckBtn = CreateTMPButton(leftPanel.transform, "NewDeckButton", "+", new Color(0.2f, 0.55f, 0.2f)); SetAnchors(newDeckBtn.GetComponent(), new Vector2(0.77f, 0.91f), new Vector2(0.98f, 0.98f)); var deckScroll = new GameObject("DeckListScroll"); deckScroll.transform.SetParent(leftPanel.transform, false); var dsr = deckScroll.AddComponent(); deckScroll.AddComponent().color = new Color(0,0,0,0.01f); SetAnchors(deckScroll.GetComponent(), new Vector2(0f, 0f), new Vector2(1f, 0.9f)); var deckContent = new GameObject("Content"); deckContent.transform.SetParent(deckScroll.transform, false); var dcrect = deckContent.AddComponent(); dcrect.anchorMin = new Vector2(0,1); dcrect.anchorMax = new Vector2(1,1); dcrect.pivot = new Vector2(0.5f,1f); deckContent.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; var dcvlg = deckContent.AddComponent(); dcvlg.spacing = 4; dcvlg.padding = new RectOffset(4,4,4,4); dcvlg.childForceExpandWidth = true; dcvlg.childForceExpandHeight = false; dsr.content = dcrect; dsr.horizontal = false; // ── CENTER: Active Deck Panel ────────────────────────────────── var centerPanel = CreatePanel(canvasGo.transform, "ActiveDeckPanel", new Color(0.09f, 0.09f, 0.14f, 0.97f)); SetAnchors(centerPanel.GetComponent(), new Vector2(0.22f, 0.06f), new Vector2(0.58f, 0.93f)); var deckTitleTxt = CreateTMPText(centerPanel.transform, "DeckTitleText", "Select a Deck", 22, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(deckTitleTxt.GetComponent(), new Vector2(0f, 0.93f), new Vector2(0.7f, 1f)); var cardCountTxt = CreateTMPText(centerPanel.transform, "CardCountText", "0 / 100", 18, FontStyles.Normal, TextAlignmentOptions.Right); SetAnchors(cardCountTxt.GetComponent(), new Vector2(0.7f, 0.93f), new Vector2(1f, 1f)); var validIndic = CreatePanel(centerPanel.transform, "ValidationIndicator", new Color(0.7f, 0.2f, 0.2f)); SetAnchors(validIndic.GetComponent(), new Vector2(0f, 0.88f), new Vector2(0.12f, 0.93f)); var validTxt = CreateTMPText(centerPanel.transform, "ValidationText", "100 cards needed", 14, FontStyles.Normal, TextAlignmentOptions.Left); SetAnchors(validTxt.GetComponent(), new Vector2(0.13f, 0.88f), new Vector2(1f, 0.93f)); // Commander var cmdInput = CreateTMPInputField(centerPanel.transform, "CommanderSearchInput", "Search commander..."); SetAnchors(cmdInput.GetComponent(), new Vector2(0.01f, 0.81f), new Vector2(0.65f, 0.87f)); var cmdSearchBtn = CreateTMPButton(centerPanel.transform, "CommanderSearchButton", "Find", new Color(0.25f, 0.45f, 0.65f)); SetAnchors(cmdSearchBtn.GetComponent(), new Vector2(0.66f, 0.81f), new Vector2(0.82f, 0.87f)); var colorIdDd = CreateTMPDropdown(centerPanel.transform, "ColorIdentityDropdown", new[]{"Any","W","U","B","R","G","WU","WB","WR","WG","UB","UR","UG","BR","BG","RG"}); SetAnchors(colorIdDd.GetComponent(), new Vector2(0.01f, 0.75f), new Vector2(0.98f, 0.81f)); var cmdResultScroll = new GameObject("CommanderResultScroll"); cmdResultScroll.transform.SetParent(centerPanel.transform, false); var cmrsr = cmdResultScroll.AddComponent(); cmdResultScroll.AddComponent().color = new Color(0,0,0,0.01f); SetAnchors(cmdResultScroll.GetComponent(), new Vector2(0f, 0.66f), new Vector2(1f, 0.75f)); var cmdContent = CreateScrollContent(cmdResultScroll, out cmrsr); var selCmdTxt = CreateTMPText(centerPanel.transform, "SelectedCommanderText", "Commander: None", 15, FontStyles.Italic, TextAlignmentOptions.Left); SetAnchors(selCmdTxt.GetComponent(), new Vector2(0.01f, 0.62f), new Vector2(0.98f, 0.66f)); // Deck card list var deckCardScroll = new GameObject("DeckCardListScroll"); deckCardScroll.transform.SetParent(centerPanel.transform, false); SetAnchors(deckCardScroll.GetComponent(), new Vector2(0f, 0.12f), new Vector2(1f, 0.62f)); var dclsr = deckCardScroll.AddComponent(); deckCardScroll.AddComponent().color = new Color(0,0,0,0.01f); var deckCardContent = CreateScrollContent(deckCardScroll, out dclsr); var saveDeckBtn = CreateTMPButton(centerPanel.transform, "SaveDeckButton", "Save", new Color(0.2f, 0.55f, 0.2f)); SetAnchors(saveDeckBtn.GetComponent(), new Vector2(0.02f, 0.03f), new Vector2(0.35f, 0.11f)); var deleteDeckBtn = CreateTMPButton(centerPanel.transform, "DeleteDeckButton", "Delete Deck", new Color(0.55f, 0.15f, 0.15f)); SetAnchors(deleteDeckBtn.GetComponent(), new Vector2(0.37f, 0.03f), new Vector2(0.7f, 0.11f)); // ── RIGHT: Card Search + Charts ──────────────────────────────── var rightPanel = CreatePanel(canvasGo.transform, "CardSearchPanel", new Color(0.1f, 0.1f, 0.16f, 0.97f)); SetAnchors(rightPanel.GetComponent(), new Vector2(0.58f, 0.06f), new Vector2(1f, 0.93f)); var cardSearchInput = CreateTMPInputField(rightPanel.transform, "CardSearchInput", "Search cards..."); SetAnchors(cardSearchInput.GetComponent(), new Vector2(0.01f, 0.92f), new Vector2(0.72f, 0.99f)); var cardSearchBtn = CreateTMPButton(rightPanel.transform, "CardSearchButton", "Search", new Color(0.2f, 0.5f, 0.8f)); SetAnchors(cardSearchBtn.GetComponent(), new Vector2(0.73f, 0.92f), new Vector2(0.99f, 0.99f)); var cardResultScroll = new GameObject("CardSearchResultScroll"); cardResultScroll.transform.SetParent(rightPanel.transform, false); SetAnchors(cardResultScroll.GetComponent(), new Vector2(0f, 0.55f), new Vector2(1f, 0.92f)); var crsr = cardResultScroll.AddComponent(); cardResultScroll.AddComponent().color = new Color(0,0,0,0.01f); var cardResultContent = CreateScrollContent(cardResultScroll, out crsr); // Mana curve var manaCurveLabel = CreateTMPText(rightPanel.transform, "ManaCurveLabel", "Mana Curve", 16, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(manaCurveLabel.GetComponent(), new Vector2(0f, 0.49f), new Vector2(1f, 0.54f)); var manaCurveParent = new GameObject("ManaCurveBarParent"); manaCurveParent.transform.SetParent(rightPanel.transform, false); SetAnchors(manaCurveParent.GetComponent(), new Vector2(0.02f, 0.33f), new Vector2(0.98f, 0.49f)); var manaHlg = manaCurveParent.AddComponent(); manaHlg.spacing = 4; manaHlg.childForceExpandWidth = true; manaHlg.childForceExpandHeight = false; // Color pie var colorPieLabel = CreateTMPText(rightPanel.transform, "ColorPieLabel", "Color Identity", 16, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(colorPieLabel.GetComponent(), new Vector2(0f, 0.27f), new Vector2(1f, 0.32f)); var colorPieParent = new GameObject("ColorPieParent"); colorPieParent.transform.SetParent(rightPanel.transform, false); SetAnchors(colorPieParent.GetComponent(), new Vector2(0.02f, 0.13f), new Vector2(0.98f, 0.27f)); var pieHlg = colorPieParent.AddComponent(); pieHlg.spacing = 6; pieHlg.childForceExpandWidth = true; pieHlg.childForceExpandHeight = false; Color[] pieColors = { Color.white, new Color(0.3f,0.6f,1f), new Color(0.1f,0.1f,0.1f), new Color(0.8f,0.2f,0.2f), new Color(0.2f,0.7f,0.2f) }; string[] pieLabels = { "W", "U", "B", "R", "G" }; for (int i = 0; i < pieColors.Length; i++) { var slice = new GameObject("Slice_" + pieLabels[i]); slice.transform.SetParent(colorPieParent.transform, false); var sliceImg = slice.AddComponent(); sliceImg.color = pieColors[i]; var sliceText = CreateTMPText(slice.transform, "Label", pieLabels[i], 14, FontStyles.Bold, TextAlignmentOptions.Center); } // -- Card type breakdown -- var typeLabel = CreateTMPText(rightPanel.transform, "TypeBreakdownLabel", "Card Types", 16, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(typeLabel.GetComponent(), new Vector2(0f, 0.08f), new Vector2(1f, 0.13f)); var typeText = CreateTMPText(rightPanel.transform, "TypeBreakdownText", "", 14, FontStyles.Normal, TextAlignmentOptions.TopLeft); SetAnchors(typeText.GetComponent(), new Vector2(0.05f, 0.01f), new Vector2(0.95f, 0.08f)); // -- Save -- if (!AssetDatabase.IsValidFolder("Assets/Scenes")) AssetDatabase.CreateFolder("Assets", "Scenes"); string path = "Assets/Scenes/DeckBuilder.unity"; EditorSceneManager.SaveScene(scene, path); var existing = new System.Collections.Generic.List(EditorBuildSettings.scenes); if (!existing.Any(s => s.path == path)) existing.Add(new EditorBuildSettingsScene(path, true)); EditorBuildSettings.scenes = existing.ToArray(); Debug.Log("[CreateDeckBuilderScene] DeckBuilder scene created and saved to " + path); } // -- Helpers -- /// /// Creates a Viewport + Content hierarchy inside the given scroll GameObject, /// wires up the ScrollRect, and returns the Content RectTransform. /// static RectTransform CreateScrollContent(GameObject scrollGo, out ScrollRect scrollRect) { scrollRect = scrollGo.GetComponent(); if (scrollRect == null) scrollRect = scrollGo.AddComponent(); // Viewport var viewport = new GameObject("Viewport"); viewport.transform.SetParent(scrollGo.transform, false); viewport.AddComponent(); var vpRect = viewport.GetComponent(); vpRect.anchorMin = Vector2.zero; vpRect.anchorMax = Vector2.one; vpRect.offsetMin = Vector2.zero; vpRect.offsetMax = Vector2.zero; // Content var content = new GameObject("Content"); content.transform.SetParent(viewport.transform, false); var contentRect = content.AddComponent(); contentRect.anchorMin = new Vector2(0f, 1f); contentRect.anchorMax = new Vector2(1f, 1f); contentRect.pivot = new Vector2(0.5f, 1f); contentRect.offsetMin = Vector2.zero; contentRect.offsetMax = Vector2.zero; content.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; var vlg = content.AddComponent(); vlg.spacing = 4; vlg.padding = new RectOffset(4, 4, 4, 4); vlg.childForceExpandWidth = true; vlg.childForceExpandHeight = false; scrollRect.viewport = vpRect; scrollRect.content = contentRect; scrollRect.horizontal = false; return contentRect; } static void SetField(object target, string fieldName, object value) { var field = target.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); if (field != null) field.SetValue(target, value); else Debug.LogWarning("Could not find field: " + fieldName); } static void SetAnchors(RectTransform rt, Vector2 min, Vector2 max) { rt.anchorMin = min; rt.anchorMax = max; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; } static GameObject CreatePanel(Transform parent, string name, Color color, bool stretch = false) { var go = new GameObject(name); go.transform.SetParent(parent, false); var img = go.AddComponent(); img.color = color; var rt = go.GetComponent(); if (stretch) SetAnchors(rt, Vector2.zero, Vector2.one); return go; } static GameObject CreateTMPText(Transform parent, string name, string text, int fontSize, FontStyles style, TextAlignmentOptions alignment) { var go = new GameObject(name); go.transform.SetParent(parent, false); var tmp = go.AddComponent(); tmp.text = text; tmp.fontSize = fontSize; tmp.fontStyle = style; tmp.alignment = alignment; tmp.color = Color.white; var rt = go.GetComponent(); SetAnchors(rt, Vector2.zero, Vector2.one); return go; } static GameObject CreateTMPButton(Transform parent, string name, string label, Color bgColor) { var go = new GameObject(name); go.transform.SetParent(parent, false); var img = go.AddComponent(); img.color = bgColor; var btn = go.AddComponent