use crate::{
error::NutsCheck, graphics::AbstractMesh, quicksilver_compat::Shape, Display, ErrorMessage,
Paint, Rectangle, RenderPipelineHandle, Tessellate, Transform, Vector,
};
use div::DivHandle;
use web_sys::Element;
pub struct DisplayArea {
region: Rectangle,
display: Display,
div: DivHandle,
}
impl DisplayArea {
pub fn select(&mut self, rect: Rectangle, div: DivHandle) -> &mut Self {
self.region = rect;
self.div = div;
self
}
pub fn full(&self) -> &Display {
&self.display
}
pub fn full_mut(&mut self) -> &mut Display {
&mut self.display
}
pub fn frame_to_display_coordinates(&self) -> Transform {
Transform::translate(self.region.pos)
}
pub fn frame_to_display_area(&self, mut rect: Rectangle) -> Rectangle {
rect.pos += self.region.pos;
rect
}
pub fn frame_to_browser_area(&self, rect: Rectangle) -> Rectangle {
self.full()
.game_to_browser_area(self.frame_to_display_area(rect))
}
pub fn display_to_frame_coordinates(&self) -> Transform {
Transform::translate(-self.region.pos)
}
pub fn is_inside(&self, display_coordinates: impl Into<Vector>) -> bool {
self.region.contains(display_coordinates)
}
pub fn draw<'a>(&'a mut self, draw: &impl Tessellate, bkg: &impl Paint) {
self.display
.draw_ex(draw, bkg, self.frame_to_display_coordinates(), 0);
}
pub fn fill<'a>(&'a mut self, bkg: &impl Paint) {
let region = Rectangle::new_sized(self.region.size);
self.draw(®ion, bkg);
}
pub fn draw_ex<'a>(
&'a mut self,
draw: &impl Tessellate,
bkg: &impl Paint,
trans: Transform,
z: i16,
) {
self.display
.draw_ex(draw, bkg, self.frame_to_display_coordinates() * trans, z)
}
pub fn fit_display(&mut self, margin: f64) {
self.display.fit_to_visible_area(margin).nuts_check();
}
pub fn draw_mesh<'a>(&mut self, mesh: &AbstractMesh, area: Rectangle, paint: &impl Paint) {
let area = self.frame_to_display_area(area);
self.display
.draw_mesh_ex(mesh, paint, area, Transform::IDENTITY, 0);
}
pub fn draw_mesh_ex<'a>(
&mut self,
mesh: &AbstractMesh,
area: Rectangle,
paint: &impl Paint,
t: Transform,
z: i16,
) {
let area = self.frame_to_display_area(area);
self.display.draw_mesh_ex(mesh, paint, area, t, z);
}
pub fn add_html(&self, element: Element) {
if let Some(parent) = self.div.parent_element().nuts_check() {
parent
.append_with_node_1(&element)
.map_err(|e| ErrorMessage::technical(format!("Failed to add HTML: {:?}", e)))
.nuts_check();
}
}
pub fn size(&self) -> Vector {
self.region.size()
}
pub fn new_render_pipeline(
&mut self,
vertex_shader_text: &'static str,
fragment_shader_text: &'static str,
vertex_descriptor: super::gpu::VertexDescriptor,
uniform_values: &[(&'static str, super::gpu::UniformValue)],
) -> crate::PaddleResult<crate::RenderPipelineHandle> {
self.full_mut().new_render_pipeline(
vertex_shader_text,
fragment_shader_text,
vertex_descriptor,
uniform_values,
)
}
pub fn update_uniform(
&mut self,
rp: RenderPipelineHandle,
name: &'static str,
value: &super::gpu::UniformValue,
) {
self.full_mut().update_uniform(rp, name, value)
}
}
impl Into<DisplayArea> for Display {
fn into(self) -> DisplayArea {
DisplayArea {
region: Rectangle::new_sized(self.game_coordinates),
div: self.div.clone(),
display: self,
}
}
}