use crate::utils::RenderError;
use ahash::AHashMap;
#[cfg(feature = "nostd")]
use alloc::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
#[cfg(not(feature = "nostd"))]
use std::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
pub mod effects;
pub trait EffectPlugin: Send + Sync {
fn name(&self) -> &str;
fn version(&self) -> &str;
fn apply_cpu(
&self,
pixels: &mut [u8],
width: u32,
height: u32,
params: &EffectParams,
) -> Result<(), RenderError>;
fn shader_code(&self) -> Option<&str> {
None
}
fn supports_gpu(&self) -> bool {
self.shader_code().is_some()
}
}
#[derive(Debug, Clone)]
pub struct EffectParams {
pub strength: f32,
pub custom: AHashMap<String, EffectValue>,
}
#[derive(Debug, Clone)]
pub enum EffectValue {
Float(f32),
Integer(i32),
Color([u8; 4]),
Boolean(bool),
String(String),
}
impl EffectParams {
pub fn new(strength: f32) -> Self {
Self {
strength,
custom: AHashMap::new(),
}
}
pub fn set(&mut self, key: impl Into<String>, value: EffectValue) {
self.custom.insert(key.into(), value);
}
pub fn get(&self, key: &str) -> Option<&EffectValue> {
self.custom.get(key)
}
pub fn get_float(&self, key: &str) -> Option<f32> {
self.custom.get(key).and_then(|v| {
if let EffectValue::Float(f) = v {
Some(*f)
} else {
None
}
})
}
pub fn get_int(&self, key: &str) -> Option<i32> {
self.custom.get(key).and_then(|v| {
if let EffectValue::Integer(i) = v {
Some(*i)
} else {
None
}
})
}
pub fn get_color(&self, key: &str) -> Option<[u8; 4]> {
self.custom.get(key).and_then(|v| {
if let EffectValue::Color(c) = v {
Some(*c)
} else {
None
}
})
}
}
pub struct PluginRegistry {
effects: AHashMap<String, Arc<dyn EffectPlugin>>,
}
impl PluginRegistry {
pub fn new() -> Self {
Self {
effects: AHashMap::new(),
}
}
pub fn register_effect(&mut self, plugin: Arc<dyn EffectPlugin>) {
self.effects.insert(plugin.name().to_string(), plugin);
}
pub fn get_effect(&self, name: &str) -> Option<Arc<dyn EffectPlugin>> {
self.effects.get(name).cloned()
}
pub fn list_effects(&self) -> Vec<String> {
self.effects.keys().cloned().collect()
}
pub fn unregister_effect(&mut self, name: &str) -> Option<Arc<dyn EffectPlugin>> {
self.effects.remove(name)
}
pub fn clear(&mut self) {
self.effects.clear();
}
}
impl Default for PluginRegistry {
fn default() -> Self {
Self::new()
}
}