use bevy::{prelude::*, ui::UiGlobalTransform};
use crate::viewport::SceneViewport;
pub(crate) fn window_to_viewport_cursor(
cursor_pos: Vec2,
camera: &Camera,
viewport_query: &Query<(&ComputedNode, &UiGlobalTransform), With<SceneViewport>>,
) -> Option<Vec2> {
let Ok((computed, vp_transform)) = viewport_query.single() else {
return Some(cursor_pos);
};
let scale = computed.inverse_scale_factor();
let vp_pos = vp_transform.translation * scale;
let vp_size = computed.size() * scale;
let vp_top_left = vp_pos - vp_size / 2.0;
let local = cursor_pos - vp_top_left;
if local.x >= 0.0 && local.y >= 0.0 && local.x <= vp_size.x && local.y <= vp_size.y {
let target_size = camera.logical_viewport_size().unwrap_or(vp_size);
Some(local * target_size / vp_size)
} else {
None
}
}
pub(crate) fn point_in_polygon_2d(point: Vec2, polygon: &[Vec2]) -> bool {
let n = polygon.len();
if n < 3 {
return false;
}
let mut inside = false;
let mut j = n - 1;
for i in 0..n {
let pi = polygon[i];
let pj = polygon[j];
if ((pi.y > point.y) != (pj.y > point.y))
&& (point.x < (pj.x - pi.x) * (point.y - pi.y) / (pj.y - pi.y) + pi.x)
{
inside = !inside;
}
j = i;
}
inside
}
pub(crate) fn point_to_segment_dist(point: Vec2, a: Vec2, b: Vec2) -> f32 {
let ab = b - a;
let ap = point - a;
let t = (ap.dot(ab) / ab.length_squared()).clamp(0.0, 1.0);
let closest = a + ab * t;
(point - closest).length()
}