142 lines
3.6 KiB
C#
142 lines
3.6 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Concurrent;
|
||
|
using System.Collections.Generic;
|
||
|
using BITKit;
|
||
|
using BITKit.Entities;
|
||
|
using BITKit.Sensors;
|
||
|
using BITKit.UX;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.UIElements;
|
||
|
|
||
|
namespace BITFALL.UX
|
||
|
{
|
||
|
public class UxPanelSensorTarget : UXBase
|
||
|
{
|
||
|
private struct MyStruct
|
||
|
{
|
||
|
public int index;
|
||
|
public float weight;
|
||
|
public VisualElement visualElement;
|
||
|
public Vector3 position;
|
||
|
public float exitTime;
|
||
|
}
|
||
|
[Inject] private ISensorTarget _sensorTarget;
|
||
|
[Inject] private IEntityMovement _movement;
|
||
|
|
||
|
[SerializeField] private VisualTreeAsset indicatorAsset;
|
||
|
[UXBindPath("sensor-container")]
|
||
|
private VisualElement indicatorContainer;
|
||
|
|
||
|
private readonly ConcurrentDictionary<int,MyStruct> _indicators = new();
|
||
|
private readonly List<int> removeIndex = new();
|
||
|
|
||
|
protected override void Start()
|
||
|
{
|
||
|
base.Start();
|
||
|
indicatorContainer.Clear();
|
||
|
}
|
||
|
|
||
|
protected override void OnPlayerInitialized(Entity obj)
|
||
|
{
|
||
|
base.OnPlayerInitialized(obj);
|
||
|
_sensorTarget.OnDetected += OnDetected;
|
||
|
}
|
||
|
private void Update()
|
||
|
{
|
||
|
foreach (var x in _indicators.Values)
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
x.visualElement[0].style.unityBackgroundImageTintColor = Color.Lerp(Color.gray,Color.white, x.weight);
|
||
|
|
||
|
if (Time.time > x.exitTime)
|
||
|
{
|
||
|
removeIndex.Add(x.index);
|
||
|
x.visualElement.RemoveFromHierarchy();
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
float AngleCircumference(float dot, float angle)
|
||
|
{
|
||
|
float ac = angle;
|
||
|
float circumference = 360f;
|
||
|
ac = angle - 10;
|
||
|
if (dot < 0)
|
||
|
{
|
||
|
ac = circumference - angle;
|
||
|
}
|
||
|
return ac;
|
||
|
}
|
||
|
}
|
||
|
foreach (var x in removeIndex)
|
||
|
{
|
||
|
_indicators.TryRemove(x);
|
||
|
}
|
||
|
removeIndex.Clear();
|
||
|
}
|
||
|
|
||
|
private void OnDetected(float weight, ISensor sensor, object root)
|
||
|
{
|
||
|
_indicators.AddOrUpdate(sensor.Id,Create,UpdateValue);
|
||
|
|
||
|
return;
|
||
|
MyStruct Create(int id)
|
||
|
{
|
||
|
var indicator =indicatorContainer.Create<VisualElement>(()=>indicatorAsset.CloneTree()[0]);
|
||
|
|
||
|
indicator[0].style.unityBackgroundImageTintColor = Color.white;
|
||
|
|
||
|
var pos = (root) switch
|
||
|
{
|
||
|
MonoBehaviour monoBehaviour=>monoBehaviour.transform.position,
|
||
|
Transform _t=>_t.position,
|
||
|
_ => Vector3.zero
|
||
|
};
|
||
|
|
||
|
return new MyStruct()
|
||
|
{
|
||
|
weight = weight,
|
||
|
index = id,
|
||
|
visualElement = indicator,
|
||
|
position = pos,
|
||
|
exitTime = Time.time + 1
|
||
|
};
|
||
|
}
|
||
|
MyStruct UpdateValue(int arg1, MyStruct arg2)
|
||
|
{
|
||
|
arg2.position = (root) switch
|
||
|
{
|
||
|
MonoBehaviour monoBehaviour=>monoBehaviour.transform.position,
|
||
|
Transform _t=>_t.position,
|
||
|
_ => Vector3.zero
|
||
|
};
|
||
|
arg2.weight = weight;
|
||
|
arg2.exitTime = Time.time + 1;
|
||
|
return arg2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|