using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using BITKit; using BITKit.Entities; using Cinemachine; using Cysharp.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using ParadoxNotion; using UnityEngine; using UnityEngine.InputSystem; namespace Net.Project.B.Dialogue { public class UnityDialogueCameraController : MonoBehaviour { [SerializeField] private CinemachineVirtualCameraBase virtualCamera; [SerializeField] private bool allowPlayerInput; [SerializeField] private bool isFixedCameraPosition; private readonly ValidHandle _allowCamera = new(); private readonly Dictionary _dialogues = new(); private CancellationTokenSource _dialogueCancel; private CinemachineTargetGroup _targetGroup; private readonly ConcurrentDictionary _actors = new(); private async void Start() { virtualCamera.enabled = false; if (isFixedCameraPosition) { var newGameObject = new GameObject(nameof(CinemachineTargetGroup)) { transform = { parent = transform.parent } }; _targetGroup =newGameObject.AddComponent(); virtualCamera.LookAt = _targetGroup.transform; } try { await BITApp.WalkUntilInitialize.Task.AttachExternalCancellation(destroyCancellationToken); } catch (OperationCanceledException) { } var dialogueService = BITApp.ServiceProvider.GetRequiredService(); dialogueService.OnDialogueStart += OnDialogueStart; dialogueService.OnDialogueEnd += OnDialogueEnd; _allowCamera.AddListener(x=>virtualCamera.enabled=x); if (allowPlayerInput is false) { _allowCamera.AddListener(x => { BITInputSystem.AllowInput.SetDisableElements(this, x); }); } await destroyCancellationToken.WaitUntilCanceled(); dialogueService.OnDialogueStart -= OnDialogueStart; dialogueService.OnDialogueEnd -= OnDialogueEnd; } private async void OnDialogueEnd(IDialogueData arg) { _allowCamera.AddElement(64); _dialogueCancel?.Cancel(); _dialogueCancel = new CancellationTokenSource(); _dialogues.TryRemove(arg.Identity); _allowCamera.RemoveElement(arg.Identity); try { await UniTask.Delay(512, cancellationToken: _dialogueCancel.Token); } catch (OperationCanceledException) { if (_dialogues.Count is not 0) return; } _allowCamera.RemoveElement(64); try { if (isFixedCameraPosition) { if (_actors.TryGetValue(arg.ActorIdentity, out var actor)) { await UniTask.Delay(1000, cancellationToken: destroyCancellationToken); if (actor) { _targetGroup.RemoveMember(actor); } } } } catch ( OperationCanceledException) { } } private UniTask OnDialogueStart(IDialogueData arg) { _allowCamera.AddElement(arg.Identity); SetCameraLook(arg); _dialogues.TryAdd(arg.Identity, arg); return UniTask.CompletedTask; } private void SetCameraLook(IDialogueData arg) { var entitiesService = BITApp.ServiceProvider.GetRequiredService(); if (_allowCamera.Allow) { if (_actors.TryGetValue(arg.ActorIdentity, out var actor)) { if (isFixedCameraPosition) { _targetGroup.AddMember(actor,1,1); } else { virtualCamera.LookAt = actor; } return; } if (entitiesService.TryGetEntity(arg.ActorIdentity, out var entity) is false) { foreach (var (id,localPlayer) in entitiesService.QueryComponents()) { entitiesService.TryGetEntity(id.Id, out entity); } } if (entity.ServiceProvider.GetService() is { } entityTransform) { if (isFixedCameraPosition) { _targetGroup.AddMember(entityTransform,1,1); } else { virtualCamera.LookAt = virtualCamera.Follow = entityTransform; } _actors.TryAdd(arg.ActorIdentity, entityTransform); } } } } }