use galactica_content::{Content, SpriteAutomaton, SpriteHandle}; use galactica_util::to_radians; use super::super::api::Rect; use crate::{ ui::mouseevent::MouseEvent, vertexbuffer::types::UiInstance, RenderInput, RenderState, }; #[derive(Debug, Clone)] pub struct Sprite { pub anim: SpriteAutomaton, pub rect: Rect, pub mask: Option, pub name: String, has_mouse: bool, has_click: bool, /// If true, ignore mouse events until click is released waiting_for_release: bool, } impl Sprite { pub fn new( ct: &Content, name: String, sprite: String, mask: Option, rect: Rect, ) -> Self { let sprite_handle = ct.get_sprite_handle(&sprite).unwrap(); // TODO: errors let mask = { if mask.is_some() { Some(ct.get_sprite_handle(&mask.unwrap()).unwrap()) } else { None } }; Self { name, anim: SpriteAutomaton::new(&ct, sprite_handle), rect, mask, has_mouse: false, has_click: false, waiting_for_release: false, } } pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) { let rect = self.rect.to_centered(state, input.ct.get_config().ui_scale); // TODO: use both dimensions, // not just height let anim_state = self.anim.get_texture_idx(); state.push_ui_buffer(UiInstance { anchor: crate::PositionAnchor::CC.to_int(), position: rect.pos.into(), angle: to_radians(90.0), dim: rect.dim.into(), color: [1.0, 1.0, 1.0, 1.0], texture_index: anim_state.texture_index(), texture_fade: anim_state.fade, mask_index: self .mask .map(|x| { let sprite = input.ct.get_sprite(x); let texture_b = sprite.get_first_frame(); // TODO: animate? [1, texture_b] }) .unwrap_or([0, 0]), }); } pub fn check_mouse(&mut self, input: &RenderInput, state: &mut RenderState) -> MouseEvent { let r = self.rect.to_centered(state, input.ct.get_config().ui_scale); if self.waiting_for_release && self.has_mouse && !input.player.input.pressed_leftclick() { self.waiting_for_release = false; } if !self.waiting_for_release && self.has_mouse && !self.has_click && input.player.input.pressed_leftclick() { self.has_click = true; return MouseEvent::Click; } if self.has_mouse && self.has_click && !input.player.input.pressed_leftclick() { self.has_click = false; return MouseEvent::Release; } // Release mouse when cursor leaves box if self.has_click && !self.has_mouse { self.has_click = false; return MouseEvent::Release; } if r.contains_mouse(input, state) && !self.has_mouse { if input.player.input.pressed_leftclick() { // If we're holding click when the cursor enters, // don't trigger the `Click` event. self.waiting_for_release = true; } self.has_mouse = true; return MouseEvent::Enter; } if !r.contains_mouse(input, state) && self.has_mouse { self.waiting_for_release = false; self.has_mouse = false; return MouseEvent::Leave; } return MouseEvent::None; } pub fn step(&mut self, input: &RenderInput, _state: &mut RenderState) { self.anim.step(&input.ct, input.time_since_last_run); } }