using System; using System.Collections.Generic; using System.Linq; using Code.Infrastructure.Configs; using Code.Infrastructure.EventBus; using Cysharp.Threading.Tasks; using Unity.Cinemachine; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using Object = UnityEngine.Object; namespace Code.Infrastructure.Camera { public class CameraFactory : IDisposable { private AsyncOperationHandle _configHandle; private GameCameraConfig _config; private AssetReference _gameCameraConfigReference; private AsyncOperationHandle> _settingsConfigsHandle; private Dictionary _settingsConfigs; private string _cameraConfigsLabel; private EventBus.EventBus _eventBus; private UnityEngine.Camera _camera; private Dictionary _cinemachines = new(); public CameraFactory(IConfigLocator configLocator, EventBus.EventBus eventBus) { _gameCameraConfigReference = configLocator.TryGetConfigAssetReference(); _cameraConfigsLabel = configLocator.TryGetManyConfigAssetReferences(); _eventBus = eventBus; } public async UniTaskVoid CreateCameraStateMachine(CameraStateMachine stateMachine) { _settingsConfigsHandle = Addressables .LoadAssetsAsync(_cameraConfigsLabel, null, Addressables.MergeMode.Union); await _settingsConfigsHandle.ToUniTask(); _settingsConfigs = _settingsConfigsHandle.Result.ToDictionary(x => x.cameraMode); _configHandle = Addressables.LoadAssetAsync(_gameCameraConfigReference); await _configHandle.ToUniTask(); _config = _configHandle.Result; var cameraObject = await Addressables.InstantiateAsync(_config.Camera).ToUniTask(); _camera = cameraObject.GetComponent(); cameraObject.GetComponent().StateMachine = stateMachine; Object.DontDestroyOnLoad(cameraObject); _eventBus.RaiseEvent(x => x.CameraInitialized(new(_camera, _settingsConfigs))); } public async UniTaskVoid LoadCinemachineCamera(CameraMode cameraMode) { var cinemachine = await Addressables.InstantiateAsync(_settingsConfigs[cameraMode].cinemachineCamera); Object.DontDestroyOnLoad(cinemachine); _cinemachines[cameraMode] = cinemachine.GetComponent(); _eventBus.RaiseEvent(x=> x.CinemachineLoaded(_cinemachines[cameraMode])); } public CinemachineCamera GetCinematicCamera(CameraMode cameraMode) => _cinemachines[cameraMode]; public void ReleaseCinemachineCamera(CameraMode cameraMode) { Addressables.Release(_cinemachines[cameraMode].gameObject); } public void Dispose() { Addressables.Release(_configHandle); Addressables.Release(_settingsConfigsHandle); Addressables.ReleaseInstance(_camera.gameObject); } } public interface ICinematicMachineHandle : IGlobalSubscriber { void CinemachineLoaded(CinemachineCamera cinemachineCamera); } }