riversong code showcase
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user