1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use std::rc::Rc; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use web_sys::{HtmlImageElement}; use crate::{Error, NikoError, Event, event, graphics::TextureId}; use glow::HasContext; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct Image { pub(crate) id: u32, } impl Image { pub(crate) fn new(id: u32) -> Self { Self { id, } } } pub struct Images { images: HashMap<u32, HtmlImageElement>, textures: HashMap<u32, TextureId>, sizes: HashMap<u32, (u32, u32)>, next_id: u32, } impl Images { pub fn new() -> Self { Self { images: HashMap::new(), textures: HashMap::new(), sizes: HashMap::new(), next_id: 0, } } pub(crate) fn create_image_from_url(&mut self, url: &str, event_queue_handle: Rc<RefCell<VecDeque<Event>>>) -> Result<Image, Error> { let id = self.next_id; self.next_id += 1; let html_image = HtmlImageElement::new().map_err(|_| NikoError::PlatformError("could not create a new HtmlImageElement".to_string()))?; html_image.set_src(url); let closure = event(&html_image, "load", move |_event: web_sys::Event| { event_queue_handle.borrow_mut().push_back(Event::ImageLoaded(id)); }).map_err(|_| NikoError::PlatformError("could not create a loading closure for an image".to_string()))?; closure.forget(); self.images.insert(id, html_image); Ok(Image::new(id)) } #[cfg(target_arch = "wasm32")] pub(crate) fn finish_loading(&mut self, id: u32, gl: &glow::Context) -> Result<(), Error> { let image = self.images.get(&id).unwrap(); let width = image.width(); let height = image.height(); self.sizes.insert(id, (width, height)); let texture = unsafe { let texture = gl.create_texture() .map_err(|error| NikoError::PlatformError(error))?; gl.bind_texture(glow::TEXTURE_2D, Some(texture)); gl.tex_image_2d_with_html_image( glow::TEXTURE_2D, 0, glow::RGBA as i32, glow::RGBA, glow::UNSIGNED_BYTE, &image, ); gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as i32); gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_EDGE as i32); gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR as i32); texture }; self.textures.insert(id, texture); Ok(()) } #[cfg(not(target_arch = "wasm32"))] pub(crate) fn finish_loading(&mut self, id: u32, gl: &glow::Context) -> Result<(), Error> { unimplemented!() } pub fn find_texture(&self, image: Image) -> Option<TextureId> { match self.textures.get(&image.id) { Some(texture) => Some(*texture), None => None, } } pub fn find_size(&self, image: Image) -> Option<(u32, u32)> { match self.sizes.get(&image.id) { Some((width, height)) => Some((*width, *height)), None => None, } } }