
# Objective Add support for interpolation in OKLab and OKLCH color spaces for UI gradients. ## Solution * New `InterpolationColorSpace` enum with `OkLab`, `OkLch`, `OkLchLong`, `Srgb` and `LinearRgb` variants. * Added a color space specialization to the gradients pipeline. * Added support for interpolation in OkLCH and OkLAB color spaces to the gradients shader. OKLCH interpolation supports both short and long hue paths. This is mostly based on the conversion functions from `bevy_color` except that interpolation in polar space uses radians. * Added `color_space` fields to each gradient type. ## Testing The `gradients` example has been updated to demonstrate the different color interpolation methods. Press space to cycle through the different options. --- ## Showcase 
112 lines
3.7 KiB
Rust
112 lines
3.7 KiB
Rust
//! This example illustrates how to create a button that changes color and text based on its
|
|
//! interaction state.
|
|
|
|
use bevy::{color::palettes::basic::*, input_focus::InputFocus, prelude::*, winit::WinitSettings};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins)
|
|
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
|
|
.insert_resource(WinitSettings::desktop_app())
|
|
// `InputFocus` must be set for accessibility to recognize the button.
|
|
.init_resource::<InputFocus>()
|
|
.add_systems(Startup, setup)
|
|
.add_systems(Update, button_system)
|
|
.run();
|
|
}
|
|
|
|
const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
|
|
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
|
|
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
|
|
|
|
fn button_system(
|
|
mut input_focus: ResMut<InputFocus>,
|
|
mut interaction_query: Query<
|
|
(
|
|
Entity,
|
|
&Interaction,
|
|
&mut BackgroundColor,
|
|
&mut BorderColor,
|
|
&mut Button,
|
|
&Children,
|
|
),
|
|
Changed<Interaction>,
|
|
>,
|
|
mut text_query: Query<&mut Text>,
|
|
) {
|
|
for (entity, interaction, mut color, mut border_color, mut button, children) in
|
|
&mut interaction_query
|
|
{
|
|
let mut text = text_query.get_mut(children[0]).unwrap();
|
|
|
|
match *interaction {
|
|
Interaction::Pressed => {
|
|
input_focus.set(entity);
|
|
**text = "Press".to_string();
|
|
*color = PRESSED_BUTTON.into();
|
|
*border_color = BorderColor::all(RED.into());
|
|
|
|
// The accessibility system's only update the button's state when the `Button` component is marked as changed.
|
|
button.set_changed();
|
|
}
|
|
Interaction::Hovered => {
|
|
input_focus.set(entity);
|
|
**text = "Hover".to_string();
|
|
*color = HOVERED_BUTTON.into();
|
|
*border_color = BorderColor::all(Color::WHITE);
|
|
button.set_changed();
|
|
}
|
|
Interaction::None => {
|
|
input_focus.clear();
|
|
**text = "Button".to_string();
|
|
*color = NORMAL_BUTTON.into();
|
|
*border_color = BorderColor::all(Color::BLACK);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn setup(mut commands: Commands, assets: Res<AssetServer>) {
|
|
// ui camera
|
|
commands.spawn(Camera2d);
|
|
commands.spawn(button(&assets));
|
|
}
|
|
|
|
fn button(asset_server: &AssetServer) -> impl Bundle + use<> {
|
|
(
|
|
Node {
|
|
width: Val::Percent(100.0),
|
|
height: Val::Percent(100.0),
|
|
align_items: AlignItems::Center,
|
|
justify_content: JustifyContent::Center,
|
|
..default()
|
|
},
|
|
children![(
|
|
Button,
|
|
Node {
|
|
width: Val::Px(150.0),
|
|
height: Val::Px(65.0),
|
|
border: UiRect::all(Val::Px(5.0)),
|
|
// horizontally center child text
|
|
justify_content: JustifyContent::Center,
|
|
// vertically center child text
|
|
align_items: AlignItems::Center,
|
|
..default()
|
|
},
|
|
BorderColor::all(Color::WHITE),
|
|
BorderRadius::MAX,
|
|
BackgroundColor(Color::BLACK),
|
|
children![(
|
|
Text::new("Button"),
|
|
TextFont {
|
|
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
|
font_size: 33.0,
|
|
..default()
|
|
},
|
|
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
|
TextShadow::default(),
|
|
)]
|
|
)],
|
|
)
|
|
}
|