#if UNITY_EDITOR using UnityEngine; using UnityEngine.UI; using UnityEditor; using UnityEditor.SceneManagement; using TMPro; using System.Reflection; using System.Linq; public static class CreateSimulatorScene { [MenuItem("Tools/Create Simulator Scene")] public static void Create() { var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single); // ── Services ────────────────────────────────────────────────────────── var services = new GameObject("[Services]"); 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 ──────────────────────────────────────────────────────── CreatePanel(canvasGo.transform, "Background", new Color(0.08f, 0.08f, 0.12f), stretch: true); // ── Header (Top Bar) ────────────────────────────────────────────────── 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.08f, 0.9f)); var titleTxt = CreateTMPText(header.transform, "TitleText", "Simulator", 28, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(titleTxt.GetComponent(), new Vector2(0.3f, 0.1f), new Vector2(0.7f, 0.9f)); var startSimBtn = CreateTMPButton(header.transform, "StartSimButton", "Start Simulation", new Color(0.2f, 0.55f, 0.2f)); SetAnchors(startSimBtn.GetComponent(), new Vector2(0.82f, 0.1f), new Vector2(0.99f, 0.9f)); // ── Config Panel (left) ─────────────────────────────────────────────── var configPanel = CreatePanel(canvasGo.transform, "ConfigPanel", new Color(0.1f, 0.1f, 0.16f, 0.97f)); SetAnchors(configPanel.GetComponent(), new Vector2(0.01f, 0.3f), new Vector2(0.49f, 0.93f)); var cfgVlg = configPanel.AddComponent(); cfgVlg.padding = new RectOffset(16, 16, 16, 16); cfgVlg.spacing = 10; cfgVlg.childForceExpandWidth = true; cfgVlg.childForceExpandHeight = false; CreateTMPText(configPanel.transform, "ConfigTitle", "Simulation Config", 20, FontStyles.Bold, TextAlignmentOptions.Center); // Deck dropdowns var deckDropdown0 = CreateTMPDropdown(configPanel.transform, "DeckDropdown0", new[] { "-- Select Deck --" }); var deckDropdown1 = CreateTMPDropdown(configPanel.transform, "DeckDropdown1", new[] { "-- Select Deck --" }); var deckDropdown2 = CreateTMPDropdown(configPanel.transform, "DeckDropdown2", new[] { "-- Select Deck --" }); var deckDropdown3 = CreateTMPDropdown(configPanel.transform, "DeckDropdown3", new[] { "-- Select Deck --" }); // Num players slider var numPlayersLabel = CreateTMPText(configPanel.transform, "NumPlayersLabel", "Players: 2", 16, FontStyles.Normal, TextAlignmentOptions.Left); var numPlayersSlider = CreateSlider(configPanel.transform, "NumPlayersSlider"); // Num games input CreateTMPText(configPanel.transform, "NumGamesLabel", "Number of Games:", 16, FontStyles.Normal, TextAlignmentOptions.Left); var numGamesInput = CreateTMPInputField(configPanel.transform, "NumGamesInput", "100"); // Threads input CreateTMPText(configPanel.transform, "ThreadsLabel", "Threads:", 16, FontStyles.Normal, TextAlignmentOptions.Left); var threadsInput = CreateTMPInputField(configPanel.transform, "ThreadsInput", "4"); // AI Profile dropdown CreateTMPText(configPanel.transform, "AiProfileLabel", "AI Profile:", 16, FontStyles.Normal, TextAlignmentOptions.Left); var aiProfileDropdown = CreateTMPDropdown(configPanel.transform, "AiProfileDropdown", new[] { "Default" }); // ── Status Panel (center, hidden initially) ─────────────────────────── var statusPanel = CreatePanel(canvasGo.transform, "StatusPanel", new Color(0.09f, 0.09f, 0.14f, 0.97f)); SetAnchors(statusPanel.GetComponent(), new Vector2(0.01f, 0.06f), new Vector2(0.49f, 0.29f)); statusPanel.SetActive(false); var stVlg = statusPanel.AddComponent(); stVlg.padding = new RectOffset(12, 12, 10, 10); stVlg.spacing = 6; stVlg.childForceExpandWidth = true; stVlg.childForceExpandHeight = false; var statusText = CreateTMPText(statusPanel.transform, "StatusText", "Ready", 16, FontStyles.Normal, TextAlignmentOptions.TopLeft); var progressBar = CreateSlider(statusPanel.transform, "ProgressBar"); var progressText = CreateTMPText(statusPanel.transform, "ProgressText", "0%", 14, FontStyles.Normal, TextAlignmentOptions.Center); var elapsedText = CreateTMPText(statusPanel.transform, "ElapsedText", "Elapsed: 0s", 14, FontStyles.Normal, TextAlignmentOptions.Left); var simsPerSecText = CreateTMPText(statusPanel.transform, "SimsPerSecText", "0 sims/s", 14, FontStyles.Normal, TextAlignmentOptions.Left); // ── Results Panel (right, hidden initially) ─────────────────────────── var resultsPanel = CreatePanel(canvasGo.transform, "ResultsPanel", new Color(0.1f, 0.1f, 0.16f, 0.97f)); SetAnchors(resultsPanel.GetComponent(), new Vector2(0.51f, 0.06f), new Vector2(0.99f, 0.93f)); resultsPanel.SetActive(false); CreateTMPText(resultsPanel.transform, "ResultsTitle", "Results", 22, FontStyles.Bold, TextAlignmentOptions.Center); var winnerText = CreateTMPText(resultsPanel.transform, "WinnerText", "Winner: —", 18, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(winnerText.GetComponent(), new Vector2(0f, 0.88f), new Vector2(1f, 0.95f)); // Results scroll view var resultsScroll = new GameObject("ResultsScroll"); resultsScroll.transform.SetParent(resultsPanel.transform, false); SetAnchors(resultsScroll.GetComponent(), new Vector2(0f, 0.15f), new Vector2(1f, 0.88f)); ScrollRect resSr; var resultsContent = CreateScrollContent(resultsScroll, out resSr); var historyBtn = CreateTMPButton(resultsPanel.transform, "HistoryButton", "View History", new Color(0.2f, 0.4f, 0.7f)); SetAnchors(historyBtn.GetComponent(), new Vector2(0.2f, 0.03f), new Vector2(0.8f, 0.13f)); // ── Error Panel (hidden initially) ──────────────────────────────────── var errorPanel = CreatePanel(canvasGo.transform, "ErrorPanel", new Color(0.15f, 0.05f, 0.05f, 0.97f)); SetAnchors(errorPanel.GetComponent(), new Vector2(0.25f, 0.35f), new Vector2(0.75f, 0.65f)); errorPanel.SetActive(false); CreateTMPText(errorPanel.transform, "ErrorTitle", "Error", 22, FontStyles.Bold, TextAlignmentOptions.Center); var errorText = CreateTMPText(errorPanel.transform, "ErrorText", "", 16, FontStyles.Normal, TextAlignmentOptions.TopLeft); SetAnchors(errorText.GetComponent(), new Vector2(0.05f, 0.25f), new Vector2(0.95f, 0.85f)); var retryBtn = CreateTMPButton(errorPanel.transform, "RetryButton", "Retry", new Color(0.55f, 0.2f, 0.2f)); SetAnchors(retryBtn.GetComponent(), new Vector2(0.3f, 0.05f), new Vector2(0.7f, 0.22f)); // ── Result Row Prefab (disabled child object used as prefab) ────────── var resultRowPrefab = new GameObject("ResultRowPrefab"); resultRowPrefab.transform.SetParent(canvasGo.transform, false); resultRowPrefab.SetActive(false); var rowImg = resultRowPrefab.AddComponent(); rowImg.color = new Color(0.15f, 0.15f, 0.2f, 0.9f); var rowHlg = resultRowPrefab.AddComponent(); rowHlg.padding = new RectOffset(8, 8, 4, 4); rowHlg.spacing = 12; rowHlg.childForceExpandWidth = false; rowHlg.childForceExpandHeight = true; var rowLe = resultRowPrefab.AddComponent(); rowLe.minHeight = 40; string[] colNames = { "DeckName", "WinRate", "Wins", "Losses" }; float[] colWidths = { 300f, 120f, 100f, 100f }; for (int i = 0; i < colNames.Length; i++) { var cell = new GameObject(colNames[i]); cell.transform.SetParent(resultRowPrefab.transform, false); var cellTxt = cell.AddComponent(); cellTxt.text = colNames[i]; cellTxt.fontSize = 16; cellTxt.color = Color.white; cellTxt.alignment = TextAlignmentOptions.Left; var cellLe = cell.AddComponent(); cellLe.minWidth = colWidths[i]; cellLe.preferredWidth = colWidths[i]; cellLe.flexibleWidth = i == 0 ? 1f : 0f; } // ── Wire SimulationController via reflection ─────────────────────────── var controllerGo = new GameObject("SimulationController"); controllerGo.transform.SetParent(canvasGo.transform, false); var controller = controllerGo.AddComponent(); SetField(controller, "backButton", backBtn.GetComponent