2026-03-26 16:14:05 +08:00
|
|
|
using System;
|
2025-09-05 19:46:30 +08:00
|
|
|
using System.Linq;
|
|
|
|
|
using AlicizaX.Resource.Runtime;
|
|
|
|
|
using AlicizaX;
|
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using Object = UnityEngine.Object;
|
|
|
|
|
|
|
|
|
|
namespace AlicizaX.UI.Runtime
|
|
|
|
|
{
|
|
|
|
|
public static class UIHolderFactory
|
|
|
|
|
{
|
2026-03-26 16:14:05 +08:00
|
|
|
private static IResourceService ResourceService => AppServices.Require<IResourceService>();
|
2026-03-31 17:25:20 +08:00
|
|
|
private static bool AllowLegacyResourcesFallback => UnityEngine.Application.isEditor || UnityEngine.Debug.isDebugBuild;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
2025-11-13 17:46:20 +08:00
|
|
|
public static async UniTask<T> CreateUIHolderAsync<T>(Transform parent) where T : UIHolderObjectBase
|
2025-09-05 19:46:30 +08:00
|
|
|
{
|
|
|
|
|
if (UIResRegistry.TryGet(typeof(T).TypeHandle, out UIResRegistry.UIResInfo resInfo))
|
|
|
|
|
{
|
|
|
|
|
GameObject obj = await LoadUIResourcesAsync(resInfo, parent);
|
|
|
|
|
|
|
|
|
|
return obj.GetComponent<T>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 17:46:20 +08:00
|
|
|
public static T CreateUIHolderSync<T>(Transform parent) where T : UIHolderObjectBase
|
|
|
|
|
{
|
|
|
|
|
if (UIResRegistry.TryGet(typeof(T).TypeHandle, out UIResRegistry.UIResInfo resInfo))
|
|
|
|
|
{
|
|
|
|
|
GameObject obj = LoadUIResourcesSync(resInfo, parent);
|
|
|
|
|
|
|
|
|
|
return obj.GetComponent<T>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-09-05 19:46:30 +08:00
|
|
|
internal static async UniTask<GameObject> LoadUIResourcesAsync(UIResRegistry.UIResInfo resInfo, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
return resInfo.LoadType == EUIResLoadType.AssetBundle
|
2026-03-26 16:14:05 +08:00
|
|
|
? await ResourceService.LoadGameObjectAsync(resInfo.Location, parent)
|
2026-03-31 17:25:20 +08:00
|
|
|
: await LoadResourceWithFallbackAsync(resInfo.Location, parent);
|
2025-09-05 19:46:30 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-13 17:46:20 +08:00
|
|
|
internal static GameObject LoadUIResourcesSync(UIResRegistry.UIResInfo resInfo, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
return resInfo.LoadType == EUIResLoadType.AssetBundle
|
2026-03-26 16:14:05 +08:00
|
|
|
? ResourceService.LoadGameObject(resInfo.Location, parent)
|
2026-03-31 17:25:20 +08:00
|
|
|
: LoadResourceWithFallbackSync(resInfo.Location, parent);
|
2025-11-13 17:46:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal static async UniTask CreateUIResourceAsync(UIMetadata meta, Transform parent, UIBase owner = null)
|
2025-09-05 19:46:30 +08:00
|
|
|
{
|
|
|
|
|
if (meta.State != UIState.CreatedUI) return;
|
|
|
|
|
GameObject obj = await LoadUIResourcesAsync(meta.ResInfo, parent);
|
2026-03-17 17:15:31 +08:00
|
|
|
if (meta.CancellationToken.IsCancellationRequested || meta.View == null || meta.State != UIState.CreatedUI)
|
|
|
|
|
{
|
|
|
|
|
if (obj != null)
|
|
|
|
|
{
|
|
|
|
|
Object.Destroy(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 19:46:30 +08:00
|
|
|
ValidateAndBind(meta, obj, owner);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 17:46:20 +08:00
|
|
|
internal static void CreateUIResourceSync(UIMetadata meta, Transform parent, UIBase owner = null)
|
2025-09-05 19:46:30 +08:00
|
|
|
{
|
|
|
|
|
if (meta.State != UIState.CreatedUI) return;
|
2025-11-13 17:46:20 +08:00
|
|
|
GameObject obj = LoadUIResourcesSync(meta.ResInfo, parent);
|
2025-09-05 19:46:30 +08:00
|
|
|
ValidateAndBind(meta, obj, owner);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 17:46:20 +08:00
|
|
|
private static async UniTask<GameObject> InstantiateResourceAsync(string location, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
GameObject prefab = (GameObject)await Resources.LoadAsync<GameObject>(location);
|
|
|
|
|
return Object.Instantiate(prefab, parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static GameObject InstantiateResourceSync(string location, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
GameObject prefab = Resources.Load<GameObject>(location);
|
|
|
|
|
return Object.Instantiate(prefab, parent);
|
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
|
2026-03-31 17:25:20 +08:00
|
|
|
private static async UniTask<GameObject> LoadResourceWithFallbackAsync(string location, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var managedObject = await ResourceService.LoadGameObjectAsync(location, parent);
|
|
|
|
|
if (managedObject != null)
|
|
|
|
|
{
|
|
|
|
|
return managedObject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
if (!AllowLegacyResourcesFallback)
|
|
|
|
|
{
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!AllowLegacyResourcesFallback)
|
|
|
|
|
{
|
|
|
|
|
throw new NullReferenceException($"UI resource load failed via IResourceService: {location}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return await InstantiateResourceAsync(location, parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static GameObject LoadResourceWithFallbackSync(string location, Transform parent)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var managedObject = ResourceService.LoadGameObject(location, parent);
|
|
|
|
|
if (managedObject != null)
|
|
|
|
|
{
|
|
|
|
|
return managedObject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
if (!AllowLegacyResourcesFallback)
|
|
|
|
|
{
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!AllowLegacyResourcesFallback)
|
|
|
|
|
{
|
|
|
|
|
throw new NullReferenceException($"UI resource load failed via IResourceService: {location}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return InstantiateResourceSync(location, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 19:46:30 +08:00
|
|
|
private static void ValidateAndBind(UIMetadata meta, GameObject holderObject, UIBase owner)
|
|
|
|
|
{
|
|
|
|
|
if (!holderObject) throw new NullReferenceException($"UI resource load failed: {meta.ResInfo.Location}");
|
|
|
|
|
|
|
|
|
|
var holder = (UIHolderObjectBase)holderObject.GetComponent(meta.View.UIHolderType);
|
|
|
|
|
|
|
|
|
|
if (holder == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidCastException($"资源{holderObject.name}上不存在{meta.View.UIHolderType.FullName}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta.View?.BindUIHolder(holder, owner);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|