2024-01-30 17:06:14 -08:00

135 lines
3.4 KiB
Rust

use galactica_content::{Content, SectionEdge, SpriteAutomaton, SpriteHandle, UiSpriteConfig};
use galactica_util::to_radians;
use nalgebra::{Point2, Vector2};
use super::{CenteredSpriteRect, SpriteRect};
use crate::{vertexbuffer::types::UiInstance, RenderInput, RenderState};
pub struct UiSprite {
pub anim: SpriteAutomaton,
mask: Option<SpriteHandle>,
rect: SpriteRect,
has_mouse: bool,
on_mouse_enter: Option<SectionEdge>,
on_mouse_leave: Option<SectionEdge>,
}
impl UiSprite {
pub fn new(
ct: &Content,
sprite: SpriteHandle,
mask: Option<SpriteHandle>,
rect: SpriteRect,
on_mouse_enter: Option<SectionEdge>,
on_mouse_leave: Option<SectionEdge>,
) -> Self {
return Self {
anim: SpriteAutomaton::new(ct, sprite),
mask,
rect,
has_mouse: false,
on_mouse_enter,
on_mouse_leave,
};
}
pub fn from(ct: &Content, ui: &UiSpriteConfig) -> Self {
if ui.sprite.is_none() {
unreachable!("called `UiSprite.from()` on a UiSprite with a None sprite!")
}
Self::from_with_sprite(ct, ui, ui.sprite.unwrap())
}
pub fn from_with_sprite(ct: &Content, ui: &UiSpriteConfig, sprite: SpriteHandle) -> Self {
Self::new(
ct,
sprite,
ui.mask,
SpriteRect {
pos: ui.rect.pos,
dim: ui.rect.dim,
anchor_self: ui.rect.anchor_self,
anchor_parent: ui.rect.anchor_parent,
},
ui.on_mouse_enter,
ui.on_mouse_leave,
)
}
pub fn step(&mut self, input: &RenderInput, state: &RenderState) {
if self.contains_mouse(input, state) && !self.has_mouse && self.on_mouse_enter.is_some() {
self.has_mouse = true;
self.anim.jump_to(input.ct, self.on_mouse_enter.unwrap())
} else if !self.contains_mouse(input, state)
&& self.has_mouse
&& self.on_mouse_leave.is_some()
{
self.has_mouse = false;
self.anim.jump_to(input.ct, self.on_mouse_leave.unwrap())
}
self.anim.step(input.ct, input.time_since_last_run);
}
pub fn contains_mouse(&self, input: &RenderInput, state: &RenderState) -> bool {
let rect = self.get_rect(state);
let fac = state.window.scale_factor() as f32;
let window_size = Vector2::new(
state.window_size.width as f32 / fac,
state.window_size.height as f32 / fac,
);
let pos = input.player.input.get_mouse_pos();
let mouse_pos = Point2::new(
pos.x / fac - window_size.x / 2.0,
window_size.y / 2.0 - pos.y / fac,
);
return rect.contains_point(mouse_pos);
}
pub fn get_rect(
&self,
state: &RenderState,
//parent: Option<SpriteRectCentered>,
) -> CenteredSpriteRect {
/*
if let Some(parent) = parent {
return self.rect.to_centered_relative(parent);
} else {
return self.rect.to_centered(state);
}*/
return self.rect.to_centered(state);
}
/// Add this image to the gpu sprite buffer
pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) {
let rect = self.get_rect(state);
// 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(); // ANIMATE
[1, texture_b]
})
.unwrap_or([0, 0]),
});
}
}