diff --git a/crates/sao-ui-rs/src/widgets/button.rs b/crates/sao-ui-rs/src/widgets/button.rs index ebd17db..84ef144 100644 --- a/crates/sao-ui-rs/src/widgets/button.rs +++ b/crates/sao-ui-rs/src/widgets/button.rs @@ -78,9 +78,7 @@ impl Widget for RoundButton { ctx.draw_circle(self.pos, self.radius, color); ctx.draw_ring(self.pos, self.radius + spacing, self.thickness, color); - if let Some(label) = self.label.as_mut() { - label.draw(ctx); - } + self.label.draw(ctx); } fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) { @@ -103,10 +101,30 @@ impl Widget for RoundButton { } } -pub struct RectButton { - pub rect: Rect, +#[derive(Clone, Debug)] +pub struct RectButtonStyle { pub rounded_corners: CornerFlags, pub radius: f32, + pub inactive_color: Color, + pub hover_color: Color, + pub selected_color: Color, +} + +impl Default for RectButtonStyle { + fn default() -> Self { + Self { + rounded_corners: CornerFlags::empty(), + radius: 0.0, + inactive_color: Color::new(1., 1., 1., 0.2), + hover_color: Color::new(1., 1., 1., 0.8), + selected_color: Color::new(1., 1., 0., 1.), + } + } +} + +pub struct RectButton { + pub style: RectButtonStyle, + pub rect: Rect, pub was_clicked: bool, pub is_selected: bool, pub is_hovering: bool, @@ -121,16 +139,7 @@ impl Button for RectButton { } impl RectButton { - pub const INACTIVE_COLOR: Color = Color::new(1., 1., 1., 0.2); - pub const HOVER_COLOR: Color = Color::new(1., 1., 1., 0.8); - pub const SELECTED_COLOR: Color = Color::new(1., 1., 0., 1.); - - pub fn new( - label: Option, - rect: Rect, - rounded_corners: CornerFlags, - radius: f32, - ) -> Self { + pub fn new(style: RectButtonStyle, label: Option, rect: Rect) -> Self { let label_height_scale = 0.7; let label_baseline_scale = 0.25; @@ -149,19 +158,16 @@ impl RectButton { ) }); + let color_anim = + Animation::new(EaseInQuad, 0.05, style.inactive_color, style.inactive_color); + Self { + style, rect, - rounded_corners, - radius, was_clicked: false, is_selected: false, is_hovering: false, - color_anim: Animation::new( - EaseInQuad, - 0.05, - Self::INACTIVE_COLOR, - Self::INACTIVE_COLOR, - ), + color_anim, label, } } @@ -175,31 +181,30 @@ impl Widget for RectButton { fn draw(&mut self, ctx: &DrawContext) { ctx.draw_partially_rounded_rect( - self.rounded_corners, + self.style.rounded_corners, self.rect, - self.radius, + self.style.radius, self.color_anim.get(), ); - if let Some(label) = self.label.as_mut() { - label.draw(ctx); - } + self.label.draw(ctx); } fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) { let is_on = self.rect.contains_point(at); + let style = &self.style; match kind { CursorEventKind::Hover | CursorEventKind::Drag => { if is_on { if !self.is_hovering && !self.is_selected { - self.color_anim.ease_to(Self::HOVER_COLOR); + self.color_anim.ease_to(style.hover_color); } self.is_hovering = true; } else { if self.is_hovering && !self.is_selected { - self.color_anim.ease_to(Self::INACTIVE_COLOR); + self.color_anim.ease_to(style.inactive_color); } self.is_hovering = false; @@ -208,7 +213,7 @@ impl Widget for RectButton { CursorEventKind::Select => { if is_on { self.is_selected = true; - self.color_anim.ease_to(Self::SELECTED_COLOR); + self.color_anim.ease_to(style.selected_color); } } CursorEventKind::Deselect => { @@ -217,9 +222,9 @@ impl Widget for RectButton { self.is_selected = false; if self.is_hovering { - self.color_anim.ease_to(Self::HOVER_COLOR); + self.color_anim.ease_to(style.hover_color); } else { - self.color_anim.ease_to(Self::INACTIVE_COLOR); + self.color_anim.ease_to(style.inactive_color); } } } diff --git a/crates/sao-ui-rs/src/widgets/menu.rs b/crates/sao-ui-rs/src/widgets/menu.rs index f15df3f..4a1b638 100644 --- a/crates/sao-ui-rs/src/widgets/menu.rs +++ b/crates/sao-ui-rs/src/widgets/menu.rs @@ -229,16 +229,16 @@ impl TabMenu { for i in 0..Self::TAB_NUM { let y = (i + 1) as f32 * Self::TAB_HEIGHT; let pos = Vec2::new(0.0, -y); - let radius = Self::HEAD_RADIUS; - let corners = if i == Self::TAB_NUM - 1 { - CornerFlags::BOTTOM_LEFT - } else { - CornerFlags::empty() - }; + let mut style = RectButtonStyle::default(); + style.radius = Self::HEAD_RADIUS; + + if i == Self::TAB_NUM - 1 { + style.rounded_corners = CornerFlags::BOTTOM_LEFT; + } let rect = Rect::from_xy_size(pos, tab_size); - tabs.push(RectButton::new(None, rect, corners, radius)); + tabs.push(RectButton::new(style, None, rect)); } let tab_list_height = Self::TAB_NUM as f32 * Self::TAB_HEIGHT; diff --git a/crates/sao-ui-rs/src/widgets/mod.rs b/crates/sao-ui-rs/src/widgets/mod.rs index 3d4acde..d7c391a 100644 --- a/crates/sao-ui-rs/src/widgets/mod.rs +++ b/crates/sao-ui-rs/src/widgets/mod.rs @@ -10,18 +10,39 @@ pub mod scroll; pub mod shell; pub mod text; -use button::{Button, RectButton, RoundButton}; +use button::{Button, RectButton, RectButtonStyle, RoundButton}; use menu::{SlotMenu, SlotMenuEvent, TabMenu}; use scroll::{ScrollBar, ScrollView}; use shell::{Offset, Reveal}; use text::{HorizontalAlignment, Label, LabelText}; +#[allow(unused)] pub trait Widget { fn update(&mut self, dt: f32) {} fn draw(&mut self, ctx: &DrawContext) {} fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {} } +impl Widget for Option { + fn update(&mut self, dt: f32) { + if let Some(inner) = self.as_mut() { + inner.update(dt); + } + } + + fn draw(&mut self, ctx: &DrawContext) { + if let Some(inner) = self.as_mut() { + inner.draw(ctx); + } + } + + fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) { + if let Some(inner) = self.as_mut() { + inner.on_cursor_event(kind, at); + } + } +} + pub trait FixedWidth { fn get_width(&self) -> f32; } @@ -164,7 +185,9 @@ impl SettingsMenu { text: text.to_string(), }; - let button = RectButton::new(Some(text), button_rect, CornerFlags::empty(), 0.0); + let style = Default::default(); + + let button = RectButton::new(style, Some(text), button_rect); buttons.push(button); }