use crate::geometry2d::Vec2;
use crate::graphics::DrawScreenParams;
#[repr(C)]
#[derive(Copy, Clone)]
pub(crate) struct ScreenVertex {
pub(crate) pos: [f32; 2], pub(crate) uv: [f32; 2],
pub(crate) screen_xy: [f32; 2], pub(crate) mask_ox: f32,
pub(crate) mask_oy: f32,
pub(crate) mask_w: f32,
pub(crate) mask_h: f32,
pub(crate) mask_on: f32, pub(crate) alpha: f32,
}
pub(crate) fn build_screen_quad_ex(
x: i32, y: i32,
src_w: u32, src_h: u32,
screen_w: u32, screen_h: u32,
mask_ox: f32, mask_oy: f32, mask_w: f32, mask_h: f32, mask_on: f32,
params: &DrawScreenParams,
) -> [ScreenVertex; 6] {
let draw_w = src_w as f32 * params.scale_x;
let draw_h = src_h as f32 * params.scale_y;
let center = Vec2::new(x as f32 + draw_w * 0.5, y as f32 + draw_h * 0.5);
let half = Vec2::new(draw_w * 0.5, draw_h * 0.5);
let rotation = params.rotation.to_radians();
let corners = [
center + Vec2::new(-half.x, -half.y).rotate(rotation),
center + Vec2::new( half.x, -half.y).rotate(rotation),
center + Vec2::new(-half.x, half.y).rotate(rotation),
center + Vec2::new( half.x, half.y).rotate(rotation),
];
let (u0, u1) = if params.flip_x { (1.0f32, 0.0f32) } else { (0.0f32, 1.0f32) };
let (v0, v1) = if params.flip_y { (1.0f32, 0.0f32) } else { (0.0f32, 1.0f32) };
let v = |idx: usize, u: f32, tv: f32| ScreenVertex {
pos: crate::draw::to_ndc(corners[idx].x, corners[idx].y, screen_w, screen_h),
uv: [u, tv],
screen_xy: corners[idx].into(),
mask_ox, mask_oy, mask_w, mask_h, mask_on,
alpha: params.alpha,
};
let tl = v(0, u0, v0);
let tr = v(1, u1, v0);
let bl = v(2, u0, v1);
let br = v(3, u1, v1);
[tl, tr, bl, tr, br, bl]
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn build_screen_quad_overlay(
x: i32, y: i32,
src_w: u32, src_h: u32,
display_w: u32, display_h: u32,
main_x: i32, main_y: i32,
win_scale_x: f32, win_scale_y: f32,
mask_ox: f32, mask_oy: f32, mask_w: f32, mask_h: f32, mask_on: f32,
params: &DrawScreenParams,
) -> [ScreenVertex; 6] {
let win_scale = Vec2::new(win_scale_x, win_scale_y);
let main_pos = Vec2::new(main_x as f32, main_y as f32);
let draw_w = src_w as f32 * params.scale_x * win_scale_x;
let draw_h = src_h as f32 * params.scale_y * win_scale_y;
let half = Vec2::new(draw_w * 0.5, draw_h * 0.5);
let center = Vec2::new(x as f32, y as f32) * win_scale + half + main_pos;
let (mask_offset, mask_size) = if mask_on > 0.5 {
(Vec2::new(mask_ox, mask_oy) * win_scale + main_pos, Vec2::new(mask_w, mask_h) * win_scale)
} else {
(Vec2::new(mask_ox, mask_oy), Vec2::new(mask_w, mask_h))
};
let rotation = params.rotation.to_radians();
let corners = [
center + Vec2::new(-half.x, -half.y).rotate(rotation),
center + Vec2::new( half.x, -half.y).rotate(rotation),
center + Vec2::new(-half.x, half.y).rotate(rotation),
center + Vec2::new( half.x, half.y).rotate(rotation),
];
let (u0, u1) = if params.flip_x { (1.0f32, 0.0f32) } else { (0.0f32, 1.0f32) };
let (v0, v1) = if params.flip_y { (1.0f32, 0.0f32) } else { (0.0f32, 1.0f32) };
let sv = |idx: usize, u: f32, tv: f32| ScreenVertex {
pos: crate::draw::to_ndc(corners[idx].x, corners[idx].y, display_w, display_h),
uv: [u, tv],
screen_xy: corners[idx].into(),
mask_ox: mask_offset.x, mask_oy: mask_offset.y, mask_w: mask_size.x, mask_h: mask_size.y, mask_on,
alpha: params.alpha,
};
let tl = sv(0, u0, v0); let tr = sv(1, u1, v0);
let bl = sv(2, u0, v1); let br = sv(3, u1, v1);
[tl, tr, bl, tr, br, bl]
}
pub(crate) fn reproject_ndc_to_overlay(p: Vec2, surface_size: Vec2, main_pos: Vec2, display_size: Vec2) -> Vec2 {
let screen = Vec2::new(
(p.x * 0.5 + 0.5) * surface_size.x,
(1.0 - (p.y * 0.5 + 0.5)) * surface_size.y,
) + main_pos;
Vec2::new(
screen.x / display_size.x * 2.0 - 1.0,
1.0 - screen.y / display_size.y * 2.0,
)
}