128 lines
4.7 KiB
C#
128 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.Pool;
|
|
using Object = UnityEngine.Object;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[Service(typeof(IRawResourceVisualizationCollection))]
|
|
public class RawResourceRenderingSystem : GameSystem, IInitializable, IDisposable, IRawResourceVisualizationCollection, IOnWorldGenerationCompletedCallback
|
|
{
|
|
private const int MaxCreatedPerUpdate = 16;
|
|
|
|
[InjectService]
|
|
private IScene _scene;
|
|
|
|
[InjectService]
|
|
private IGameDatabase _gameDatabase;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
[InjectService]
|
|
private GameConfig _config;
|
|
|
|
private Dictionary<int, GameObject> _visualizationsById = new();
|
|
|
|
public RawResourceRenderingSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_signalBus.Subscribe<WorldGenerationCompletedSignal>(OnWorldGenerationCompleted);
|
|
_signalBus.Subscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
|
_signalBus.Subscribe<RawResourcesRemovedSignal>(OnRawResourcesRemoved);
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_signalBus.Unsubscribe<WorldGenerationCompletedSignal>(OnWorldGenerationCompleted);
|
|
_signalBus.Unsubscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
|
_signalBus.Unsubscribe<RawResourcesRemovedSignal>(OnRawResourcesRemoved);
|
|
}
|
|
|
|
private void OnWorldGenerationCompleted(WorldGenerationCompletedSignal signal)
|
|
{
|
|
signal.Callbacks.Add(this);
|
|
}
|
|
|
|
public async UniTask OnWorldGenerationCompletedAsync(World world)
|
|
{
|
|
await CreateVisualizationsAsync();
|
|
}
|
|
|
|
private async UniTask CreateVisualizationsAsync()
|
|
{
|
|
var visualizationCount = 0;
|
|
|
|
foreach (var resourceNode in _world.RawResources)
|
|
{
|
|
var definition = _gameDatabase.WithId<ResourceNodeDefinition>(resourceNode.DefinitionId);
|
|
|
|
var rotation = definition.RandomRotation ? Quaternion.Euler(0, Random.Range(0, 360), 0) : resourceNode.Orientation.ToQuaternion();
|
|
var scale = Vector3.one * Random.Range(definition.ScaleRange.x, definition.ScaleRange.y);
|
|
|
|
GameObject prefab;
|
|
if (definition.Prefab.IsValid())
|
|
prefab = (GameObject)definition.Prefab.Asset;
|
|
else
|
|
prefab = await definition.Prefab.LoadAssetAsync<GameObject>();
|
|
|
|
var visualization = Object.Instantiate(prefab, _scene.SceneFolders.RawResources);
|
|
visualization.transform.SetPositionAndRotation(resourceNode.Position, rotation);
|
|
visualization.transform.localScale = Vector3.Scale(visualization.transform.localScale, scale);
|
|
|
|
_visualizationsById.Add(resourceNode.Id, visualization);
|
|
|
|
if (++visualizationCount % MaxCreatedPerUpdate == 0) await UniTask.NextFrame();
|
|
}
|
|
}
|
|
|
|
private void OnCollectDeletedGameObjects(CollectDeletedGameObjectsSignal signal)
|
|
{
|
|
if ((signal.Filter & DeletedGameObjectsFilter.RawResources) == 0) return;
|
|
|
|
using var resourceNodesScope = ListPool<(int, bool)>.Get(out var resourceNodeIds);
|
|
_world.RawResources.GetResourceNodes(signal.Rect, _config.GeneralSettings.BaseElevation, resourceNodeIds);
|
|
|
|
foreach (var (id, canBeDeleted) in resourceNodeIds)
|
|
{
|
|
if (!canBeDeleted) continue;
|
|
|
|
var visualization = _visualizationsById[id];
|
|
signal.GameObjects.Add(visualization.gameObject);
|
|
}
|
|
}
|
|
|
|
private void OnRawResourcesRemoved(RawResourcesRemovedSignal signal)
|
|
{
|
|
foreach (var resourceNode in signal.ResourceNodes)
|
|
{
|
|
if (!_visualizationsById.Remove(resourceNode.Id, out var visualization)) return;
|
|
|
|
_ = DestroyVisualizationAsync(visualization);
|
|
}
|
|
}
|
|
|
|
private async UniTask DestroyVisualizationAsync(GameObject visualization)
|
|
{
|
|
if (visualization.TryGetComponent<IDestroyRawResourceAnimation>(out var animation)) await animation.PlayAsync();
|
|
|
|
Object.Destroy(visualization);
|
|
}
|
|
|
|
public bool TryGetVisualization(int id, out GameObject visualization)
|
|
{
|
|
return _visualizationsById.TryGetValue(id, out visualization);
|
|
}
|
|
}
|
|
} |