#if UNITY_EDITOR using ShrinkApp.Editor; using ShrinkContext.AppAdapter; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.UI; namespace ShrinkApp.Starter.Basic.Editor { public static class ShrinkAppBasicStarterGenerator { private const string MenuPath = "ShrinkApp/Starter/生成 Basic Entry 场景"; private const string CompositionMenuPath = "ShrinkApp/Starter/创建默认 Cordis Composition"; private const string CompositionPath = "Assets/Resources/ShrinkAppComposition.asset"; [MenuItem(MenuPath)] public static void Generate() { EnsureAssets(); BuildScene(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log("[ShrinkApp.Starter.Basic] 已生成 Basic Entry 场景与配置。"); } [MenuItem(CompositionMenuPath)] public static void CreateDefaultCompositionAsset() { EnsureResourcesDirectory(); var existing = AssetDatabase.LoadAssetAtPath(CompositionPath); if (existing != null) { Selection.activeObject = existing; return; } // 修复脚本/asmdef 变更期间可能留下的无主 .asset,而不是在同一路径叠加创建。 if (!string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(CompositionPath))) AssetDatabase.DeleteAsset(CompositionPath); var composition = ScriptableObject.CreateInstance(); composition.SetDocument(ShrinkAppBasicContextComposition.CreateDefaultDocument()); AssetDatabase.CreateAsset(composition, CompositionPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Selection.activeObject = composition; } private static void EnsureAssets() { ShrinkAppEditorMenu.CreateSettingsAsset(); EnsureResourcesDirectory(); const string dataSaverSettingsPath = "Assets/Resources/ShrinkDataSaverSettings.asset"; if (AssetDatabase.LoadAssetAtPath(dataSaverSettingsPath) == null) { var asset = ScriptableObject.CreateInstance("ShrinkDataSaverSettings"); if (asset == null) throw new System.InvalidOperationException( "Cannot create ShrinkDataSaverSettings. Ensure ShrinkDataSaver.Runtime is imported and compiled."); AssetDatabase.CreateAsset(asset, dataSaverSettingsPath); } const string starterSettingsPath = "Assets/Resources/ShrinkAppBasicStarterSettings.asset"; if (AssetDatabase.LoadAssetAtPath(starterSettingsPath) == null) { var starterAsset = ScriptableObject.CreateInstance(); starterAsset.autoBindLoopbackTransport = true; starterAsset.defaultCommandText = "starter status"; starterAsset.defaultLoopbackSessionId = 1; starterAsset.logCommandOutputToConsole = true; starterAsset.maxCommandOutputLines = 12; AssetDatabase.CreateAsset(starterAsset, starterSettingsPath); } CreateDefaultCompositionAsset(); } private static void EnsureResourcesDirectory() { const string resourcesDir = "Assets/Resources"; if (!AssetDatabase.IsValidFolder(resourcesDir)) AssetDatabase.CreateFolder("Assets", "Resources"); } private static void BuildScene() { const string scenesDir = "Assets/Scenes"; if (!AssetDatabase.IsValidFolder(scenesDir)) AssetDatabase.CreateFolder("Assets", "Scenes"); var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); new GameObject("Main Camera", typeof(Camera)); new GameObject("EventSystem", typeof(UnityEngine.EventSystems.EventSystem), typeof(UnityEngine.EventSystems.StandaloneInputModule)); var canvasGo = new GameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster)); var canvas = canvasGo.GetComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; var scaler = canvasGo.GetComponent(); scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(1920, 1080); var panelGo = new GameObject("Panel", typeof(RectTransform), typeof(Image)); panelGo.transform.SetParent(canvasGo.transform, false); var panelRect = panelGo.GetComponent(); panelRect.sizeDelta = new Vector2(980f, 720f); panelRect.anchoredPosition = Vector2.zero; panelGo.GetComponent().color = new Color(0.12f, 0.15f, 0.2f, 0.92f); var statusText = CreateText("StatusText", panelGo.transform, new Vector2(0f, 240f), new Vector2(840f, 120f), "ShrinkApp Basic starter ready."); statusText.alignment = TextAnchor.MiddleCenter; var detailText = CreateText("DetailText", panelGo.transform, new Vector2(0f, 135f), new Vector2(840f, 140f), "app=False, save=False, cmd=False, net=False"); detailText.alignment = TextAnchor.UpperLeft; detailText.fontSize = 20; var commandInputField = CreateInputField("CommandInput", panelGo.transform, new Vector2(0f, 20f), new Vector2(520f, 54f), "starter status"); var outputText = CreateText("OutputText", panelGo.transform, new Vector2(0f, -250f), new Vector2(840f, 180f), string.Empty); outputText.alignment = TextAnchor.UpperLeft; outputText.fontSize = 20; outputText.horizontalOverflow = HorizontalWrapMode.Wrap; outputText.verticalOverflow = VerticalWrapMode.Overflow; var saveMetaText = CreateText("SaveMetaText", panelGo.transform, new Vector2(-280f, -430f), new Vector2(240f, 150f), "No save slots found."); saveMetaText.alignment = TextAnchor.UpperLeft; saveMetaText.fontSize = 18; var moduleText = CreateText("ModuleText", panelGo.transform, new Vector2(0f, -430f), new Vector2(240f, 150f), "No started modules."); moduleText.alignment = TextAnchor.UpperLeft; moduleText.fontSize = 18; var serviceText = CreateText("ServiceText", panelGo.transform, new Vector2(280f, -430f), new Vector2(240f, 150f), "No registered services."); serviceText.alignment = TextAnchor.UpperLeft; serviceText.fontSize = 18; var commandListText = CreateText("CommandListText", panelGo.transform, new Vector2(-280f, -600f), new Vector2(240f, 150f), "Command service not ready."); commandListText.alignment = TextAnchor.UpperLeft; commandListText.fontSize = 18; var networkText = CreateText("NetworkText", panelGo.transform, new Vector2(280f, -600f), new Vector2(240f, 150f), "Network service not ready."); networkText.alignment = TextAnchor.UpperLeft; networkText.fontSize = 18; var saveButton = CreateButton("SaveButton", panelGo.transform, new Vector2(-250f, -70f), "Save Slot 0"); var loadButton = CreateButton("LoadButton", panelGo.transform, new Vector2(0f, -70f), "Load Slot 0"); var commandButton = CreateButton("CommandButton", panelGo.transform, new Vector2(250f, -70f), "Run Command"); var loopbackButton = CreateButton("LoopbackButton", panelGo.transform, new Vector2(-250f, -165f), "Bind Loopback"); var disconnectButton = CreateButton("DisconnectLoopbackButton", panelGo.transform, new Vector2(0f, -165f), "Disconnect Loopback"); var refreshButton = CreateButton("RefreshButton", panelGo.transform, new Vector2(250f, -165f), "Refresh Status"); var clearOutputButton = CreateButton("ClearOutputButton", panelGo.transform, new Vector2(0f, -345f), "Clear Output"); var controller = panelGo.AddComponent(); var serializedObject = new SerializedObject(controller); serializedObject.FindProperty("statusText").objectReferenceValue = statusText; serializedObject.FindProperty("detailText").objectReferenceValue = detailText; serializedObject.FindProperty("outputText").objectReferenceValue = outputText; serializedObject.FindProperty("moduleText").objectReferenceValue = moduleText; serializedObject.FindProperty("serviceText").objectReferenceValue = serviceText; serializedObject.FindProperty("saveMetaText").objectReferenceValue = saveMetaText; serializedObject.FindProperty("commandListText").objectReferenceValue = commandListText; serializedObject.FindProperty("networkText").objectReferenceValue = networkText; serializedObject.FindProperty("saveButton").objectReferenceValue = saveButton; serializedObject.FindProperty("loadButton").objectReferenceValue = loadButton; serializedObject.FindProperty("commandButton").objectReferenceValue = commandButton; serializedObject.FindProperty("loopbackButton").objectReferenceValue = loopbackButton; serializedObject.FindProperty("refreshButton").objectReferenceValue = refreshButton; serializedObject.FindProperty("clearOutputButton").objectReferenceValue = clearOutputButton; serializedObject.FindProperty("disconnectLoopbackButton").objectReferenceValue = disconnectButton; serializedObject.FindProperty("commandInputField").objectReferenceValue = commandInputField; serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorSceneManager.SaveScene(scene, "Assets/Scenes/ShrinkAppEntry.unity"); } private static Text CreateText(string name, Transform parent, Vector2 anchoredPosition, Vector2 size, string text) { var go = new GameObject(name, typeof(RectTransform), typeof(Text)); go.transform.SetParent(parent, false); var rect = go.GetComponent(); rect.sizeDelta = size; rect.anchoredPosition = anchoredPosition; var label = go.GetComponent(); label.text = text; label.font = Resources.GetBuiltinResource("LegacyRuntime.ttf"); label.fontSize = 28; label.color = Color.white; return label; } private static Button CreateButton(string name, Transform parent, Vector2 anchoredPosition, string labelText) { var go = new GameObject(name, typeof(RectTransform), typeof(Image), typeof(Button)); go.transform.SetParent(parent, false); var rect = go.GetComponent(); rect.sizeDelta = new Vector2(220f, 72f); rect.anchoredPosition = anchoredPosition; go.GetComponent().color = new Color(0.24f, 0.45f, 0.75f, 1f); var label = CreateText("Label", go.transform, Vector2.zero, new Vector2(220f, 72f), labelText); label.alignment = TextAnchor.MiddleCenter; label.resizeTextForBestFit = true; label.resizeTextMinSize = 18; label.resizeTextMaxSize = 28; return go.GetComponent