use std::error::Error; use async_trait::async_trait; use log::debug; use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlImageElement}; use crate::rendering::Renderer; use wasm_bindgen::{JsCast, JsValue}; use crate::CLIENT; use crate::textures::TextureManager; #[derive(Debug)] pub struct WebRenderer { canvas_element_id: String } #[async_trait] impl Renderer for WebRenderer { async fn get(canvas_element_id: &str) -> Result> { Ok(Self { canvas_element_id: canvas_element_id.to_string() }) } async fn render_frame(&self, _time_delta_ms: f64) -> Result<(), Box> { // TODO - core is working on this, please no touchy without telling him // TODO - until this notice is removed // time_delta_ms is the delta, in ms, from when the last render_frame was called by the browser let window = web_sys::window().ok_or("window needs to exist")?; let document = window.document().ok_or("window.document needs to exist")?; let canvas_element = document.get_element_by_id(&self.canvas_element_id).ok_or("canvas element does not exist")?; let typed_canvas_element: HtmlCanvasElement = canvas_element.dyn_into::().map_err(|_| ()).unwrap(); let context = typed_canvas_element.get_context("2d").unwrap().unwrap().dyn_into::().unwrap(); let client = CLIENT.read()?; if client.client_data.is_none() { return Err("client not yet initialized".into()); } let client_data = client.client_data.as_ref().unwrap(); //let camera_translate_x = -client.x + (typed_canvas_element.width() / 2) as f64; let viewer_size_x = typed_canvas_element.width() as f64; //let camera_translate_y = -client.y + (typed_canvas_element.height() / 2) as f64; let viewer_size_y = typed_canvas_element.height() as f64; context.set_transform(1f64, 0f64, 0f64, 1f64, 0f64, 0f64).map_err(|e: JsValue| e.as_string().unwrap())?; context.clear_rect(0f64, 0f64, viewer_size_x, viewer_size_y); // *dont* translate the camera. we're movign everything else around us. cameracentrism. // only translation will be to center our core module. //context.translate(camera_translate_x, camera_translate_y).map_err(|e: JsValue| e.as_string().unwrap())?; context.translate(viewer_size_x / 2.0, viewer_size_y / 2.0).map_err(|e: JsValue| e.as_string().unwrap())?; for planet in &client.planets { //context.save(); //context.set_transform(1f64, 0f64, 0f64, 1f64, 0f64, 0f64).map_err(|e: JsValue| e.as_string().unwrap())?; //context.translate(-planet.x, -planet.y).map_err(|e: JsValue| e.as_string().unwrap())?; let texture_image = document.get_element_by_id(&format!("tex-{}", planet.planet_type.as_texture_id())).unwrap().dyn_into::().unwrap(); // pos: //debug!("P {} {}", planet.x - planet.radius - client.x, planet.y - planet.radius - client.y); debug!("P {} {}", planet.x - planet.radius - /*client.x*/0f64, planet.y - planet.radius - /*client.y*/100f64); context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, planet.x - planet.radius - /*client.x*/0f64, planet.y - planet.radius - /*client.y*/100f64, planet.radius * 2f64, planet.radius * 2f64).map_err(|e: JsValue| e.as_string().unwrap())?; //context.restore(); } for player in &client.players { context.save(); //context.translate(player.x, player.y).map_err(|e: JsValue| e.as_string().unwrap())?; context.set_text_align("center"); context.set_font("30px Segoe UI"); context.set_fill_style(&JsValue::from_str("white")); // CssStyleColor context.fill_text(&player.username, 0f64, -35f64).map_err(|e: JsValue| e.as_string().unwrap())?; context.rotate(player.rotation).map_err(|e: JsValue| e.as_string().unwrap())?; // fwip let texture_image = document.get_element_by_id("tex-hearty").unwrap().dyn_into::().unwrap(); debug!("H {} {}", player.x - 25f64 - client.x, player.y - 25f64 - client.y); context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, player.x - 25f64 - client.x, player.y - 25f64 - client.y, 50f64, 50f64).map_err(|e: JsValue| e.as_string().unwrap())?; // sktch //context.rotate(-player.rotation).map_err(|e: JsValue| e.as_string().unwrap())?; // fwoop context.restore(); } context.scale(0.25f64, 0.25f64).map_err(|e: JsValue| e.as_string().unwrap())?; // do not remove // im making this smiley an easter egg soon // i just have to go fix the broken build system first /* context.begin_path(); // Draw the outer circle. context .arc(75.0, 75.0, 50.0, 0.0, std::f64::consts::PI * 2.0) .unwrap(); // Draw the mouth. context.move_to(110.0, 75.0); context.arc(75.0, 75.0, 35.0, 0.0, std::f64::consts::PI).unwrap(); // Draw the left eye. context.move_to(65.0, 65.0); context .arc(60.0, 65.0, 5.0, 0.0, std::f64::consts::PI * 2.0) .unwrap(); // Draw the right eye. context.move_to(95.0, 65.0); context .arc(90.0, 65.0, 5.0, 0.0, std::f64::consts::PI * 2.0) .unwrap(); context.stroke(); */ Ok(()) } }