using Unity.Burst;
using Unity.Entities;
using UnityEngine;
using GarmentButton.PlayerTags;
using Unity.Transforms;
using Unity.Physics;
using GarmentButton.PhysicFillters;
using Unity.Mathematics;
namespace GarmentButton.CameraGeneral
{
public partial struct SetCameraTransformSystem : ISystem, ISystemStartStop
{
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PlayerTag>();
state.RequireForUpdate<CameraReferenceProperty>();
state.RequireForUpdate<CameraRotationProperties>();
state.RequireForUpdate<CameraPositionProperties>();
}
public void OnStartRunning(ref SystemState state)
{
var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
var playerTransform = SystemAPI.GetComponent<LocalTransform>(playerEntity);
foreach (var (cameraProperty, basedRotation, offset) in SystemAPI.Query<RefRW<CameraReferenceProperty>, RefRW<BaseRotation>, RefRW<CameraOffestFromPlayer>>())
offset.ValueRW.Value = (float3)cameraProperty.ValueRO.Transform.Value.position - playerTransform.Position;
}
public void OnStopRunning(ref SystemState state)
{
}
public void OnUpdate(ref SystemState state)
{
var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
var playerTransform = SystemAPI.GetComponentRO<LocalTransform>(playerEntity);
foreach (var (camera, cameraRotation, cameraPosition, playerScreenPosition, directionToPlayer) in SystemAPI.Query<RefRW<CameraReferenceProperty>, RefRW<CameraRotationProperties>, RefRW<CameraPositionProperties>, RefRW<ScreenPositionPlayer>, RefRW<CameraDirectionToPlayer>>())
{
cameraRotation.ValueRW.Value = camera.ValueRO.Transform.Value.rotation;
cameraPosition.ValueRW.Value = camera.ValueRO.Transform.Value.position;
playerScreenPosition.ValueRW.Value = camera.ValueRO.Value.Value.WorldToViewportPoint(playerTransform.ValueRO.Position);
directionToPlayer.ValueRW.Value = playerTransform.ValueRO.Position - cameraPosition.ValueRO.Value;
}
foreach (var item in SystemAPI.Query<RefRO<FollowPlayerObjectTag>>())
{
item.ValueRO.Value.Value.SetPositionAndRotation(playerTransform.ValueRO.Position, playerTransform.ValueRO.Rotation);
}
}
}
[UpdateAfter(typeof(SetCameraTransformSystem))]
[BurstCompile]
public partial struct CheckSomeBetweenCameraAndPlayerSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PhysicsWorldSingleton>();
state.RequireForUpdate<CameraPositionProperties>();
state.RequireForUpdate<CameraRotationProperties>();
state.RequireForUpdate<CameraDirectionToPlayer>();
state.RequireForUpdate<BaseRotation>();
state.RequireForUpdate<WantedRotationCamera>();
state.RequireForUpdate<PlayerTag>();
state.RequireForUpdate<LocalTransform>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var playerEntity = SystemAPI.GetSingletonEntity<PlayerTag>();
var playerTransform = SystemAPI.GetComponent<LocalTransform>(playerEntity);
var physicsWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>();
foreach (var (position, rotation, baseRotation, desireRotation, shouldRotate, offset) in SystemAPI.Query<RefRO<CameraPositionProperties>, RefRO<CameraRotationProperties>, RefRO<BaseRotation>, RefRW<WantedRotationCamera>, EnabledRefRW<WantedRotationCamera>, RefRO<CameraOffestFromPlayer>>().WithPresent<WantedRotationCamera>())
{
var startPosition = playerTransform.Position + offset.ValueRO.Value;
var endPosition = startPosition + (-offset.ValueRO.Value * 0.9f);
Debug.DrawLine(startPosition, endPosition, Color.green);
quaternion wantedRotation;
var rayCastInput = new RaycastInput()
{
Start = startPosition,
End = endPosition,
Filter = new CollisionFilter
{
BelongsTo = (uint)CollisionLayer.Defualt,
CollidesWith = (uint)(CollisionLayer.Ground)
}
};
if (physicsWorld.CastRay(rayCastInput, out var hit))
{
var angle = math.radians(45);
//var angle = 45 * Time.deltaTime;
quaternion rotationX = quaternion.RotateX(angle);
wantedRotation = math.mul(rotationX, baseRotation.ValueRO.Value);
}
else
{
wantedRotation = baseRotation.ValueRO.Value;
}
wantedRotation = math.slerp(rotation.ValueRO.Value, wantedRotation, 10f * Time.deltaTime);
if (!Approximately(wantedRotation, rotation.ValueRO.Value))
{
var wantedRotationClearer = RoundSmallValuesToZero(wantedRotation);
desireRotation.ValueRW.Value = RoundSmallValuesToZero(wantedRotationClearer);
shouldRotate.ValueRW = true;
}
else
{
shouldRotate.ValueRW = false;
}
}
}
public bool Approximately(quaternion q1, quaternion q2, float epsilon = 1e-5f)
{
// Calculate the dot product between the two quaternions
float dot = math.dot(q1.value, q2.value);
// Quaternions are approximately equal if their dot product is close to 1
return math.abs(dot - 1f) < epsilon;
}
public quaternion RoundSmallValuesToZero(quaternion q, float threshold = 1e-5f)
{
return new quaternion(
math.abs(q.value.x) < threshold ? 0f : q.value.x,
math.abs(q.value.y) < threshold ? 0f : q.value.y,
math.abs(q.value.z) < threshold ? 0f : q.value.z,
math.abs(q.value.w) < threshold ? 0f : q.value.w
);
}
}
[UpdateAfter(typeof(CheckSomeBetweenCameraAndPlayerSystem))]
public partial struct RotateCameraBased : ISystem
{
public void OnCreate(ref SystemState state)
{
var query = SystemAPI.QueryBuilder().WithAll<CameraReferenceProperty, WantedRotationCamera>().Build();
state.RequireForUpdate(query);
}
public void OnUpdate(ref SystemState state)
{
foreach (var (camera, rotation) in SystemAPI.Query<CameraReferenceProperty, RefRO<WantedRotationCamera>>())
{
camera.Transform.Value.rotation = rotation.ValueRO.Value;
}
}
}
}