sol_chess/src/game/button.rs

190 lines
4.8 KiB
Rust

use macroquad::prelude::*;
pub struct Button {
pub is_active: bool,
text: String,
is_down: bool,
is_clicked: bool,
rect: Rect,
shadow_width: f32,
color: ButtonColor,
}
pub enum ButtonColor {
Grey,
Green,
Red,
Blue,
}
impl ButtonColor {
fn to_bg_color(&self) -> Color {
match self {
ButtonColor::Grey => Color::from_rgba(140, 140, 140, 200),
ButtonColor::Green => Color::from_rgba(112, 140, 141, 200),
ButtonColor::Red => Color::from_rgba(123, 70, 85, 200),
ButtonColor::Blue => Color::from_rgba(140, 120, 250, 200),
}
}
fn to_shadow_color(&self) -> Color {
let bg_color = self.to_bg_color();
Color::from_rgba(
(bg_color.r * 255.) as u8,
(bg_color.g * 255.) as u8,
(bg_color.b * 255.) as u8,
100,
)
}
}
impl Button {
pub fn new(text: &str, rect: Rect, color: ButtonColor) -> Self {
Self {
text: text.to_string(),
is_down: false,
is_clicked: false,
is_active: true,
rect,
shadow_width: 5.0,
color,
}
}
pub fn is_clicked(&mut self) -> bool {
if self.is_clicked {
self.is_clicked = false;
return true;
}
false
}
pub fn draw(&self) {
self.draw_button();
self.draw_label();
}
fn draw_button(&self) {
let bg_color = match self.is_active {
true => self.color.to_bg_color(),
false => ButtonColor::Grey.to_bg_color(),
};
let button_draw_offset = self.get_button_draw_offset();
draw_rectangle(
self.rect.x + button_draw_offset,
self.rect.y + button_draw_offset,
self.rect.w,
self.rect.h,
bg_color,
);
self.draw_shadow();
}
fn draw_shadow(&self) {
if !self.is_active {
return;
}
if self.is_down {
return;
}
let color = self.color.to_shadow_color();
draw_rectangle(
self.rect.x + self.rect.w,
self.rect.y + self.shadow_width,
self.shadow_width,
self.rect.h,
color,
);
draw_rectangle(
self.rect.x + self.shadow_width,
self.rect.y + self.rect.h,
self.rect.w - self.shadow_width,
self.shadow_width,
color,
);
draw_triangle(
vec2(self.rect.x + self.rect.w, self.rect.y),
vec2(
self.rect.x + self.rect.w + self.shadow_width,
self.rect.y + self.shadow_width,
),
vec2(self.rect.x + self.rect.w, self.rect.y + self.shadow_width),
color,
);
draw_triangle(
vec2(self.rect.x, self.rect.y + self.rect.h),
vec2(
self.rect.x + self.shadow_width,
self.rect.y + self.rect.h + self.shadow_width,
),
vec2(self.rect.x + self.shadow_width, self.rect.y + self.rect.h),
color,
);
}
fn draw_label(&self) {
let font_color = match self.is_active {
true => Color::from_rgba(0, 0, 0, 255),
false => Color::from_rgba(100, 100, 100, 255),
};
let font_size = (0.3 * self.rect.w) as u16;
let dims = measure_text(&self.text, None, font_size, 1.0);
let button_draw_offset = self.get_button_draw_offset();
draw_text(
&self.text,
self.rect.x + (self.rect.w - dims.width) * 0.5 + button_draw_offset,
self.rect.y + (self.rect.h - dims.height) * 0.5 + dims.offset_y + button_draw_offset,
font_size as f32,
font_color,
);
}
fn get_button_draw_offset(&self) -> f32 {
let button_pressed_correction = match self.is_down {
true => self.shadow_width,
false => match self.is_active {
true => 0.0,
false => self.shadow_width,
},
};
button_pressed_correction
}
pub fn handle_input(&mut self) {
if !self.is_active {
self.is_down = false;
return;
}
let (mx, my) = mouse_position();
let c = Circle::new(mx, my, 0.0);
if is_mouse_button_pressed(MouseButton::Left) {
if c.overlaps_rect(&self.rect) {
self.is_down = true;
return;
}
}
if is_mouse_button_released(MouseButton::Left) {
if c.overlaps_rect(&self.rect) {
self.is_clicked = true;
self.is_down = false;
return;
}
self.is_down = false;
}
}
}