157 lines
No EOL
4.8 KiB
C#
157 lines
No EOL
4.8 KiB
C#
using UnityEngine;
|
|
using R3;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.Pool;
|
|
using KitsuneCafe.System;
|
|
using KitsuneCafe.Extension;
|
|
|
|
namespace KitsuneCafe.UI
|
|
{
|
|
public class UISceneManager : MonoBehaviour
|
|
{
|
|
[SerializeField] private UiOrchestrator orchestrator;
|
|
|
|
[SerializeField] private Transform root;
|
|
[SerializeField] private PanelSettings panelSettings;
|
|
[SerializeField] private GameObject prefab;
|
|
|
|
private readonly Dictionary<ElementId, GameObject> activeElements = new();
|
|
private readonly Dictionary<VisualTreeAsset, IObjectPool<GameObject>> pools = new();
|
|
|
|
private void Awake()
|
|
{
|
|
var d = Disposable.CreateBuilder();
|
|
|
|
Observable.FromEvent<EventHandler<SpawnElementRequest>, SpawnElementRequest>(
|
|
h => (sender, e) => h(e),
|
|
e => orchestrator.SpawnRequested += e,
|
|
e => orchestrator.SpawnRequested -= e
|
|
).Subscribe(request =>
|
|
{
|
|
SpawnElement(request.Id, request.Element, request.Position);
|
|
})
|
|
.AddTo(ref d);
|
|
|
|
Observable.FromEvent<EventHandler<DespawnElementRequest>, DespawnElementRequest>(
|
|
h => (sender, e) => h(e),
|
|
e => orchestrator.DespawnRequested += e,
|
|
e => orchestrator.DespawnRequested -= e
|
|
)
|
|
.Select(request => request.Id)
|
|
.Subscribe(DespawnElement)
|
|
.AddTo(ref d);
|
|
|
|
d.RegisterTo(destroyCancellationToken);
|
|
}
|
|
|
|
private IObjectPool<GameObject> GetOrCreatePool(IUiElement element)
|
|
{
|
|
if (!pools.TryGetValue(element.VisualTreeAsset, out var pool))
|
|
{
|
|
pool = new ObjectPool<GameObject>(
|
|
() => CreatePoolObject(pool),
|
|
GetPoolObject,
|
|
ReleasePoolObject,
|
|
DestroyPoolObject,
|
|
collectionCheck: false,
|
|
defaultCapacity: 10,
|
|
maxSize: 100
|
|
);
|
|
|
|
pools.Add(element.VisualTreeAsset, pool);
|
|
}
|
|
return pool;
|
|
}
|
|
|
|
private GameObject CreatePoolObject(IObjectPool<GameObject> pool)
|
|
{
|
|
GameObject obj;
|
|
if (prefab != null)
|
|
{
|
|
obj = Instantiate(prefab);
|
|
}
|
|
else
|
|
{
|
|
obj = new GameObject("Pooled Object", typeof(UIDocument));
|
|
}
|
|
|
|
obj.AddComponent<UiElementInstance>();
|
|
|
|
var doc = obj.GetComponent<UIDocument>();
|
|
doc.panelSettings = panelSettings;
|
|
|
|
var poolObj = obj.AddComponent<PooledObject>();
|
|
poolObj.objectPool = pool;
|
|
|
|
obj.transform.SetParent(root);
|
|
|
|
return obj;
|
|
}
|
|
|
|
private void GetPoolObject(GameObject obj)
|
|
{
|
|
obj.SetActive(true);
|
|
}
|
|
|
|
private void ReleasePoolObject(GameObject obj)
|
|
{
|
|
obj.SetActive(false);
|
|
}
|
|
|
|
private void DestroyPoolObject(GameObject obj)
|
|
{
|
|
Destroy(obj);
|
|
}
|
|
|
|
private GameObject GetUiDocument(IUiElement element)
|
|
{
|
|
return GetOrCreatePool(element).Get();
|
|
}
|
|
|
|
private Observable<T> ObserveEvent<T>(VisualElement target) where T : EventBase<T>, new()
|
|
{
|
|
return Observable.FromEvent<EventCallback<T>, T>(
|
|
h => e => h(e),
|
|
e => target.RegisterCallback(e),
|
|
e => target.UnregisterCallback(e)
|
|
);
|
|
}
|
|
|
|
private void SpawnElement(ElementId id, IUiElement element, Vector3 worldPosition)
|
|
{
|
|
var obj = GetUiDocument(element);
|
|
|
|
var trans = obj.transform;
|
|
trans.SetParent(root);
|
|
trans.SetPositionAndRotation(worldPosition, Quaternion.identity);
|
|
trans.localScale = Vector3.one;
|
|
|
|
if (obj.TryGetComponent(out UIDocument doc) && obj.TryGetComponent(out UiElementInstance instance))
|
|
{
|
|
doc.visualTreeAsset = element.VisualTreeAsset;
|
|
doc.panelSettings = panelSettings;
|
|
Observable.EveryValueChanged(doc, d => d.rootVisualElement)
|
|
.WhereNotNull()
|
|
.Select(_ => doc)
|
|
.Subscribe(doc =>
|
|
{
|
|
instance.Configure(element, doc.rootVisualElement);
|
|
})
|
|
.AddTo(doc.gameObject);
|
|
}
|
|
|
|
activeElements[id] = obj;
|
|
}
|
|
|
|
private void DespawnElement(ElementId id)
|
|
{
|
|
if (activeElements.TryGetValue(id, out GameObject obj))
|
|
{
|
|
obj.GetComponent<PooledObject>().Release();
|
|
activeElements.Remove(id);
|
|
}
|
|
}
|
|
}
|
|
} |