BITFALL/Assets/Artists/Scripts/UX/UXDamageIndicator.cs

144 lines
3.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using BITKit;
using BITKit.Entities;
using BITKit.Entities.Player;
using BITKit.UX;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITFALL.UX
{
public class UXDamageIndicator : MonoBehaviour
{
[SerializeReference, SubclassSelector] private IPlayerService playerService;
[SerializeField] private UIDocument document;
[SerializeField] private VisualTreeAsset indicatorAsset;
[UXBindPath("indicator-container")]
private VisualElement indicatorContainer;
[Inject] private IHealth _health;
[Inject] private IEntityMovement _movement;
private List<(VisualElement visualElement, Vector3 position, float exitTime)> _indicators = new();
private void Start()
{
playerService.OnPlayerInitialized += OnPlayerInitialized;
playerService.OnPlayerDisposed+=OnPlayerDisposed;
destroyCancellationToken.Register(() =>
{
playerService.OnPlayerInitialized -= OnPlayerInitialized;
playerService.OnPlayerDisposed-=OnPlayerDisposed;
});
BITKit.UX.UXUtils.Inject(this);
indicatorContainer.Clear();
}
private void OnPlayerDisposed(Entity obj)
{
foreach (var x in _indicators)
{
x.visualElement.RemoveFromHierarchy();
}
_indicators.Clear();
}
private void OnPlayerInitialized(Entity obj)
{
obj.Inject(this);
_health.OnDamageRelease += OnDamageRelease;
}
private void Update()
{
foreach (var x in _indicators)
{
//
// var direction =Vector3.ProjectOnPlane(x.position - _movement.Position,Vector3.up).normalized;
//
// direction = Quaternion.LookRotation(direction) * _movement.Rotation * Vector3.forward;
//
// var rotation = Quaternion.LookRotation(direction);
// var angle =(rotation.eulerAngles.y+180)%360;
//
// x.visualElement.transform.rotation = Quaternion.Euler(0, 0, -angle);
//Calculate direction
Vector3 rhs = x.position - _movement.Position;
Vector3 offset = x.visualElement.transform.rotation.eulerAngles;
var forward = _movement.Forward;
//Convert angle into screen space
rhs.y = 0f;
rhs.Normalize();
//Get the angle between two positions.
float angle = Vector3.Angle(rhs, forward);
//Calculate the perpendicular of both vectors
//More information about this calculation: https://unity3d.com/es/learn/tutorials/modules/beginner/scripting/vector-maths-dot-cross-products?playlist=17117
Vector3 Perpendicular = Vector3.Cross(forward, rhs);
//Calculate magnitude between two vectors
float dot = -Vector3.Dot(Perpendicular, Vector3.up);
//get the horizontal angle in direction of target / sender.
angle = AngleCircumference(dot, angle);
//Apply the horizontal rotation to the indicator.
offset.z = -angle;
x.visualElement.transform.rotation = Quaternion.Euler(offset);
if (Time.time > x.exitTime)
x.visualElement.RemoveFromHierarchy();
float AngleCircumference(float dot, float angle)
{
float ac = angle;
float circumference = 360f;
ac = angle - 10;
if (dot < 0)
{
ac = circumference - angle;
}
return ac;
}
}
_indicators.RemoveAll(x => x.exitTime < Time.time);
}
private void OnDamageRelease(DamageMessage arg1)
{
if (arg1.Position.IsDefault()) return;
var indicator =indicatorContainer.Create<VisualElement>(()=>indicatorAsset.CloneTree()[0]);
if (arg1.Damage is 0)
{
indicator[0].style.unityBackgroundImageTintColor = Color.black;
}
_indicators.Add((indicator, (Vector3)arg1.Position, Time.time + 1));
}
// private async void KillIndicator(VisualElement indicator)
// {
// try
// {
// await Task.Delay(500, destroyCancellationToken);
// indicator.RemoveFromHierarchy();
// }
// catch (Exception e)
// {
// Console.WriteLine(e);
// throw;
// }
// }
}
}