use blit::Color;
use super::*;
#[derive(Debug)]
pub struct Flat {
pub color: Color,
pub size: (i32, i32),
}
#[derive(Debug)]
pub struct Image {
pub sprite_ref: SpriteRef,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ButtonState {
Normal,
Hover,
Pressed,
}
pub struct Button<S> {
show: S,
pos: (i32, i32),
state: ButtonState,
state_changed: fn(&mut Button<S>, ButtonState),
}
impl<S> Button<S> {
pub fn pos(&self) -> (i32, i32) {
self.pos
}
pub fn with_pos(mut self, x: i32, y: i32) -> Self {
self.pos = (x, y);
self
}
pub fn set_pos(&mut self, x: i32, y: i32) {
self.pos = (x, y);
}
pub fn pressed(&self) -> bool {
match self.state {
ButtonState::Pressed => true,
_ => false,
}
}
pub fn with_callback(mut self, func: fn(&mut Button<S>, ButtonState)) -> Self {
self.state_changed = func;
self
}
fn empty_state_changed_callback(_: &mut Button<S>, _: ButtonState) {}
}
impl Button<Flat> {
pub fn new(size: (i32, i32), color: Color) -> Self {
let show = Flat { size, color };
Button {
show,
pos: (0, 0),
state: ButtonState::Normal,
state_changed: Button::empty_state_changed_callback,
}
}
}
impl Control for Button<Flat> {
fn update(&mut self, args: &ControlState, _res: &Resources) {
let prev_state = self.state;
if !args.mouse_collision(self.pos, self.show.size) {
self.state = ButtonState::Normal;
} else {
self.state = if args.mouse_down {
ButtonState::Pressed
} else {
ButtonState::Hover
};
}
if prev_state != self.state {
let state = self.state;
(self.state_changed)(self, state);
}
}
fn draw(&self, buffer: &mut Vec<u32>, buffer_width: usize, _res: &Resources) {
let mut color = self.show.color.u32();
match self.state {
ButtonState::Hover => color |= 0x44_44_44,
ButtonState::Pressed => color &= 0xAA_AA_AA,
_ => (),
}
for y in self.pos.1..self.pos.1 + self.show.size.1 {
for x in self.pos.0..self.pos.0 + self.show.size.0 {
let index = x as usize + y as usize * buffer_width;
if x == self.pos.0
|| x == self.pos.0 + self.show.size.0 - 1
|| y == self.pos.1
|| y == self.pos.1 + self.show.size.1 - 1
{
buffer[index] = 0;
} else {
buffer[x as usize + y as usize * buffer_width] = color;
}
}
}
}
fn control_type(&self) -> ControlType {
ControlType::Button
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl Button<Image> {
pub fn new_with_sprite(sprite_ref: SpriteRef) -> Self {
let img = Image { sprite_ref };
Button {
show: img,
pos: (0, 0),
state: ButtonState::Normal,
state_changed: Button::empty_state_changed_callback,
}
}
}
impl Control for Button<Image> {
fn update(&mut self, args: &ControlState, res: &Resources) {
let prev_state = self.state;
let sprite = res.get_sprite(self.show.sprite_ref).unwrap();
let mut real_size = sprite.size();
real_size.1 /= 3;
if !args.mouse_collision(self.pos, real_size) {
self.state = ButtonState::Normal;
} else {
self.state = if args.mouse_down {
ButtonState::Pressed
} else {
ButtonState::Hover
};
}
if prev_state != self.state {
let state = self.state;
(self.state_changed)(self, state);
}
}
fn draw(&self, buffer: &mut Vec<u32>, buffer_width: usize, res: &Resources) {
let sprite = res.get_sprite(self.show.sprite_ref).unwrap();
let mut draw_size = sprite.size();
draw_size.1 /= 3;
let height_offset = match self.state {
ButtonState::Normal => 0,
ButtonState::Hover => draw_size.1,
ButtonState::Pressed => draw_size.1 * 2,
} as i32;
sprite.blit_rect(
buffer,
buffer_width,
self.pos,
(0, height_offset, draw_size.0, draw_size.1),
);
}
fn control_type(&self) -> ControlType {
ControlType::Button
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}