use glam::{Vec2, Vec4};
use tessera_ui::{Color, DrawCommand, PxPosition, PxSize};
use super::pipeline::ShapeUniforms;
#[derive(Debug, Clone, PartialEq)]
pub enum ShapeCommand {
Rect {
color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
},
OutlinedRect {
color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
border_width: f32,
},
RippleRect {
color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
ripple: RippleProps,
},
RippleOutlinedRect {
color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
border_width: f32,
ripple: RippleProps,
},
Ellipse {
color: Color,
shadow: Option<ShadowProps>,
},
OutlinedEllipse {
color: Color,
shadow: Option<ShadowProps>,
border_width: f32,
},
FilledOutlinedRect {
color: Color,
border_color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
border_width: f32,
},
RippleFilledOutlinedRect {
color: Color,
border_color: Color,
corner_radii: [f32; 4],
g2_k_value: f32,
shadow: Option<ShadowProps>,
border_width: f32,
ripple: RippleProps,
},
FilledOutlinedEllipse {
color: Color,
border_color: Color,
shadow: Option<ShadowProps>,
border_width: f32,
},
}
impl DrawCommand for ShapeCommand {
fn barrier(&self) -> Option<tessera_ui::BarrierRequirement> {
None
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ShadowProps {
pub color: Color,
pub offset: [f32; 2],
pub smoothness: f32,
}
impl Default for ShadowProps {
fn default() -> Self {
Self {
color: Color::BLACK.with_alpha(0.25),
offset: [0.0, 2.0],
smoothness: 4.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RippleProps {
pub center: [f32; 2],
pub radius: f32,
pub alpha: f32,
pub color: Color,
}
impl Default for RippleProps {
fn default() -> Self {
Self {
center: [0.0, 0.0],
radius: 0.0,
alpha: 0.0,
color: Color::WHITE,
}
}
}
pub(crate) fn rect_to_uniforms(
command: &ShapeCommand,
size: PxSize,
position: PxPosition,
) -> ShapeUniforms {
let (
primary_color_rgba,
border_color_rgba,
corner_radii,
g2_k_value,
shadow,
border_width,
render_mode,
ripple,
) = match command {
ShapeCommand::Rect {
color,
corner_radii,
g2_k_value,
shadow,
} => (
*color,
Color::TRANSPARENT,
*corner_radii,
*g2_k_value,
*shadow,
0.0,
0.0,
None,
),
ShapeCommand::OutlinedRect {
color,
corner_radii,
g2_k_value,
shadow,
border_width,
} => (
*color,
Color::TRANSPARENT,
*corner_radii,
*g2_k_value,
*shadow,
*border_width,
1.0,
None,
),
ShapeCommand::RippleRect {
color,
corner_radii,
g2_k_value,
shadow,
ripple,
} => (
*color,
Color::TRANSPARENT,
*corner_radii,
*g2_k_value,
*shadow,
0.0,
3.0,
Some(*ripple),
),
ShapeCommand::RippleOutlinedRect {
color,
corner_radii,
g2_k_value,
shadow,
border_width,
ripple,
} => (
*color,
Color::TRANSPARENT,
*corner_radii,
*g2_k_value,
*shadow,
*border_width,
4.0,
Some(*ripple),
),
ShapeCommand::Ellipse { color, shadow } => (
*color,
Color::TRANSPARENT,
[-1.0, -1.0, -1.0, -1.0],
0.0,
*shadow,
0.0,
0.0,
None,
),
ShapeCommand::OutlinedEllipse {
color,
shadow,
border_width,
} => (
*color,
Color::TRANSPARENT,
[-1.0, -1.0, -1.0, -1.0],
0.0,
*shadow,
*border_width,
1.0,
None,
),
ShapeCommand::FilledOutlinedRect {
color,
border_color,
corner_radii,
g2_k_value,
shadow,
border_width,
} => (
*color,
*border_color,
*corner_radii,
*g2_k_value,
*shadow,
*border_width,
5.0,
None,
),
ShapeCommand::RippleFilledOutlinedRect {
color,
border_color,
corner_radii,
g2_k_value,
shadow,
border_width,
ripple,
} => (
*color,
*border_color,
*corner_radii,
*g2_k_value,
*shadow,
*border_width,
5.0,
Some(*ripple),
),
ShapeCommand::FilledOutlinedEllipse {
color,
border_color,
shadow,
border_width,
} => (
*color,
*border_color,
[-1.0, -1.0, -1.0, -1.0],
0.0,
*shadow,
*border_width,
5.0,
None,
),
};
let width = size.width;
let height = size.height;
let (shadow_rgba_color, shadow_offset_vec, shadow_smooth_val) = if let Some(s_props) = shadow {
(s_props.color, s_props.offset, s_props.smoothness)
} else {
(Color::TRANSPARENT, [0.0, 0.0], 0.0)
};
let (ripple_params, ripple_color) = if let Some(r_props) = ripple {
(
Vec4::new(
r_props.center[0],
r_props.center[1],
r_props.radius,
r_props.alpha,
),
Vec4::new(r_props.color.r, r_props.color.g, r_props.color.b, 0.0),
)
} else {
(Vec4::ZERO, Vec4::ZERO)
};
ShapeUniforms {
corner_radii: corner_radii.into(),
primary_color: primary_color_rgba.to_array().into(),
border_color: border_color_rgba.to_array().into(),
shadow_color: shadow_rgba_color.to_array().into(),
render_params: [
shadow_offset_vec[0],
shadow_offset_vec[1],
shadow_smooth_val,
render_mode,
]
.into(),
ripple_params,
ripple_color,
g2_k_value,
border_width,
position: [
position.x.to_f32(),
position.y.to_f32(),
width.to_f32(),
height.to_f32(),
]
.into(),
screen_size: Vec2::ZERO, }
}