diff --git a/.gitignore b/.gitignore index 118097c..a9ed6b4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ /[Ll]ibrary/ /[Tt]emp/ /[Oo]bj/ -/DotNet/**/[Bb]in/ -/DotNet/**/[Oo]bj/ /TestResults/ /[Bb]uild/ /[Bb]uilds/ @@ -59,16 +57,6 @@ ExportedObj/ *.opendb *.VC.db -# Tracked source project for rebuilding ShrinkModFramework external DLL fixtures. -!Tools/ShrinkModFixtureBuilder/ShrinkModFixtureBuilder.csproj -Tools/ShrinkModFixtureBuilder/bin/ -Tools/ShrinkModFixtureBuilder/obj/ - -# Tracked standalone .NET projects for ShrinkEventBus runtime and generator validation. -!DotNet/ShrinkEventBus.Core/ShrinkEventBus.Core.csproj -!DotNet/ShrinkEventBus.Generator/ShrinkEventBus.Generator.csproj -!DotNet/ShrinkEventBus.Smoke/ShrinkEventBus.Smoke.csproj - # Unity3D generated meta files *.pidb.meta *.pdb.meta diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e53d03a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,84 @@ +[submodule "Assets/Modules/ShrinkApp.Core"] + path = Assets/Modules/ShrinkApp.Core + url = https://git.crash.work/ShrinkSDK/ShrinkApp.Core.git + branch = main +[submodule "Assets/Modules/ShrinkApp.Starter.Basic"] + path = Assets/Modules/ShrinkApp.Starter.Basic + url = https://git.crash.work/ShrinkSDK/ShrinkApp.Starter.Basic.git + branch = main +[submodule "Assets/Modules/ShrinkCommand"] + path = Assets/Modules/ShrinkCommand + url = https://git.crash.work/ShrinkSDK/ShrinkCommand.git + branch = main +[submodule "Assets/Modules/ShrinkCommand.Integration.App"] + path = Assets/Modules/ShrinkCommand.Integration.App + url = https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.App.git + branch = main +[submodule "Assets/Modules/ShrinkCommand.Integration.EventBus"] + path = Assets/Modules/ShrinkCommand.Integration.EventBus + url = https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.EventBus.git + branch = main +[submodule "Assets/Modules/ShrinkCommand.Integration.Network"] + path = Assets/Modules/ShrinkCommand.Integration.Network + url = https://git.crash.work/ShrinkSDK/ShrinkCommand.Integration.Network.git + branch = main +[submodule "Assets/Modules/ShrinkContext.AppAdapter"] + path = Assets/Modules/ShrinkContext.AppAdapter + url = https://git.crash.work/ShrinkSDK/ShrinkContext.AppAdapter.git + branch = main +[submodule "Assets/Modules/ShrinkContext.Core"] + path = Assets/Modules/ShrinkContext.Core + url = https://git.crash.work/ShrinkSDK/ShrinkContext.Core.git + branch = main +[submodule "Assets/Modules/ShrinkContext.EventBusAdapter"] + path = Assets/Modules/ShrinkContext.EventBusAdapter + url = https://git.crash.work/ShrinkSDK/ShrinkContext.EventBusAdapter.git + branch = main +[submodule "Assets/Modules/ShrinkDataSaver"] + path = Assets/Modules/ShrinkDataSaver + url = https://git.crash.work/ShrinkSDK/ShrinkDataSaver.git + branch = main +[submodule "Assets/Modules/ShrinkDataSaver.Integration.App"] + path = Assets/Modules/ShrinkDataSaver.Integration.App + url = https://git.crash.work/ShrinkSDK/ShrinkDataSaver.Integration.App.git + branch = main +[submodule "Assets/Modules/ShrinkDataSaver.Integration.EventBus"] + path = Assets/Modules/ShrinkDataSaver.Integration.EventBus + url = https://git.crash.work/ShrinkSDK/ShrinkDataSaver.Integration.EventBus.git + branch = main +[submodule "Assets/Modules/ShrinkEventBus"] + path = Assets/Modules/ShrinkEventBus + url = https://git.crash.work/ShrinkSDK/ShrinkEventBus.git + branch = main +[submodule "Assets/Modules/ShrinkEventBus.Entities"] + path = Assets/Modules/ShrinkEventBus.Entities + url = https://git.crash.work/ShrinkSDK/ShrinkEventBus.Entities.git + branch = main +[submodule "Assets/Modules/ShrinkModFramework"] + path = Assets/Modules/ShrinkModFramework + url = https://git.crash.work/ShrinkSDK/ShrinkModFramework.git + branch = main +[submodule "Assets/Modules/ShrinkNetwork"] + path = Assets/Modules/ShrinkNetwork + url = https://git.crash.work/ShrinkSDK/ShrinkNetwork.git + branch = main +[submodule "Assets/Modules/ShrinkNetwork.Integration.App"] + path = Assets/Modules/ShrinkNetwork.Integration.App + url = https://git.crash.work/ShrinkSDK/ShrinkNetwork.Integration.App.git + branch = main +[submodule "Assets/Modules/ShrinkNetwork.Integration.EventBus"] + path = Assets/Modules/ShrinkNetwork.Integration.EventBus + url = https://git.crash.work/ShrinkSDK/ShrinkNetwork.Integration.EventBus.git + branch = main +[submodule "Assets/Modules/ShrinkShared.CodeGen"] + path = Assets/Modules/ShrinkShared.CodeGen + url = https://git.crash.work/ShrinkSDK/ShrinkShared.CodeGen.git + branch = main +[submodule "Assets/Modules/ShrinkTutorial"] + path = Assets/Modules/ShrinkTutorial + url = https://git.crash.work/ShrinkSDK/ShrinkTutorial.git + branch = main +[submodule "Assets/Modules/ShrinkInstaller"] + path = Assets/Modules/ShrinkInstaller + url = https://git.crash.work/ShrinkSDK/Installer.git + branch = main diff --git a/Assets/Modules/ShrinkApp.Core b/Assets/Modules/ShrinkApp.Core new file mode 160000 index 0000000..35acaca --- /dev/null +++ b/Assets/Modules/ShrinkApp.Core @@ -0,0 +1 @@ +Subproject commit 35acaca8584e0d9b74be571ff0519801719929d0 diff --git a/Assets/Modules/ShrinkApp.Core/CHANGELOG.md b/Assets/Modules/ShrinkApp.Core/CHANGELOG.md deleted file mode 100644 index 6723b34..0000000 --- a/Assets/Modules/ShrinkApp.Core/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# Changelog - -本文件记录 `ShrinkApp.Core` 的包内变更。 - -## [0.1.1] - 2026-08-16 - -### Added - -- `ShrinkAppSettings.hostingMode`(`ShrinkAppHostingMode`):`ClassicHost` 保持原有自动启动;`ContextLoader` 让位给 ShrinkContext 加载器宿主(见 `ShrinkContext.AppAdapter`),支持运行中按模块 disable/enable。 -- `ShrinkApp.InitializeForExternalHost(services, settings)`:外部宿主把服务容器接回 `ShrinkApp.Services` 静态入口。 -- `ShrinkAppInstallers.GetDiscoveredInstallerTypes()`:编译期安装器发现的公共入口,供外部宿主枚举。 -- `ShrinkAppContext.CreateStandalone(services, settings)`:非 MonoBehaviour 宿主构建上下文。 - -### Changed - -- `Bootstrap` 在 `ContextLoader` 模式下直接返回,经典路径零行为变化。 - -## [0.1.0] - 2026-05-18 - -### Added - -- 新增统一宿主层 `ShrinkApp.Core`。 -- 新增 `ShrinkApp`、`ShrinkAppHost`、`ShrinkAppSettings`、`ShrinkAppServices`、`ShrinkAppContext`。 -- 新增模块安装器契约:`IShrinkAppModuleInstaller` 与 `[ShrinkAppModuleInstaller]`。 -- 新增运行时生命周期事件:`ShrinkAppStartedEvent`、`ShrinkAppStartFailedEvent`。 diff --git a/Assets/Modules/ShrinkApp.Core/CHANGELOG.md.meta b/Assets/Modules/ShrinkApp.Core/CHANGELOG.md.meta deleted file mode 100644 index 5c6f252..0000000 --- a/Assets/Modules/ShrinkApp.Core/CHANGELOG.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3557769562f2f7042a462bcf44b9fedf -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Editor.meta b/Assets/Modules/ShrinkApp.Core/Editor.meta deleted file mode 100644 index 218b5d8..0000000 --- a/Assets/Modules/ShrinkApp.Core/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 346774b237ebc2b49bc74a69b150780e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef b/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef deleted file mode 100644 index c8b5011..0000000 --- a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "ShrinkApp.Core.Editor", - "rootNamespace": "ShrinkApp.Editor", - "references": [ - "ShrinkApp.Core.Runtime" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} diff --git a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef.meta b/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef.meta deleted file mode 100644 index d500713..0000000 --- a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkApp.Core.Editor.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d16f21ff20129e14283877a81cca3054 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs b/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs deleted file mode 100644 index e95c817..0000000 --- a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs +++ /dev/null @@ -1,39 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace ShrinkApp.Editor -{ - public static class ShrinkAppEditorMenu - { - [MenuItem("ShrinkApp/创建 Settings")] - public static void CreateSettingsAsset() - { - const string resourcesDir = "Assets/Resources"; - if (!AssetDatabase.IsValidFolder(resourcesDir)) - AssetDatabase.CreateFolder("Assets", "Resources"); - - const string assetPath = "Assets/Resources/ShrinkAppSettings.asset"; - var existing = AssetDatabase.LoadAssetAtPath(assetPath); - if (existing != null) - { - Selection.activeObject = existing; - EditorGUIUtility.PingObject(existing); - return; - } - - // 旧版本曾生成过 m_Script=fileID:0 的无效占位资产。删除该占位后 - // 才能在同一路径创建真正绑定 ShrinkAppSettings 类型的资产。 - if (!string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(assetPath))) - AssetDatabase.DeleteAsset(assetPath); - - var asset = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(asset, assetPath); - AssetDatabase.SaveAssets(); - Selection.activeObject = asset; - EditorGUIUtility.PingObject(asset); - Debug.Log("[ShrinkApp] 已创建 ShrinkAppSettings.asset"); - } - } -} -#endif diff --git a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs.meta b/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs.meta deleted file mode 100644 index b182ab1..0000000 --- a/Assets/Modules/ShrinkApp.Core/Editor/ShrinkAppEditorMenu.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 30f867e31a8e02e41b25f1ef5b4dddec -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/README.md b/Assets/Modules/ShrinkApp.Core/README.md deleted file mode 100644 index 3213240..0000000 --- a/Assets/Modules/ShrinkApp.Core/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# ShrinkApp.Core - -`ShrinkApp.Core` 是 `Shrink` 系列模块的统一宿主层。它不直接替代各个基础包的独立使用方式,而是在项目需要“导入一组包后直接起盘”时,提供统一的启动链、模块安装器、服务容器和基础生命周期事件。 - -## 当前定位 - -- 统一宿主:在 `BeforeSceneLoad` 阶段创建 `ShrinkAppHost` -- 模块安装器:通过编译期注入的安装器注册表获取 `IShrinkAppModuleInstaller` -- 服务容器:各模块通过 `RegisterServices(...)` 暴露门面服务 -- 生命周期事件:通过 `ShrinkEventBus` 发布 `ShrinkAppStartedEvent` / `ShrinkAppStartFailedEvent` - -## 核心类型 - -```csharp -ShrinkApp -ShrinkAppHost -ShrinkAppSettings -ShrinkAppServices -ShrinkAppContext -IShrinkAppModuleInstaller -[ShrinkAppModuleInstaller] -``` - -## 启动流程 - -1. `ShrinkApp` 在 `RuntimeInitializeOnLoadMethod(BeforeSceneLoad)` 创建宿主。 -2. 宿主从编译期注册表 `ShrinkAppGeneratedRegistry` 读取全部安装器类型。 -3. 安装器按 `DependsOn + Order` 排序。 -4. 先执行 `RegisterServices(...)`,再顺序执行 `InitializeAsync(...)`。 -5. 启动完成后在首场景 `Start()` 阶段发布 `ShrinkAppStartedEvent`。 -6. 任一安装器重复、依赖缺失、循环依赖、初始化异常都会 fail-fast。 diff --git a/Assets/Modules/ShrinkApp.Core/README.md.meta b/Assets/Modules/ShrinkApp.Core/README.md.meta deleted file mode 100644 index 8efa3a2..0000000 --- a/Assets/Modules/ShrinkApp.Core/README.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 271d3627f55ae2b498a8b430db8d2b41 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef deleted file mode 100644 index 18b3716..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "ShrinkApp.Core.Runtime", - "rootNamespace": "ShrinkApp", - "references": [ - "ShrinkEventBus.Runtime", - "UniTask" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef.meta deleted file mode 100644 index 3d3abf1..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.Core.Runtime.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b5b7047dbc0ca2e438a92daa2baa200c -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs deleted file mode 100644 index 9e96ba4..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs +++ /dev/null @@ -1,81 +0,0 @@ -#nullable enable - -using System; -using Cysharp.Threading.Tasks; -using UnityEngine; - -namespace ShrinkApp -{ - public static class ShrinkApp - { - public static ShrinkAppHost? Host { get; private set; } - public static ShrinkAppContext? Context { get; private set; } - public static ShrinkAppSettings Settings => ShrinkAppSettings.Instance; - public static ShrinkAppServices Services => Context?.Services ?? throw new System.InvalidOperationException("ShrinkApp is not initialized."); - public static bool IsRunning => (Host != null && Host.IsRunning) || _externalHostRunning; - - private static bool _externalHostRunning; - - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] - private static void ResetStaticState() - { - Host = null; - Context = null; - _externalHostRunning = false; - ShrinkAppSettings.ResetCachedInstance(); - } - - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - private static void Bootstrap() - { - if (Host != null) - return; - - var settings = ShrinkAppSettings.Instance; - if (settings.hostingMode == ShrinkAppHostingMode.ContextLoader) - { - // 阶段 2 过渡:经典宿主让位,由 ShrinkContext 加载器宿主(ShrinkContext.AppAdapter)接管启动 - return; - } - - var hostGameObject = new GameObject("ShrinkAppHost"); - var host = hostGameObject.AddComponent(); - if (settings.dontDestroyOnLoad) - UnityEngine.Object.DontDestroyOnLoad(hostGameObject); - - var services = new ShrinkAppServices(); - var context = new ShrinkAppContext(host, settings, services); - host.Configure(context); - - Host = host; - Context = context; - host.StartAppAsync().Forget(ex => - { - Debug.LogException(ex); - Debug.LogError("[ShrinkApp] 启动失败: " + ex.Message); - }); - } - - /// - /// 阶段 2 过渡:由外部宿主(如 ShrinkContext 加载器宿主)提供已初始化的服务容器。 - /// Host 保持 null——外部宿主不经过 ShrinkAppHost 生命周期,IsRunning 以外部宿主为准。 - /// - public static void InitializeForExternalHost(ShrinkAppServices services, ShrinkAppSettings? settings = null) - { - if (services == null) - throw new ArgumentNullException(nameof(services)); - - Context = new ShrinkAppContext(null!, settings ?? Settings, services); - _externalHostRunning = false; - } - - /// - /// Lets a non- orchestrator expose its lifecycle through - /// the legacy static facade while the migration is in progress. - /// - public static void SetExternalHostRunning(bool running) - { - _externalHostRunning = running; - } - } -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs.meta deleted file mode 100644 index d44777f..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 10523dad09cece4438f29620b3253fdb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs deleted file mode 100644 index 8d79f3c..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs +++ /dev/null @@ -1,53 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ShrinkApp -{ - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class ShrinkAppInstallerRegistryAttribute : Attribute - { - public ShrinkAppInstallerRegistryAttribute(params Type[] installerTypes) - { - InstallerTypes = installerTypes ?? Array.Empty(); - } - - public Type[] InstallerTypes { get; } - } - - internal static class ShrinkAppGeneratedRegistry - { - public static IReadOnlyList GetInstallerTypes() - { - var types = new List(); - var seen = new HashSet(); - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - object[] attributes; - try - { - attributes = assembly.GetCustomAttributes(typeof(ShrinkAppInstallerRegistryAttribute), false); - } - catch - { - continue; - } - - foreach (var attribute in attributes.OfType()) - { - foreach (var installerType in attribute.InstallerTypes ?? Array.Empty()) - { - if (installerType == null || !seen.Add(installerType)) - continue; - - types.Add(installerType); - } - } - } - - return types; - } - } -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs.meta deleted file mode 100644 index 0ee7d05..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppGeneratedRegistry.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1818116c8e85f5e489c0c4955f506ff2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs deleted file mode 100644 index 33adaae..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs +++ /dev/null @@ -1,167 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; -using Cysharp.Threading.Tasks; -using ShrinkEventBus; -using UnityEngine; - -namespace ShrinkApp -{ - public sealed class ShrinkAppHost : MonoBehaviour - { - private readonly List _startedModules = new(); - private ShrinkAppContext? _context; - private bool _unityStarted; - private bool _publishedStartedEvent; - - public bool IsRunning { get; private set; } - public bool HasFailed { get; private set; } - public string LastError { get; private set; } = string.Empty; - public IReadOnlyList StartedModules => _startedModules; - - internal void Configure(ShrinkAppContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } - - internal async UniTask StartAppAsync() - { - if (IsRunning || HasFailed) - return; - if (_context == null) - throw new InvalidOperationException("ShrinkAppHost is not configured."); - - var installers = CreateInstallerInstances(); - var orderedInstallers = SortInstallers(installers, _context.Settings); - - try - { - foreach (var installer in orderedInstallers) - installer.RegisterServices(_context); - - foreach (var installer in orderedInstallers) - { - await installer.InitializeAsync(_context); - _startedModules.Add(installer.ModuleId); - } - - IsRunning = true; - PublishStartedEventIfReady(); - } - catch (Exception ex) - { - HasFailed = true; - LastError = ex.Message; - EventBus.Post(new ShrinkAppStartFailedEvent - { - ErrorMessage = ex.Message, - FailedModuleId = _startedModules.LastOrDefault() ?? string.Empty - }); - throw; - } - } - - private void Start() - { - _unityStarted = true; - PublishStartedEventIfReady(); - } - - private void PublishStartedEventIfReady() - { - if (_publishedStartedEvent || !_unityStarted || !IsRunning) - return; - - _publishedStartedEvent = true; - EventBus.Post(new ShrinkAppStartedEvent - { - ModuleIds = _startedModules.ToArray() - }); - } - - private static IReadOnlyList CreateInstallerInstances() - { - var installers = new List(); - foreach (var installerType in ShrinkAppGeneratedRegistry.GetInstallerTypes()) - { - if (installerType == null) - continue; - if (!typeof(IShrinkAppModuleInstaller).IsAssignableFrom(installerType)) - throw new InvalidOperationException($"Installer type does not implement IShrinkAppModuleInstaller: {installerType.FullName}"); - if (installerType.IsAbstract) - throw new InvalidOperationException($"Installer type cannot be abstract: {installerType.FullName}"); - - if (Activator.CreateInstance(installerType) is not IShrinkAppModuleInstaller installer) - throw new InvalidOperationException($"Failed to create installer: {installerType.FullName}"); - - installers.Add(installer); - } - - return installers; - } - - private static IReadOnlyList SortInstallers( - IReadOnlyList installers, - ShrinkAppSettings settings) - { - var disabled = new HashSet( - settings.disabledModuleIds?.Where(id => !string.IsNullOrWhiteSpace(id)).Select(id => id.Trim()) ?? - Enumerable.Empty(), - StringComparer.OrdinalIgnoreCase); - - var enabledInstallers = installers - .Where(installer => !disabled.Contains(installer.ModuleId)) - .ToArray(); - - var byId = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var installer in enabledInstallers) - { - if (string.IsNullOrWhiteSpace(installer.ModuleId)) - throw new InvalidOperationException($"Installer {installer.GetType().FullName} has an empty ModuleId."); - if (!byId.TryAdd(installer.ModuleId.Trim(), installer)) - throw new InvalidOperationException($"Duplicate installer ModuleId: {installer.ModuleId}"); - } - - var visitState = new Dictionary(StringComparer.OrdinalIgnoreCase); - var ordered = new List(); - foreach (var installer in enabledInstallers.OrderBy(item => item.Order).ThenBy(item => item.ModuleId, StringComparer.OrdinalIgnoreCase)) - { - Visit(installer, byId, visitState, ordered); - } - - return ordered; - } - - private static void Visit( - IShrinkAppModuleInstaller installer, - IReadOnlyDictionary byId, - IDictionary visitState, - IList ordered) - { - var state = visitState.TryGetValue(installer.ModuleId, out var existingState) ? existingState : 0; - if (state == 2) - return; - if (state == 1) - throw new InvalidOperationException($"Circular installer dependency detected at module: {installer.ModuleId}"); - - visitState[installer.ModuleId] = 1; - foreach (var dependencyId in installer.DependsOn ?? Array.Empty()) - { - if (string.IsNullOrWhiteSpace(dependencyId)) - continue; - - if (!byId.TryGetValue(dependencyId.Trim(), out var dependency)) - throw new InvalidOperationException( - $"Installer dependency missing. Module={installer.ModuleId}, DependsOn={dependencyId}"); - - Visit(dependency, byId, visitState, ordered); - } - - visitState[installer.ModuleId] = 2; - if (!ordered.Contains(installer)) - ordered.Add(installer); - } - } -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs.meta deleted file mode 100644 index 3d7ab55..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppHost.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: df43c81d962edd64cbd214b2697b4179 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs deleted file mode 100644 index fbf277f..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs +++ /dev/null @@ -1,16 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; - -namespace ShrinkApp -{ - /// - /// 编译期发现的应用模块安装器类型(公共入口)。 - /// 经典 ShrinkAppHost 与外部宿主(ShrinkContext 加载器宿主)共用同一份发现结果。 - /// - public static class ShrinkAppInstallers - { - public static IReadOnlyList GetDiscoveredInstallerTypes() => - ShrinkAppGeneratedRegistry.GetInstallerTypes(); - } -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs.meta deleted file mode 100644 index 2ea0f8d..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppInstallers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c22f2e857d66bae458ff3dd6d9519d0d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs deleted file mode 100644 index 28159b1..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs +++ /dev/null @@ -1,181 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; -using Cysharp.Threading.Tasks; -using ShrinkEventBus; -using UnityEngine; - -namespace ShrinkApp -{ - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] - public sealed class ShrinkAppModuleInstallerAttribute : Attribute - { - } - - public interface IShrinkAppModuleInstaller - { - string ModuleId { get; } - int Order { get; } - IReadOnlyList DependsOn { get; } - void RegisterServices(ShrinkAppContext context); - UniTask InitializeAsync(ShrinkAppContext context); - } - - public sealed class ShrinkAppContext - { - internal ShrinkAppContext(ShrinkAppHost host, ShrinkAppSettings settings, ShrinkAppServices services) - { - Host = host; - Settings = settings; - Services = services; - } - - /// - /// 为非 MonoBehaviour 宿主(如 ShrinkContext 纤程适配器)构建上下文。 - /// Host 为 null:适用于不经过 ShrinkAppHost 启动流的独立编排场景。 - /// - public static ShrinkAppContext CreateStandalone(ShrinkAppServices services, ShrinkAppSettings? settings = null) - { - if (services == null) - throw new ArgumentNullException(nameof(services)); - return new ShrinkAppContext(null!, settings ?? ShrinkAppSettings.Instance, services); - } - - public ShrinkAppHost Host { get; } - public ShrinkAppSettings Settings { get; } - public ShrinkAppServices Services { get; } - } - - public sealed class ShrinkAppServices - { - private readonly Dictionary _services = new(); - - public void Register(TService service) where TService : class - { - if (service == null) - throw new ArgumentNullException(nameof(service)); - - _services[typeof(TService)] = service; - } - - public bool TryGet(out TService? service) where TService : class - { - if (_services.TryGetValue(typeof(TService), out var boxed) && boxed is TService typed) - { - service = typed; - return true; - } - - service = null; - return false; - } - - /// - /// Removes a service only when the current registration is the supplied instance. - /// This lets context-driven components expose the legacy service facade as a - /// reversible effect without removing a newer replacement during teardown. - /// - public bool TryUnregister(TService service) where TService : class - { - if (service == null) - throw new ArgumentNullException(nameof(service)); - - if (!_services.TryGetValue(typeof(TService), out var current) || - !ReferenceEquals(current, service)) - return false; - - return _services.Remove(typeof(TService)); - } - - public TService GetRequired() where TService : class - { - if (!TryGet(out var service) || service == null) - throw new InvalidOperationException($"Required service is not registered: {typeof(TService).FullName}"); - - return service; - } - - public IReadOnlyList GetRegisteredServiceTypeNames() - { - return _services.Keys - .Select(type => type.FullName ?? type.Name) - .OrderBy(name => name, StringComparer.OrdinalIgnoreCase) - .ToArray(); - } - } - - /// ShrinkApp 的宿主模式(阶段 2 过渡:两种模式并存,按项目选择)。 - public enum ShrinkAppHostingMode - { - /// 经典模式:ShrinkAppHost 在 BeforeSceneLoad 自动创建并按拓扑序启动安装器。 - ClassicHost = 0, - - /// 加载器模式:经典宿主让位,由 ShrinkContext 加载器宿主(ShrinkContext.AppAdapter)接管启动, - /// 支持运行中按模块 disable/enable 与依赖响应式等待。 - ContextLoader = 1, - } - - [CreateAssetMenu(fileName = "ShrinkAppSettings", menuName = "ShrinkApp/Settings")] - public class ShrinkAppSettings : ScriptableObject - { - private static ShrinkAppSettings? _instance; - - public static ShrinkAppSettings Instance - { - get - { - if (_instance != null) - return _instance; - - _instance = Resources.Load("ShrinkAppSettings"); - -#if UNITY_EDITOR - if (!_instance) - { - var guids = UnityEditor.AssetDatabase.FindAssets("t:ShrinkAppSettings"); - if (guids.Length > 0) - { - var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]); - _instance = UnityEditor.AssetDatabase.LoadAssetAtPath(path); - } - } -#endif - - if (!_instance) - { - _instance = CreateInstance(); - Debug.LogWarning( - "[ShrinkApp] 未找到 ShrinkAppSettings,当前使用默认配置。建议通过 Assets -> Create -> ShrinkApp -> Settings 创建配置。"); - } - - return _instance!; - } - internal set => _instance = value; - } - - internal static void ResetCachedInstance() - { - _instance = null; - } - - public bool dontDestroyOnLoad = true; - public bool verboseLogging; - public string[] disabledModuleIds = Array.Empty(); - - [Tooltip("宿主模式:ClassicHost 为经典自动启动;ContextLoader 由 ShrinkContext 加载器宿主接管(阶段 2 过渡)")] - public ShrinkAppHostingMode hostingMode = ShrinkAppHostingMode.ClassicHost; - } - - public sealed class ShrinkAppStartedEvent : IShrinkEvent - { - public IReadOnlyList ModuleIds { get; set; } = Array.Empty(); - } - - public sealed class ShrinkAppStartFailedEvent : IShrinkEvent - { - public string ErrorMessage { get; set; } = string.Empty; - public string FailedModuleId { get; set; } = string.Empty; - } -} diff --git a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs.meta b/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs.meta deleted file mode 100644 index c988efd..0000000 --- a/Assets/Modules/ShrinkApp.Core/Runtime/ShrinkAppTypes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 384dd878beec6b848b64aa843b464e95 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Core/package.json b/Assets/Modules/ShrinkApp.Core/package.json deleted file mode 100644 index e8ebe78..0000000 --- a/Assets/Modules/ShrinkApp.Core/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "com.cneicy.shrink-app-core", - "version": "0.1.1", - "displayName": "ShrinkApp Core", - "description": "Shrink 系列统一宿主层,提供模块安装器、服务容器与统一启动流程。", - "unity": "2022.3", - "dependencies": { - "com.cneicy.shrink-eventbus": "2.0.0", - "com.cneicy.shrink-shared-codegen": "0.1.0", - "com.cysharp.unitask": "2.5.10" - }, - "keywords": [ - "app", - "bootstrap", - "framework", - "host", - "starter" - ], - "author": { - "name": "cneicy", - "url": "https://github.com/cneicy" - } -} diff --git a/Assets/Modules/ShrinkApp.Core/package.json.meta b/Assets/Modules/ShrinkApp.Core/package.json.meta deleted file mode 100644 index 55828d4..0000000 --- a/Assets/Modules/ShrinkApp.Core/package.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 30fa106725f9afc46af98aff2ee92198 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Starter.Basic b/Assets/Modules/ShrinkApp.Starter.Basic new file mode 160000 index 0000000..88e70ee --- /dev/null +++ b/Assets/Modules/ShrinkApp.Starter.Basic @@ -0,0 +1 @@ +Subproject commit 88e70eef0eeb9ceaede042888003b6f275440be4 diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md b/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md deleted file mode 100644 index 0b1bc05..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md +++ /dev/null @@ -1,15 +0,0 @@ -# Changelog - -本文件记录 `ShrinkApp.Starter.Basic` 的包内变更。 - -## [0.1.0] - 2026-05-18 - -### Added - -- 新增最小起盘 Starter 包。 -- 新增场景生成器 `ShrinkAppBasicStarterGenerator`。 -- 新增示例控制器 `ShrinkAppBasicSampleController`。 -- 新增 `ShrinkAppBasicDemoRuntime`,补齐默认命令源、状态命令与最小 loopback 网络示例。 -- 新增 `ShrinkAppBasicStarterSettings`,提供最小 Starter 级别的默认配置资产。 -- 示例场景继续扩展为小型调试台,补齐命令输入、输出日志、模块/服务/存档/命令/网络状态面板。 -- 状态面板进一步细化为已启动模块、已注册服务、存档槽位、命令列表、网络诊断五块只读视图。 diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md.meta b/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md.meta deleted file mode 100644 index eba6b24..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/CHANGELOG.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e3e78d4720b16b84fbf0d766b0a0122b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/Editor.meta b/Assets/Modules/ShrinkApp.Starter.Basic/Editor.meta deleted file mode 100644 index ffcd571..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f6be676789111fd4a9afd67b011a12c9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef b/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef deleted file mode 100644 index 73fa11f..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "ShrinkApp.Starter.Basic.Editor", - "rootNamespace": "ShrinkApp.Starter.Basic.Editor", - "references": [ - "ShrinkApp.Starter.Basic.Runtime", - "ShrinkApp.Core.Runtime", - "ShrinkApp.Core.Editor", - "ShrinkContext.AppAdapter.Runtime", - "ShrinkDataSaver.Runtime", - "ShrinkDataSaver.Integration.App", - "UnityEngine.UI" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef.meta b/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef.meta deleted file mode 100644 index 0b63870..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkApp.Starter.Basic.Editor.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: aa988409913004043b6cbe3d19de32bd -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkAppBasicStarterGenerator.cs b/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkAppBasicStarterGenerator.cs deleted file mode 100644 index a6394bb..0000000 --- a/Assets/Modules/ShrinkApp.Starter.Basic/Editor/ShrinkAppBasicStarterGenerator.cs +++ /dev/null @@ -1,248 +0,0 @@ -#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