using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Cysharp.Threading.Tasks; using Unity.Mathematics; using UnityEngine; namespace DanieleMarotta.RiversongCodeShowcase { [Service(typeof(IAoERenderingService))] [GameSystemGroup(typeof(LateGameSystemGroup))] public class AoERenderingSystem : GameSystem, IInitializable, IDisposable, IUpdatable, IAoERenderingService { private const int MaxAoECount = 16; private static readonly int AoESourcesPropertyID = Shader.PropertyToID("_AoE_Sources"); private static readonly int AoECountPropertyID = Shader.PropertyToID("_AoE_Count"); [InjectService] private GameConfig _config; [InjectService] private IBuildingVisualizationCollection _buildingVisualizationCollection; private ComputeBuffer _aoeBuffer; private List _data = new(MaxAoECount); public AoERenderingSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _aoeBuffer = new ComputeBuffer(MaxAoECount, sizeof(int) + sizeof(float) * 4, ComputeBufferType.Structured, ComputeBufferMode.Dynamic); return UniTask.CompletedTask; } public void Dispose() { _aoeBuffer.Dispose(); } public void Update() { _aoeBuffer.SetData(_data); var material = _config.Vfx.AoEMaterial; material.SetBuffer(AoESourcesPropertyID, _aoeBuffer); material.SetInt(AoECountPropertyID, _data.Count); _data.Clear(); } public void Add(int layer, TileRect rect) { _data.Add( new AoE { Layer = layer, Rect = new float4(rect.Min, rect.Max) }); } [StructLayout(LayoutKind.Sequential)] private struct AoE { public int Layer; public float4 Rect; } } }