Files
Hasebe/Assets/Code/Infrastructure/UI/UIFactory.cs
T
2026-10-23 16:15:02 +03:00

120 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.Configs;
using Code.Infrastructure.Utils;
using Cysharp.Threading.Tasks;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
namespace Code.Infrastructure.UI
{
public interface IUIFactory
{
// Новый
Canvas GameplayCanvas { get; }
// Тот что был создан на сцене
Canvas Canvas { get; }
UniTask<UIPanel> LoadPanel(UIPanelType panelType, bool gameplayCanvas, Transform parent = null);
}
public interface IUIFactoryInitializer
{
UniTask LoadConfigs();
void SetCanvas(Canvas canvas);
void SetCanvasCamera(UnityEngine.Camera camera);
}
public class UIFactory : IDisposable, IUIFactory, IUIFactoryInitializer
{
private Dictionary<UIPanelType, UIPanelSettings> _configs;
private readonly AssetReference _canvasConfigReference;
private readonly string _configsLabel;
private AsyncOperationHandle<IList<UIPanelSettings>> _configsHandle;
private AsyncOperationHandle<CanvasSettings> _canvasSettingsHandle;
private CanvasSettings _canvasConfig;
private GameObject _gameplayCanvas;
public Canvas GameplayCanvas { get; private set; }
public Canvas Canvas { get; private set; }
public UIFactory(IConfigLocator configLocator)
{
_configsLabel = configLocator.TryGetManyConfigAssetReferences<UIPanelSettings>();
_canvasConfigReference = configLocator.TryGetConfigAssetReference<CanvasSettings>();
}
public void SetCanvas(Canvas canvas)
{
Canvas = canvas;
UnityEngine.Object.DontDestroyOnLoad(canvas.gameObject);
}
public void SetCanvasCamera(UnityEngine.Camera camera)
{
Canvas.worldCamera = camera;
Canvas.planeDistance = 0.1f;
GameplayCanvas.worldCamera = camera;
}
public async UniTask<UIPanel> LoadPanel(UIPanelType panelType, bool gameplayCanvas, Transform parent = null)
{
var panel = (await Addressables.InstantiateAsync(_configs[panelType].Prefab,
parent ?? gameplayCanvas ? _gameplayCanvas.transform : Canvas.transform).ToUniTask())
.GetComponent<UIPanel>();
panel.PanelType = panelType;
return panel;
}
public async UniTask LoadConfigs()
{
if (await AddressablesUtilities.CheckLabelExists(_configsLabel)) await LoadPanelConfigs();
_canvasSettingsHandle = Addressables.LoadAssetAsync<CanvasSettings>(_canvasConfigReference);
await _canvasSettingsHandle.ToUniTask();
_canvasConfig = _canvasSettingsHandle.Result;
_gameplayCanvas = new GameObject { name = "GameplayCanvas" };
UnityEngine.Object.DontDestroyOnLoad(_gameplayCanvas);
GameplayCanvas = _gameplayCanvas.AddComponent<Canvas>();
GameplayCanvas.renderMode = _canvasConfig.RenderMode;
GameplayCanvas.sortingOrder = _canvasConfig.OrderInLayer;
GameplayCanvas.planeDistance = _canvasConfig.PlaneDistance;
var scaler = GameplayCanvas.AddComponent<CanvasScaler>();
scaler.uiScaleMode = _canvasConfig.ScaleMode;
scaler.referenceResolution =
new Vector2(_canvasConfig.ReferenceResolutionX, _canvasConfig.ReferenceResolutionY);
GameplayCanvas.AddComponent<GraphicRaycaster>();
}
private async UniTask LoadPanelConfigs()
{
_configsHandle = Addressables.LoadAssetsAsync<UIPanelSettings>(_configsLabel);
await _configsHandle.ToUniTask();
_configs = _configsHandle.Result.ToDictionary(c => c.UIPanelType);
}
public void Dispose()
{
if (_configsHandle.IsValid())
Addressables.Release(_configsHandle);
if (_canvasSettingsHandle.IsValid())
Addressables.Release(_canvasSettingsHandle);
if (_gameplayCanvas)
Addressables.ReleaseInstance(_gameplayCanvas);
}
}
}