use astrelis_core::math::Vec2;
use astrelis_render::{Color, Viewport};
use crate::event::UiEventSystem;
use crate::inspector::OverlayQuad;
use crate::metrics_collector::MetricsCollector;
use crate::tree::UiTree;
use crate::widget_id::WidgetIdRegistry;
use super::overlay_draw_list::OverlayDrawList;
#[derive(Clone)]
pub struct MiddlewareContext<'a> {
pub tree: &'a UiTree,
pub metrics: Option<&'a MetricsCollector>,
pub events: &'a UiEventSystem,
pub registry: &'a WidgetIdRegistry,
pub viewport: Viewport,
pub mouse_position: Vec2,
pub delta_time: f32,
pub frame_number: u64,
}
impl<'a> MiddlewareContext<'a> {
pub fn new(
tree: &'a UiTree,
events: &'a UiEventSystem,
registry: &'a WidgetIdRegistry,
viewport: Viewport,
) -> Self {
Self {
tree,
metrics: None,
events,
registry,
viewport,
mouse_position: events.mouse_position(),
delta_time: 0.0,
frame_number: 0,
}
}
pub fn with_metrics(mut self, metrics: &'a MetricsCollector) -> Self {
self.metrics = Some(metrics);
self
}
pub fn with_delta_time(mut self, delta_time: f32) -> Self {
self.delta_time = delta_time;
self
}
pub fn with_frame_number(mut self, frame_number: u64) -> Self {
self.frame_number = frame_number;
self
}
pub fn viewport_size(&self) -> Vec2 {
let logical = self.viewport.to_logical();
Vec2::new(logical.width, logical.height)
}
}
pub struct OverlayContext<'a> {
draw_list: &'a mut OverlayDrawList,
}
impl<'a> OverlayContext<'a> {
pub fn new(draw_list: &'a mut OverlayDrawList) -> Self {
Self { draw_list }
}
pub fn draw_rect(&mut self, position: Vec2, size: Vec2, color: Color) {
self.draw_list
.add_quad(position, size, color, None, 0.0, 0.0);
}
pub fn draw_rect_rounded(&mut self, position: Vec2, size: Vec2, color: Color, radius: f32) {
self.draw_list
.add_quad(position, size, color, None, 0.0, radius);
}
pub fn draw_rect_bordered(
&mut self,
position: Vec2,
size: Vec2,
fill: Color,
border: Color,
border_width: f32,
) {
self.draw_list
.add_quad(position, size, fill, Some(border), border_width, 0.0);
}
pub fn draw_rect_bordered_rounded(
&mut self,
position: Vec2,
size: Vec2,
fill: Color,
border: Color,
border_width: f32,
radius: f32,
) {
self.draw_list
.add_quad(position, size, fill, Some(border), border_width, radius);
}
pub fn draw_text(&mut self, position: Vec2, text: &str, color: Color, size: f32) {
self.draw_list
.add_text(position, text.to_string(), color, size);
}
pub fn draw_line(&mut self, start: Vec2, end: Vec2, color: Color, thickness: f32) {
self.draw_list.add_line(start, end, color, thickness);
}
pub fn draw_overlay_quad(&mut self, quad: &OverlayQuad) {
self.draw_list.add_quad(
quad.position,
quad.size,
quad.fill_color,
quad.border_color,
quad.border_width,
0.0,
);
}
pub fn draw_list_mut(&mut self) -> &mut OverlayDrawList {
self.draw_list
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::event::UiEventSystem;
use crate::tree::UiTree;
use crate::widget_id::WidgetIdRegistry;
#[test]
fn test_middleware_context_creation() {
let tree = UiTree::new();
let events = UiEventSystem::new();
let registry = WidgetIdRegistry::new();
let viewport = Viewport::default();
let ctx = MiddlewareContext::new(&tree, &events, ®istry, viewport)
.with_delta_time(0.016)
.with_frame_number(42);
assert_eq!(ctx.delta_time, 0.016);
assert_eq!(ctx.frame_number, 42);
}
#[test]
fn test_overlay_context_drawing() {
let mut draw_list = OverlayDrawList::new();
{
let mut ctx = OverlayContext::new(&mut draw_list);
ctx.draw_rect(Vec2::new(10.0, 20.0), Vec2::new(100.0, 50.0), Color::RED);
ctx.draw_text(Vec2::new(10.0, 10.0), "Test", Color::WHITE, 16.0);
ctx.draw_line(Vec2::ZERO, Vec2::new(100.0, 100.0), Color::GREEN, 2.0);
}
assert_eq!(draw_list.commands().len(), 3);
}
#[test]
fn test_overlay_quad_compatibility() {
let mut draw_list = OverlayDrawList::new();
let quad = OverlayQuad {
position: Vec2::new(0.0, 0.0),
size: Vec2::new(100.0, 100.0),
fill_color: Color::RED,
border_color: Some(Color::WHITE),
border_width: 2.0,
};
{
let mut ctx = OverlayContext::new(&mut draw_list);
ctx.draw_overlay_quad(&quad);
}
assert_eq!(draw_list.commands().len(), 1);
}
}