using GarmentButton.VerletIntegration.Interaction;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
namespace GarmentButton.VerletIntegration.Tear
{
[UpdateInGroup(typeof(VerletIntegrationPhysicsGroupSystems))]
[UpdateAfter(typeof(SimulateInteractionSystem))]
[BurstCompile]
public partial struct CheckStretchesSystem : ISystem
{
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
state.RequireForUpdate<Stick>();
state.RequireForUpdate<Point>();
state.RequireForUpdate<Tringle>();
state.RequireForUpdate<TearLenght>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
state.Dependency = new CheckStretchesJob
{
ECB = ecb,
}.ScheduleParallel(state.Dependency);
}
[BurstCompile]
[WithAll(typeof(TearLenght))]
public partial struct CheckStretchesJob : IJobEntity
{
public EntityCommandBuffer.ParallelWriter ECB;
public void Execute(
Entity entity,
[ChunkIndexInQuery] int sortKey,
in TearLenght tearLenght,
in DynamicBuffer<Point> points,
ref DynamicBuffer<Stick> sticks,
ref DynamicBuffer<Tringle> tringles)
{
if (sticks.Length == 0 || tringles.Length == 0)
return;
var hasChanged = false;
for (var i = 0; i < sticks.Length; i++)
{
var stick = sticks[i];
if (!stick.Active)
continue;
var delta = points[stick.PointA].Position - points[stick.PointB].Position;
var maxLength = stick.Lenght * Stick.CONVERTION_RATE + tearLenght.Value;
if (math.lengthsq(delta) <= maxLength * maxLength)
continue;
stick.Active = false;
sticks[i] = stick;
RemoveConnectedTringles(stick.PointA, stick.PointB, ref tringles, ref hasChanged);
}
if (hasChanged)
ECB.AddComponent<UpdatedTringlesTag>(sortKey, entity);
}
private static void RemoveConnectedTringles(
short pointA,
short pointB,
ref DynamicBuffer<Tringle> tringles,
ref bool hasChanged)
{
for (var i = 0; i < tringles.Length; i += 3)
{
var tringleEdge = tringles[i];
var tringleEdge2 = tringles[i + 1];
var tringleEdge3 = tringles[i + 2];
if (tringleEdge.Index == 0 && tringleEdge2.Index == 0 && tringleEdge3.Index == 0)
continue;
var hasPointA = IsOneOfThem(pointA, tringleEdge, tringleEdge2, tringleEdge3);
var hasPointB = IsOneOfThem(pointB, tringleEdge, tringleEdge2, tringleEdge3);
if (!hasPointA || !hasPointB) continue;
tringleEdge.Index = 0;
tringles[i] = tringleEdge;
tringles[i + 1] = tringleEdge;
tringles[i + 2] = tringleEdge;
hasChanged = true;
}
}
private static bool IsOneOfThem(short point, Tringle tringleEdge, Tringle tringleEdge2, Tringle tringleEdge3)
{
return tringleEdge.Index == point || tringleEdge2.Index == point || tringleEdge3.Index == point;
}
}
}
public struct UpdatedTringlesTag : IComponentData
{
}
}