use std::collections::BTreeMap;
use crate::tree::Color;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ShaderHandle {
Stock(StockShader),
Custom(&'static str),
}
impl ShaderHandle {
pub fn name(&self) -> String {
match self {
ShaderHandle::Stock(s) => s.name().to_string(),
ShaderHandle::Custom(n) => format!("custom::{n}"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum StockShader {
SolidQuad,
RoundedRect,
Text,
DividerLine,
Image,
Spinner,
Skeleton,
ProgressIndeterminate,
}
impl StockShader {
pub fn name(self) -> &'static str {
match self {
StockShader::SolidQuad => "stock::solid_quad",
StockShader::RoundedRect => "stock::rounded_rect",
StockShader::Text => "stock::text",
StockShader::DividerLine => "stock::divider_line",
StockShader::Image => "stock::image",
StockShader::Spinner => "stock::spinner",
StockShader::Skeleton => "stock::skeleton",
StockShader::ProgressIndeterminate => "stock::progress_indeterminate",
}
}
pub fn is_continuous(self) -> bool {
matches!(
self,
StockShader::Spinner | StockShader::Skeleton | StockShader::ProgressIndeterminate
)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum UniformValue {
F32(f32),
Vec2([f32; 2]),
Vec4([f32; 4]),
Color(Color),
Bool(bool),
}
impl UniformValue {
pub fn debug_short(&self) -> String {
match self {
UniformValue::F32(v) => format!("{v:.2}"),
UniformValue::Vec2([x, y]) => format!("({x:.2},{y:.2})"),
UniformValue::Vec4([x, y, z, w]) => format!("({x:.2},{y:.2},{z:.2},{w:.2})"),
UniformValue::Color(c) => match c.token {
Some(name) => name.to_string(),
None => format!("rgba({},{},{},{})", c.r, c.g, c.b, c.a),
},
UniformValue::Bool(b) => b.to_string(),
}
}
}
pub type UniformBlock = BTreeMap<&'static str, UniformValue>;
#[derive(Clone, Debug)]
pub struct ShaderBinding {
pub handle: ShaderHandle,
pub uniforms: UniformBlock,
}
impl ShaderBinding {
pub fn stock(shader: StockShader) -> Self {
Self {
handle: ShaderHandle::Stock(shader),
uniforms: UniformBlock::new(),
}
}
pub fn custom(name: &'static str) -> Self {
Self {
handle: ShaderHandle::Custom(name),
uniforms: UniformBlock::new(),
}
}
pub fn with(mut self, key: &'static str, value: UniformValue) -> Self {
self.uniforms.insert(key, value);
self
}
pub fn set(&mut self, key: &'static str, value: UniformValue) {
self.uniforms.insert(key, value);
}
pub fn color(self, key: &'static str, c: Color) -> Self {
self.with(key, UniformValue::Color(c))
}
pub fn f32(self, key: &'static str, v: f32) -> Self {
self.with(key, UniformValue::F32(v))
}
pub fn vec4(self, key: &'static str, v: [f32; 4]) -> Self {
self.with(key, UniformValue::Vec4(v))
}
}
pub mod stock_wgsl {
pub const ROUNDED_RECT: &str = include_str!("../shaders/rounded_rect.wgsl");
pub const TEXT: &str = include_str!("../shaders/text.wgsl");
pub const TEXT_MSDF: &str = include_str!("../shaders/text_msdf.wgsl");
pub const TEXT_HIGHLIGHT: &str = include_str!("../shaders/text_highlight.wgsl");
pub const ICON_LINE: &str = include_str!("../shaders/icon_line.wgsl");
pub const VECTOR: &str = include_str!("../shaders/vector.wgsl");
pub const VECTOR_RELIEF: &str = include_str!("../shaders/vector_relief.wgsl");
pub const VECTOR_GLASS: &str = include_str!("../shaders/vector_glass.wgsl");
pub const IMAGE: &str = include_str!("../shaders/image.wgsl");
pub const SURFACE: &str = include_str!("../shaders/surface.wgsl");
pub const SPINNER: &str = include_str!("../shaders/spinner.wgsl");
pub const SKELETON: &str = include_str!("../shaders/skeleton.wgsl");
pub const PROGRESS_INDETERMINATE: &str = include_str!("../shaders/progress_indeterminate.wgsl");
}