use std::cell::Cell;
use crate::backend::hybrid::HybridWebGlRenderer;
use crate::color::Color;
use crate::geometry::{Point, Size};
use crate::scene::SceneBuilder as _;
use crate::window::{Event, EventCtx, Frame, PickSource, WindowApp, WindowConfig, WindowError};
pub struct WebGlHost {
renderer: HybridWebGlRenderer,
background: Color,
dpi: f64,
cursor: Option<Point>,
}
impl WebGlHost {
pub fn new(
canvas: &web_sys::HtmlCanvasElement,
config: WindowConfig,
) -> Result<Self, WindowError> {
let (width, height) = match (canvas.width(), canvas.height()) {
(0, _) | (_, 0) => {
canvas.set_width(config.width);
canvas.set_height(config.height);
(config.width, config.height)
}
wh => wh,
};
let renderer = HybridWebGlRenderer::new(canvas, width, height, config.picking)?;
Ok(Self {
renderer,
background: config.background,
dpi: super::BASE_DPI,
cursor: None,
})
}
pub fn render<A: WindowApp>(&mut self, app: &mut A) -> Result<(), WindowError> {
let size = self.size();
self.renderer.scene().clear();
{
let mut frame = Frame {
scene: self.renderer.scene(),
size,
dpi: self.dpi,
};
app.draw(&mut frame);
}
self.renderer.present(self.background)?;
Ok(())
}
pub fn dispatch<A: WindowApp>(&mut self, app: &mut A, event: Event) -> bool {
match event {
Event::CursorMoved { position } => self.cursor = Some(position),
Event::CursorLeft => self.cursor = None,
_ => {}
}
let size = self.size();
let redraw = Cell::new(false);
let mut exit = false;
let mut ctx = EventCtx {
renderer: &self.renderer,
redraw: &redraw,
cursor: self.cursor,
size,
dpi: self.dpi,
exit: &mut exit,
};
app.event(&mut ctx, event);
redraw.get()
}
pub fn resize(&mut self, width: u32, height: u32, dpi: f64) -> Result<(), WindowError> {
if width == 0 || height == 0 {
return Ok(());
}
self.renderer.resize(width, height)?;
self.dpi = dpi;
Ok(())
}
pub fn pick_at(&self, x: u32, y: u32) -> Option<u32> {
self.renderer.pick_at(x, y)
}
pub fn set_refresh_pick(&mut self, refresh: bool) {
self.renderer.set_refresh_pick(refresh);
}
pub fn size(&self) -> Size {
let (w, h) = self.renderer.size();
Size::new(w as f64, h as f64)
}
pub fn dpi(&self) -> f64 {
self.dpi
}
pub fn set_background(&mut self, background: Color) {
self.background = background;
}
}
impl PickSource for HybridWebGlRenderer {
fn pick_at(&self, x: u32, y: u32) -> Option<u32> {
HybridWebGlRenderer::pick_at(self, x, y)
}
}