From 0c042f9937cc9876fc6a388574596660b3cda604 Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Sun, 31 Aug 2025 11:35:42 -0500 Subject: [PATCH] Begin work on a reusable on-hover color component The two buttons ("close" and the "Big Red" button) have identical hover code, except for which color theme they select. I was about to start work on the cutting board, particularly it's cut-line selectors, and realized that would make a 3rd copy of this code. This commit adds just the background color handler. It seems to work as expected on the CloseButton. I'll finish removing the old observers once I have the BorderColor version in place. --- src/widgets/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index bbe8d57..7308f4f 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -18,6 +18,8 @@ impl Plugin for GameUiPlugin { app .init_resource::() .register_type::() + .add_observer(HoverBackgroundcolor::hover_start) + .add_observer(HoverBackgroundcolor::hover_stop) .add_observer(CloseButton::hover_start) .add_observer(CloseButton::hover_stop) .add_observer(CloseButton::press_start) @@ -216,6 +218,7 @@ impl CloseButton { BackgroundColor(GRAY.into()), BorderColor(DARK_GRAY.into()), BorderRadius::all(Px(2.0)), + HoverBackgroundcolor::new(GREEN.into()), children![( // TODO: Replace with an icon/sprite Text::new("X"), @@ -233,7 +236,7 @@ impl CloseButton { ) { // Get the components for only the Trigger's target entity if let Ok((mut bg, mut border)) = button_colors.get_mut(event.target()) { - bg.0 = ui_theme.quiet_hover_bg; + // bg.0 = ui_theme.quiet_hover_bg; border.0 = ui_theme.quiet_hover_border; } } @@ -244,7 +247,7 @@ impl CloseButton { ui_theme: Res, ) { if let Ok((mut bg, mut border)) = button_colors.get_mut(event.target()) { - bg.0 = ui_theme.quiet_bg; + // bg.0 = ui_theme.quiet_bg; border.0 = ui_theme.quiet_border; } } @@ -273,3 +276,48 @@ impl CloseButton { } } } + +/// Background color to use for an item being hovered over. +/// +/// Adding this to an entity both sets the color and implicitly enables the +/// on-hover behavior. Without it, the system(s) don't find the entity and so +/// no color changing is exhibited. +#[derive(Component)] +struct HoverBackgroundcolor { + pub color: Color, + // hold onto the original so it can be put back + orig_bg: Option, +} + +impl HoverBackgroundcolor { + fn new(color: Color) -> Self { + Self { + color, + orig_bg: None, + } + } + + fn hover_start( + event: Trigger>, + // Get button background and border colors so we can change them. + // Filter for *changed* interactions, and only entities with a [`Button`] + mut colors: Query<(&mut HoverBackgroundcolor, &mut BackgroundColor)>, + ) { + // Get the components for only the Trigger's target entity + if let Ok((mut hover, mut bg)) = colors.get_mut(event.target()) { + hover.orig_bg = Some(bg.0); // store the original + bg.0 = hover.color; + } + } + + fn hover_stop( + event: Trigger>, + mut colors: Query<(&HoverBackgroundcolor, &mut BackgroundColor)>, + ) { + if let Ok((hover, mut bg)) = colors.get_mut(event.target()) { + bg.0 = hover + .orig_bg + .expect("Tried to restore an original color but there was none!"); + } + } +}