164 lines
5.9 KiB
C#
164 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[Service(typeof(IBuildingVisualizationCollection))]
|
|
public class BuildingVisualizationManager : GameSystem, IInitializable, IDisposable, IBuildingVisualizationCollection
|
|
{
|
|
private const int SpatialLookupCellSize = 5;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
[InjectService]
|
|
private IScene _scene;
|
|
|
|
[InjectService]
|
|
private ITileSpace _tileSpace;
|
|
|
|
[InjectService]
|
|
private IEntityCollection _entityCollection;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
private HashSet<int> _pendingVisualizations = new();
|
|
|
|
private Dictionary<int, BuildingVisualization> _visualizations = new();
|
|
|
|
private SpatialLookup<GameObject> _allVisualizationsSpatialLookup = new(SpatialLookupCellSize);
|
|
|
|
private SpatialLookup<GameObject> _canBeDeletedSpatialLookup = new(SpatialLookupCellSize);
|
|
|
|
public BuildingVisualizationManager(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_signalBus.Subscribe<BuildingCreatedSignal>(OnBuildingCreated);
|
|
_signalBus.Subscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
|
_signalBus.Subscribe<BuildingDeletedSignal>(OnBuildingDeleted);
|
|
_signalBus.Subscribe<BuildingUpgradedSignal>(OnBuildingUpgraded);
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_signalBus.Unsubscribe<BuildingCreatedSignal>(OnBuildingCreated);
|
|
_signalBus.Unsubscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
|
_signalBus.Unsubscribe<BuildingDeletedSignal>(OnBuildingDeleted);
|
|
_signalBus.Unsubscribe<BuildingUpgradedSignal>(OnBuildingUpgraded);
|
|
}
|
|
|
|
private void OnBuildingCreated(BuildingCreatedSignal signal)
|
|
{
|
|
var building = signal.Building;
|
|
|
|
_pendingVisualizations.Add(building.Id);
|
|
|
|
_ = CreateVisualizationAsync(building);
|
|
}
|
|
|
|
private async UniTask CreateVisualizationAsync(Building building)
|
|
{
|
|
var folder = _scene.SceneFolders.Buildings;
|
|
var visualizationGameObject = await building.Definition.Visualization.InstantiateAsync(folder);
|
|
|
|
if (!_pendingVisualizations.Remove(building.Id))
|
|
{
|
|
building.Definition.Visualization.ReleaseInstance(visualizationGameObject);
|
|
return;
|
|
}
|
|
|
|
var visualization = visualizationGameObject.GetComponent<BuildingVisualization>();
|
|
if (!visualization)
|
|
{
|
|
Debug.LogError($"Building visualization '{visualizationGameObject.name}' has no {nameof(BuildingVisualization)} component");
|
|
return;
|
|
}
|
|
|
|
visualization.SetTier(0);
|
|
|
|
var position = _tileSpace.GetRectWorldCenter(building.Rect);
|
|
var rotation = building.Orientation.ToQuaternion();
|
|
visualization.transform.SetPositionAndRotation(position, rotation);
|
|
|
|
_visualizations.Add(building.Id, visualization);
|
|
_signalBus.Raise(new BuildingVisualizationCreatedSignal(building, visualization));
|
|
|
|
_allVisualizationsSpatialLookup.Add(visualization.gameObject, building.Rect, building.Id);
|
|
if (building.Definition.CanBeDeleted) _canBeDeletedSpatialLookup.Add(visualization.gameObject, building.Rect, building.Id);
|
|
}
|
|
|
|
private void OnCollectDeletedGameObjects(CollectDeletedGameObjectsSignal signal)
|
|
{
|
|
if ((signal.Filter & DeletedGameObjectsFilter.Buildings) == 0) return;
|
|
|
|
_canBeDeletedSpatialLookup.Find(signal.Rect, signal.GameObjects);
|
|
}
|
|
|
|
private void OnBuildingDeleted(BuildingDeletedSignal signal)
|
|
{
|
|
var building = signal.Building;
|
|
|
|
if (_pendingVisualizations.Remove(building.Id))
|
|
{
|
|
_signalBus.Raise(new BuildingDeleteAnimationCompletedSignal(building));
|
|
return;
|
|
}
|
|
|
|
_visualizations.Remove(building.Id, out var visualization);
|
|
_allVisualizationsSpatialLookup.Remove(building.Rect, building.Id);
|
|
_canBeDeletedSpatialLookup.Remove(building.Rect, building.Id);
|
|
|
|
if (signal.Options == DeleteBuildingOptions.Silent)
|
|
{
|
|
FinalizeBuildingDeletion(building, visualization);
|
|
return;
|
|
}
|
|
|
|
_ = PlayDeleteAnimationAsync(building, visualization);
|
|
}
|
|
|
|
private async UniTask PlayDeleteAnimationAsync(Building building, BuildingVisualization visualization)
|
|
{
|
|
var deleteAnimation = visualization.GetComponent<BuildingDeleteAnimation>();
|
|
await deleteAnimation.PlayAsync(building);
|
|
|
|
FinalizeBuildingDeletion(building, visualization);
|
|
}
|
|
|
|
private void FinalizeBuildingDeletion(Building building, BuildingVisualization visualization)
|
|
{
|
|
_signalBus.Raise(new BuildingDeleteAnimationCompletedSignal(building));
|
|
|
|
building.Definition.Visualization.ReleaseInstance(visualization.gameObject);
|
|
}
|
|
|
|
private void OnBuildingUpgraded(BuildingUpgradedSignal signal)
|
|
{
|
|
var building = signal.Building;
|
|
var visualization = _visualizations[building.Id];
|
|
|
|
visualization.SetTier(building.TierIndex);
|
|
|
|
if (visualization.TryGetComponent<BuildingUpgradeAnimation>(out var animation)) _ = animation.PlayAsync(building);
|
|
}
|
|
|
|
public bool IsVisualizationPending(int id)
|
|
{
|
|
return _pendingVisualizations.Contains(id);
|
|
}
|
|
|
|
public bool TryGetVisualization(int id, out BuildingVisualization visualization)
|
|
{
|
|
return _visualizations.TryGetValue(id, out visualization);
|
|
}
|
|
}
|
|
}
|