use bevy_app::{Plugin, PostUpdate};
use bevy_color::{Alpha, Color};
use bevy_ecs::{
component::Component,
hierarchy::Children,
query::Changed,
reflect::ReflectComponent,
system::{Commands, Query},
};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_scene::prelude::*;
use bevy_ui::{percent, px, BackgroundColor, Node, PositionType, ZIndex};
use bevy_ui_render::ui_material::MaterialNode;
use crate::{
alpha_pattern::{AlphaPattern, AlphaPatternMaterial},
constants::size,
palette,
rounded_corners::RoundedCorners,
};
#[derive(SceneComponent, Default, Clone, Reflect)]
#[reflect(Component, Clone, Default)]
#[scene(FeathersColorSwatchProps)]
pub struct FeathersColorSwatch;
pub struct FeathersColorSwatchProps {
pub opaque_color_percentage: f32,
pub corners: RoundedCorners,
pub border_radius: f32,
}
impl Default for FeathersColorSwatchProps {
fn default() -> Self {
Self {
opaque_color_percentage: Default::default(),
corners: Default::default(),
border_radius: 5.0,
}
}
}
#[derive(Component, Default, Clone, Reflect)]
#[reflect(Component, Clone, Default)]
pub struct ColorSwatchValue(pub Color);
#[derive(Component, Default, Clone, Reflect)]
#[reflect(Component, Clone, Default)]
pub struct ColorSwatchFg;
impl FeathersColorSwatch {
fn scene(props: FeathersColorSwatchProps) -> impl Scene {
let non_alpha_fg = (props.opaque_color_percentage > 0.0).then(|| {
bsn! {
Node {
position_type: PositionType::Absolute,
left: percent(100.0 - props.opaque_color_percentage.clamp(0.0, 100.0)),
top: px(0),
bottom: px(0),
right: px(0),
border_radius: {RoundedCorners::Right.to_border_radius(props.border_radius)}, }
ColorSwatchFg
BackgroundColor({palette::ACCENT})
ZIndex(1)
}
});
bsn! {
Node {
height: size::ROW_HEIGHT,
min_width: size::ROW_HEIGHT,
border_radius: {props.corners.to_border_radius(props.border_radius)},
}
FeathersColorSwatch
ColorSwatchValue
AlphaPattern
MaterialNode::<AlphaPatternMaterial>
Children [
Node {
position_type: PositionType::Absolute,
left: px(0),
top: px(0),
bottom: px(0),
right: px(0),
border_radius: {props.corners.to_border_radius(props.border_radius)},
}
ColorSwatchFg
BackgroundColor({palette::ACCENT.with_alpha(0.5)})
--
@{non_alpha_fg}
]
}
}
}
fn update_swatch_color(
q_swatch: Query<(&ColorSwatchValue, &Children), Changed<ColorSwatchValue>>,
mut commands: Commands,
) {
for (value, children) in q_swatch.iter() {
if let Some(first_child) = children.first() {
commands
.entity(*first_child)
.insert(BackgroundColor(value.0));
}
if let Some(second_child) = children.get(1) {
commands
.entity(*second_child)
.insert(BackgroundColor(value.0.with_alpha(1.0)));
}
}
}
pub struct ColorSwatchPlugin;
impl Plugin for ColorSwatchPlugin {
fn build(&self, app: &mut bevy_app::App) {
app.add_systems(PostUpdate, update_swatch_color);
}
}