use std::panic::Location;
use crate::shader::{ShaderBinding, StockShader, UniformValue};
use crate::tokens;
use crate::tree::*;
pub const DEFAULT_RADIUS: f32 = tokens::RADIUS_MD;
pub const DEFAULT_HEIGHT: f32 = 16.0;
#[track_caller]
pub fn skeleton() -> El {
skeleton_with_color(tokens::MUTED)
}
#[track_caller]
pub fn skeleton_with_color(base: Color) -> El {
skeleton_shape(base, DEFAULT_RADIUS)
.default_width(Size::Fill(1.0))
.default_height(Size::Fixed(DEFAULT_HEIGHT))
}
#[track_caller]
pub fn skeleton_circle(size: f32) -> El {
skeleton_shape(tokens::MUTED, size * 0.5)
.width(Size::Fixed(size))
.height(Size::Fixed(size))
}
#[track_caller]
fn skeleton_shape(base: Color, radius: f32) -> El {
let binding = ShaderBinding::stock(StockShader::Skeleton)
.with("vec_a", UniformValue::Color(base))
.with("vec_c", UniformValue::Vec4([radius, 0.0, 0.0, 0.0]));
El::new(Kind::Custom("skeleton"))
.at_loc(Location::caller())
.shader(binding)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shader::ShaderHandle;
#[test]
fn skeleton_binds_stock_skeleton_shader() {
let s = skeleton();
let binding = s.shader_override.as_ref().expect("shader binding");
assert_eq!(
binding.handle,
ShaderHandle::Stock(StockShader::Skeleton),
"skeleton must paint through stock::skeleton",
);
}
#[test]
fn skeleton_packs_color_into_vec_a() {
let s = skeleton_with_color(tokens::PRIMARY);
let binding = s.shader_override.as_ref().unwrap();
match binding.uniforms.get("vec_a") {
Some(UniformValue::Color(c)) => assert_eq!(*c, tokens::PRIMARY),
other => panic!("expected vec_a=PRIMARY color, got {other:?}"),
}
}
#[test]
fn skeleton_circle_sets_equal_axes_and_pill_radius() {
let s = skeleton_circle(32.0);
assert_eq!(s.width, Size::Fixed(32.0));
assert_eq!(s.height, Size::Fixed(32.0));
let binding = s.shader_override.as_ref().unwrap();
match binding.uniforms.get("vec_c") {
Some(UniformValue::Vec4(v)) => assert!(
(v[0] - 16.0).abs() < f32::EPSILON,
"skeleton_circle radius should be size/2, got {}",
v[0]
),
other => panic!("expected vec_c with radius, got {other:?}"),
}
}
#[test]
fn skeleton_default_size_is_full_width_one_line() {
let s = skeleton();
assert_eq!(s.width, Size::Fill(1.0));
assert_eq!(s.height, Size::Fixed(DEFAULT_HEIGHT));
}
#[test]
fn skeleton_kind_is_custom_skeleton() {
let s = skeleton();
assert_eq!(s.kind, Kind::Custom("skeleton"));
}
}