use std::{collections::BTreeMap, fs::File, io::Read}; use skia_safe::{ canvas::SrcRectConstraint, utils::text_utils::Align, Canvas, Color4f, ColorSpace, Data, Font, Image, Paint, Point, Rect, }; use twclient::world::{tee::Tee, World}; const TEE_COLL_RADIUS: f32 = 16.0; const TEE_REND_RADIUS: f32 = 32.0; pub struct TeeRenderer { skins: BTreeMap, } impl TeeRenderer { pub fn new() -> Self { Self { skins: BTreeMap::new(), } } pub fn draw(&mut self, world: &World, canvas: &mut Canvas) { for t in world.tees.inner.values() { canvas.save(); canvas.translate((t.x as f32, t.y as f32)); self.draw_tee(canvas, t); canvas.restore(); } } pub fn draw_tee(&mut self, canvas: &mut Canvas, tee: &Tee) { let tee_paint = Paint::new( Color4f { a: 1.0, r: 1.0, g: 1.0, b: 1.0, }, &ColorSpace::new_srgb(), ); let name_paint = Paint::new( Color4f { a: 1.0, r: 1.0, g: 1.0, b: 0.0, }, &ColorSpace::new_srgb(), ); let skin_texture = self .skins .entry(tee.skin.clone()) .or_insert_with(|| TeeRenderer::load_skin(tee.name.as_str()).unwrap()); let origin = Point { x: tee.x as f32, y: tee.y as f32, }; canvas.draw_image_rect( skin_texture, Some(( &Rect { top: 16.0, left: 16.0, right: 96.0, bottom: 96.0, }, SrcRectConstraint::Strict, )), Rect { top: -TEE_REND_RADIUS, left: -TEE_REND_RADIUS, right: TEE_REND_RADIUS, bottom: TEE_REND_RADIUS, }, &tee_paint, ); canvas.draw_str_align( tee.name.as_str(), (origin.x, origin.y - 20.0), &Font::default(), &name_paint, Align::Center, ); } pub fn load_skin(_name: &str) -> Option { let path = "/usr/share/ddnet/data/skins/default.png"; let mut file = File::open(path).unwrap(); let mut data = Vec::new(); file.read_to_end(&mut data).unwrap(); let data = Data::new_copy(&data); Image::from_encoded(data) } }