using GarmentButton.FlatenArray;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
namespace GarmentButton.PathFinding
{
[BurstCompile]
[UpdateBefore(typeof(CalculatePathSystem))]
public partial struct NearEdgeSystem : ISystem
{
private const int CHECK_EDGE_BATCH_SIZE = 64;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Grid>();
state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
var query = SystemAPI.QueryBuilder().WithAll<GridData, GridAdditionalData, UpdateCheck, UpdatePoints>()
.WithNone<CastTag>().Build();
state.RequireForUpdate(query);
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
.CreateCommandBuffer(state.WorldUnmanaged);
var gridEntity = SystemAPI.GetSingletonEntity<GridData>();
var gridData = SystemAPI.GetSingleton<GridData>();
var updatePoint = SystemAPI.GetComponentRW<UpdatePoints>(gridEntity);
var converter = new FlatenFloatArray2D(gridData.GridSize, gridData.CellSize, gridData.Center);
var groundType = SystemAPI.GetSingletonRW<GridAdditionalData>();
var updateCount = updatePoint.ValueRO.Indexes.Length;
if (updateCount > 0)
{
state.Dependency = new CheckEdgesJob
{
Converter = converter,
Native = groundType.ValueRW.Types,
UpdatePoints = updatePoint.ValueRO.Indexes.AsReadOnly(),
}.ScheduleParallel(updateCount, CHECK_EDGE_BATCH_SIZE, state.Dependency);
}
state.Dependency = new FinishGrid
{
UpdatePoints = updatePoint.ValueRW.Indexes,
ECB = ecb,
GridEntity = gridEntity,
}.Schedule(state.Dependency);
}
[BurstCompile]
public partial struct CheckEdgesJob : IJobFor
{
[ReadOnly] public FlatenFloatArray2D Converter;
[ReadOnly] public NativeArray<ushort>.ReadOnly UpdatePoints;
[NativeDisableParallelForRestriction]
public NativeArray<GroundType> Native;
public void Execute(int index)
{
Basic(index);
}
private void Basic(int requestedIndex)
{
var pointIndex = UpdatePoints[requestedIndex];
if (Native[pointIndex] != GroundType.Ground)
return;
var width = Converter.GridSize.x;
var height = Converter.GridSize.y;
var pointX = pointIndex % width;
var pointY = pointIndex / width;
for (var yOffset = -1; yOffset <= 1; yOffset++)
{
for (var xOffset = -1; xOffset <= 1; xOffset++)
{
if ((xOffset | yOffset) == 0)
continue;
var neighbourX = pointX + xOffset;
var neighbourY = pointY + yOffset;
if ((uint)neighbourX >= (uint)width || (uint)neighbourY >= (uint)height)
continue;
var indexSide = neighbourY * width + neighbourX;
if (Native[indexSide] != GroundType.Air)
continue;
Native[pointIndex] = GroundType.NearGround;
return;
}
}
}
}
[BurstCompile]
public partial struct FinishGrid : IJob
{
public EntityCommandBuffer ECB;
public Entity GridEntity;
[DeallocateOnJobCompletion] public NativeArray<ushort> UpdatePoints;
public void Execute()
{
ECB.RemoveComponent<UpdateCheck>(GridEntity);
ECB.RemoveComponent<UpdatePoints>(GridEntity);
}
}
}
}