using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;
namespace GarmentButton.VerletIntegration
{
public class BakePoints : MonoBehaviour
{
public Vector2Int Grid = new Vector2Int(15, 6);
public float Distance = 0.2f;
[HideInInspector] public Vector3[] Points;
[HideInInspector] public int[] Tringles;
[HideInInspector] public bool[] IsLocked;
[HideInInspector] public StickPartiallyMono[] Sticks;
public Vector3 MaximumBound;
public Vector3 MinmumBound;
public bool FollowEntity;
public bool DebugCloth;
public SimulationSettings SimulationSettings;
public float HandleSize = 0.25f;
[HideInInspector] public Vector3 HandlePositionOffSet1;
[HideInInspector] public Vector3 HandlePositionOffeset2;
public Vector3 GetRelative(Vector3 position)
{
return transform.position + position;
}
}
public class BakePointsBaker : Baker<BakePoints>
{
public override void Bake(BakePoints authoring)
{
if (authoring.SimulationSettings == null) return;
var entity = Entity.Null;
if (authoring.FollowEntity)
entity = GetEntity(TransformUsageFlags.Dynamic);
else
entity = GetEntity(TransformUsageFlags.None);
//Buffers
var points = CreateBuffers(authoring, entity);
if (authoring.FollowEntity)
FollowEntity(authoring.Points, entity, points);
GeneralDataBake(authoring, entity);
//Cache Lengths
CacheLengths(authoring, entity);
if (authoring.DebugCloth)
AddComponent<DebugClothTag>(entity);
}
private void CacheLengths(BakePoints authoring, Entity entity)
{
AddComponent(entity, new PointArrayLenght
{
Value = (ushort)authoring.Points.Length
});
AddComponent(entity, new SticksArrayLenght()
{
Value = (ushort) authoring.Sticks.Length
});
AddComponent(entity, new TringleArrayLenght()
{
Value = (ushort) authoring.Tringles.Length
});
}
private void GeneralDataBake(BakePoints authoring, Entity entity)
{
var flag = new FlagData
{
NumberIterations = (byte)authoring.SimulationSettings.NumberIternations,
GravityForce = authoring.SimulationSettings.Gravity,
Damping = authoring.SimulationSettings.Damping,
};
var boundBox = new BoundBox
{
Min = authoring.MinmumBound,
Max = authoring.MaximumBound,
};
AddComponent(entity, flag);
AddComponent(entity, boundBox);
float3 deg = authoring.transform.eulerAngles;
float3 rad = math.radians(deg);
quaternion q = quaternion.EulerZXY(rad);
AddComponent(entity, new RecordLastTransform()
{
Position = authoring.transform.position,
Rotation = q,
});
}
private DynamicBuffer<Point> CreateBuffers(BakePoints authoring, Entity entity)
{
var points = AddBuffer<Point>(entity);
points.Capacity = authoring.Points.Length;
points.Length = authoring.Points.Length;
for (var i = 0; i < points.Length; i++)
{
var position = authoring.GetRelative(authoring.Points[i]);
points[i] = new Point
{
Position = position,
PrevesPosition = position,
State = authoring.IsLocked[i] ? PointState.Boarder : PointState.Free,
IsLocked = authoring.IsLocked[i],
};
}
var stickBuffer = AddBuffer<Stick>(entity);
stickBuffer.Capacity = authoring.Sticks.Length;
stickBuffer.Length = authoring.Sticks.Length;
for (var i = 0; i < stickBuffer.Length; i++)
{
stickBuffer[i] = new Stick
{
PointA = authoring.Sticks[i].PointA,
PointB = authoring.Sticks[i].PointB,
Active = true,
Lenght = (ushort)(authoring.Sticks[i].Lenght * authoring.SimulationSettings.LenghtMultiply),
};
}
var tringlesBuffer = AddBuffer<Tringle>(entity);
tringlesBuffer.Capacity = authoring.Tringles.Length;
tringlesBuffer.Length = authoring.Tringles.Length;
for (var i = 0; i < tringlesBuffer.Length; i++)
{
tringlesBuffer[i] = new Tringle
{
Index = (short)authoring.Tringles[i],
};
}
return points;
}
private void FollowEntity(Vector3[] localPoints, Entity entity, DynamicBuffer<Point> bufferPoints)
{
var relativePoints = AddBuffer<RelativeLock>(entity);
for (var i = 0; i < bufferPoints.Length; i++)
{
if (!bufferPoints[i].IsLocked)
continue;
relativePoints.Add(new RelativeLock()
{
Index = (ushort)i,
OffSet = localPoints[i],
});
}
}
}
}