using System;
using UnityEditor.AnimatedValues;
using UnityEngine;
namespace UnityEditor.Rendering.LookDev
{
/// state of the comparison gizmo of the LookDev
[Serializable]
public class ComparisonGizmoState
{
internal const float thickness = 0.0028f;
internal const float thicknessSelected = 0.015f;
internal const float circleRadius = 0.014f;
internal const float circleRadiusSelected = 0.03f;
internal const float blendFactorCircleRadius = 0.01f;
internal const float blendFactorCircleRadiusSelected = 0.03f;
/// Position of the first extremity
public Vector2 point1 { get; private set; }
/// Position of the second extremity
public Vector2 point2 { get; private set; }
/// Position of the center
[field: SerializeField]
public Vector2 center { get; private set; } = Vector2.zero;
/// Angle from vertical in radian
[field: SerializeField]
public float angle { get; private set; }
/// Length between extremity
[field: SerializeField]
public float length { get; private set; } = 0.2f;
internal Vector4 plane { get; private set; }
internal Vector4 planeOrtho { get; private set; }
///
/// The position of the blending slider.
/// From value -1 on first extremity to value 1 on second extremity.
///
[field: SerializeField]
public float blendFactor { get; set; }
internal float blendFactorMaxGizmoDistance
=> length - circleRadius - blendFactorCircleRadius;
internal float blendFactorMinGizmoDistance
=> length - circleRadius - blendFactorCircleRadiusSelected;
internal void Init()
=> Update(center, length, angle);
//TODO: optimize
private Vector4 Get2DPlane(Vector2 firstPoint, float angle)
{
Vector4 result = new Vector4();
angle = angle % (2.0f * (float)Math.PI);
Vector2 secondPoint = new Vector2(firstPoint.x + Mathf.Sin(angle), firstPoint.y + Mathf.Cos(angle));
Vector2 diff = secondPoint - firstPoint;
if (Mathf.Abs(diff.x) < 1e-5)
{
result.Set(-1.0f, 0.0f, firstPoint.x, 0.0f);
float sign = Mathf.Cos(angle) > 0.0f ? 1.0f : -1.0f;
result *= sign;
}
else
{
float slope = diff.y / diff.x;
result.Set(-slope, 1.0f, -(firstPoint.y - slope * firstPoint.x), 0.0f);
}
if (angle > Mathf.PI)
result = -result;
float length = Mathf.Sqrt(result.x * result.x + result.y * result.y);
result = result / length;
return result;
}
///
/// Update all fields while moving one extremity
///
/// The new first extremity position
/// The new second extremity position
public void Update(Vector2 point1, Vector2 point2)
{
this.point1 = point1;
this.point2 = point2;
center = (point1 + point2) * 0.5f;
length = (point2 - point1).magnitude * 0.5f;
Vector3 verticalPlane = Get2DPlane(center, 0.0f);
float side = Vector3.Dot(new Vector3(point1.x, point1.y, 1.0f), verticalPlane);
angle = (Mathf.Deg2Rad * Vector2.Angle(new Vector2(0.0f, 1.0f), (point1 - point2).normalized));
if (side > 0.0f)
angle = 2.0f * Mathf.PI - angle;
plane = Get2DPlane(center, angle);
planeOrtho = Get2DPlane(center, angle + 0.5f * (float)Mathf.PI);
}
///
/// Update all fields while moving the bar
///
/// The new center position
/// Tne new length of this gizmo
/// The new angle of this gizmo
public void Update(Vector2 center, float length, float angle)
{
this.center = center;
this.length = length;
this.angle = angle;
plane = Get2DPlane(center, angle);
planeOrtho = Get2DPlane(center, angle + 0.5f * (float)Mathf.PI);
Vector2 dir = new Vector2(planeOrtho.x, planeOrtho.y);
point1 = center + dir * length;
point2 = center - dir * length;
}
}
}