#if UNITY_EDITOR using UnityEngine; using UnityEngine.UI; using UnityEditor; using UnityEditor.SceneManagement; using TMPro; using System.Reflection; using System.Linq; public static class CreateTrainingScene { [MenuItem("Tools/Create Training Scene")] public static void Create() { var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single); var services = new GameObject("[Services]"); services.AddComponent(); 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(); } CreatePanel(canvasGo.transform, "Background", new Color(0.05f, 0.05f, 0.08f), stretch: true); // Header var header = CreatePanel(canvasGo.transform, "Header", new Color(0.12f, 0.12f, 0.18f)); 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 title = CreateTMPText(header.transform, "TitleText", "ML Training Dashboard", 28, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(title.GetComponent(), new Vector2(0.1f, 0.1f), new Vector2(0.9f, 0.9f)); // Left column: Stats + Controls var leftCol = CreatePanel(canvasGo.transform, "LeftColumn", new Color(0.08f, 0.08f, 0.12f)); SetAnchors(leftCol.GetComponent(), new Vector2(0f, 0.01f), new Vector2(0.28f, 0.92f)); // Stats panel var statsPanel = CreatePanel(leftCol.transform, "StatsPanel", new Color(0.12f, 0.12f, 0.18f)); SetAnchors(statsPanel.GetComponent(), new Vector2(0.02f, 0.72f), new Vector2(0.98f, 0.99f)); var statsTitle = CreateTMPText(statsPanel.transform, "StatsTitle", "TRAINING DATA", 16, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(statsTitle.GetComponent(), new Vector2(0f, 0.78f), new Vector2(1f, 1f)); var cardCountTxt = CreateTMPText(statsPanel.transform, "CardCountText", "Cards: --", 14, FontStyles.Normal, TextAlignmentOptions.Left); SetAnchors(cardCountTxt.GetComponent(), new Vector2(0.05f, 0.55f), new Vector2(0.95f, 0.77f)); var sessionCountTxt = CreateTMPText(statsPanel.transform, "SessionCountText", "Sessions: --", 14, FontStyles.Normal, TextAlignmentOptions.Left); SetAnchors(sessionCountTxt.GetComponent(), new Vector2(0.05f, 0.33f), new Vector2(0.95f, 0.55f)); var modelVerTxt = CreateTMPText(statsPanel.transform, "ModelVersionText", "Model: --", 14, FontStyles.Normal, TextAlignmentOptions.Left); SetAnchors(modelVerTxt.GetComponent(), new Vector2(0.05f, 0.11f), new Vector2(0.95f, 0.33f)); var lastTrainedTxt = CreateTMPText(statsPanel.transform, "LastTrainedText", "Last trained: --", 12, FontStyles.Normal, TextAlignmentOptions.Left); SetAnchors(lastTrainedTxt.GetComponent(), new Vector2(0.05f, 0f), new Vector2(0.95f, 0.11f)); // Controls panel var ctrlPanel = CreatePanel(leftCol.transform, "ControlsPanel", new Color(0.12f, 0.12f, 0.18f)); SetAnchors(ctrlPanel.GetComponent(), new Vector2(0.02f, 0.42f), new Vector2(0.98f, 0.71f)); var statusTxt = CreateTMPText(ctrlPanel.transform, "StatusText", "Ready.", 13, FontStyles.Normal, TextAlignmentOptions.Center); SetAnchors(statusTxt.GetComponent(), new Vector2(0.02f, 0.75f), new Vector2(0.98f, 1f)); var startBtn = CreateTMPButton(ctrlPanel.transform, "StartTrainingButton", "Start Training", new Color(0.1f, 0.5f, 0.1f)); SetAnchors(startBtn.GetComponent(), new Vector2(0.05f, 0.45f), new Vector2(0.95f, 0.73f)); var stopBtn = CreateTMPButton(ctrlPanel.transform, "StopTrainingButton", "Stop", new Color(0.5f, 0.1f, 0.1f)); SetAnchors(stopBtn.GetComponent(), new Vector2(0.05f, 0.15f), new Vector2(0.95f, 0.43f)); var exportBtn = CreateTMPButton(ctrlPanel.transform, "ExportModelButton", "Export Model", new Color(0.2f, 0.3f, 0.5f)); SetAnchors(exportBtn.GetComponent(), new Vector2(0.05f, 0.01f), new Vector2(0.95f, 0.14f)); // Center column: Live Charts var centerCol = CreatePanel(canvasGo.transform, "CenterColumn", new Color(0.08f, 0.08f, 0.12f)); SetAnchors(centerCol.GetComponent(), new Vector2(0.29f, 0.01f), new Vector2(0.69f, 0.92f)); var accLabel = CreateTMPText(centerCol.transform, "AccuracyLabel", "Accuracy: --", 14, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(accLabel.GetComponent(), new Vector2(0f, 0.87f), new Vector2(1f, 0.93f)); var accChart = CreatePanel(centerCol.transform, "AccuracyChart", new Color(0.05f, 0.15f, 0.05f)); SetAnchors(accChart.GetComponent(), new Vector2(0.02f, 0.5f), new Vector2(0.98f, 0.86f)); var lossLabel = CreateTMPText(centerCol.transform, "LossLabel", "Loss: --", 14, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(lossLabel.GetComponent(), new Vector2(0f, 0.43f), new Vector2(1f, 0.49f)); var lossChart = CreatePanel(centerCol.transform, "LossChart", new Color(0.15f, 0.05f, 0.05f)); SetAnchors(lossChart.GetComponent(), new Vector2(0.02f, 0.06f), new Vector2(0.98f, 0.42f)); // Feature importance title var featTitle = CreateTMPText(centerCol.transform, "FeatureTitle", "Feature Importance", 13, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(featTitle.GetComponent(), new Vector2(0f, 0.01f), new Vector2(1f, 0.05f)); // Right column: Model History + Log var rightCol = CreatePanel(canvasGo.transform, "RightColumn", new Color(0.08f, 0.08f, 0.12f)); SetAnchors(rightCol.GetComponent(), new Vector2(0.7f, 0.01f), new Vector2(1f, 0.92f)); // History panel var histPanel = CreatePanel(rightCol.transform, "HistoryPanel", new Color(0.12f, 0.12f, 0.18f)); SetAnchors(histPanel.GetComponent(), new Vector2(0.02f, 0.52f), new Vector2(0.98f, 0.99f)); var histTitle = CreateTMPText(histPanel.transform, "HistoryTitle", "MODEL HISTORY", 15, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(histTitle.GetComponent(), new Vector2(0f, 0.88f), new Vector2(1f, 1f)); var histScrollGo = new GameObject("HistoryScroll"); histScrollGo.transform.SetParent(histPanel.transform, false); var histScroll = histScrollGo.AddComponent(); var histScrollRT = histScrollGo.GetComponent(); SetAnchors(histScrollRT, new Vector2(0.01f, 0.01f), new Vector2(0.99f, 0.87f)); var histContent = new GameObject("Content"); histContent.transform.SetParent(histScrollGo.transform, false); var histContentRT = histContent.AddComponent(); histContentRT.anchorMin = Vector2.zero; histContentRT.anchorMax = new Vector2(1f, 0f); histContentRT.pivot = new Vector2(0.5f, 0f); histContent.AddComponent().spacing = 4; histContent.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; histScroll.content = histContentRT; histScroll.vertical = true; histScroll.horizontal = false; // Log panel var logPanel = CreatePanel(rightCol.transform, "LogPanel", new Color(0.06f, 0.06f, 0.06f)); SetAnchors(logPanel.GetComponent(), new Vector2(0.02f, 0.01f), new Vector2(0.98f, 0.51f)); var logTitle = CreateTMPText(logPanel.transform, "LogTitle", "TRAINING LOG", 14, FontStyles.Bold, TextAlignmentOptions.Center); SetAnchors(logTitle.GetComponent(), new Vector2(0f, 0.88f), new Vector2(1f, 1f)); var logScrollGo = new GameObject("LogScroll"); logScrollGo.transform.SetParent(logPanel.transform, false); var logScroll = logScrollGo.AddComponent(); SetAnchors(logScrollGo.GetComponent(), new Vector2(0.01f, 0.01f), new Vector2(0.99f, 0.87f)); var logContent = new GameObject("LogContent"); logContent.transform.SetParent(logScrollGo.transform, false); var logContentRT = logContent.AddComponent(); logContentRT.anchorMin = Vector2.zero; logContentRT.anchorMax = new Vector2(1f, 0f); logContentRT.pivot = new Vector2(0.5f, 0f); var logText = logContent.AddComponent(); logText.fontSize = 11; logText.color = new Color(0.7f, 1f, 0.7f); logText.text = ""; logContent.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; logScroll.content = logContentRT; logScroll.vertical = true; logScroll.horizontal = false; // Error panel var errorPanel = CreatePanel(canvasGo.transform, "ErrorPanel", new Color(0.4f, 0.05f, 0.05f, 0.95f)); SetAnchors(errorPanel.GetComponent(), new Vector2(0.3f, 0.4f), new Vector2(0.7f, 0.6f)); errorPanel.SetActive(false); var errorTxt = CreateTMPText(errorPanel.transform, "ErrorText", "", 16, FontStyles.Normal, TextAlignmentOptions.Center); SetAnchors(errorTxt.GetComponent(), new Vector2(0.05f, 0.1f), new Vector2(0.95f, 0.9f)); // Wire up TrainingController var controllerGo = new GameObject("TrainingController"); controllerGo.transform.SetParent(canvasGo.transform, false); var ctrl = controllerGo.AddComponent(); SetPrivateField(ctrl, "backButton", backBtn.GetComponent