Skip to main content

ass_renderer/plugin/
mod.rs

1//! Plugin system for custom effects and backends
2
3use crate::utils::RenderError;
4use ahash::AHashMap;
5
6#[cfg(feature = "nostd")]
7use alloc::{
8    string::{String, ToString},
9    sync::Arc,
10    vec::Vec,
11};
12#[cfg(not(feature = "nostd"))]
13use std::{
14    string::{String, ToString},
15    sync::Arc,
16    vec::Vec,
17};
18
19pub mod effects;
20
21/// Effect plugin trait for custom effects
22pub trait EffectPlugin: Send + Sync {
23    /// Get plugin name
24    fn name(&self) -> &str;
25
26    /// Get plugin version
27    fn version(&self) -> &str;
28
29    /// Apply effect to pixel data
30    fn apply_cpu(
31        &self,
32        pixels: &mut [u8],
33        width: u32,
34        height: u32,
35        params: &EffectParams,
36    ) -> Result<(), RenderError>;
37
38    /// Get shader code for GPU backends
39    fn shader_code(&self) -> Option<&str> {
40        None
41    }
42
43    /// Check if effect supports GPU acceleration
44    fn supports_gpu(&self) -> bool {
45        self.shader_code().is_some()
46    }
47}
48
49/// Effect parameters
50#[derive(Debug, Clone)]
51pub struct EffectParams {
52    /// Effect strength (0.0-1.0)
53    pub strength: f32,
54    /// Custom parameters
55    pub custom: AHashMap<String, EffectValue>,
56}
57
58/// Effect parameter value
59#[derive(Debug, Clone)]
60pub enum EffectValue {
61    /// Float value
62    Float(f32),
63    /// Integer value
64    Integer(i32),
65    /// Color value (RGBA)
66    Color([u8; 4]),
67    /// Boolean value
68    Boolean(bool),
69    /// String value
70    String(String),
71}
72
73impl EffectParams {
74    /// Create new effect parameters
75    pub fn new(strength: f32) -> Self {
76        Self {
77            strength,
78            custom: AHashMap::new(),
79        }
80    }
81
82    /// Set a custom parameter
83    pub fn set(&mut self, key: impl Into<String>, value: EffectValue) {
84        self.custom.insert(key.into(), value);
85    }
86
87    /// Get a custom parameter
88    pub fn get(&self, key: &str) -> Option<&EffectValue> {
89        self.custom.get(key)
90    }
91
92    /// Get parameter as float
93    pub fn get_float(&self, key: &str) -> Option<f32> {
94        self.custom.get(key).and_then(|v| {
95            if let EffectValue::Float(f) = v {
96                Some(*f)
97            } else {
98                None
99            }
100        })
101    }
102
103    /// Get parameter as integer
104    pub fn get_int(&self, key: &str) -> Option<i32> {
105        self.custom.get(key).and_then(|v| {
106            if let EffectValue::Integer(i) = v {
107                Some(*i)
108            } else {
109                None
110            }
111        })
112    }
113
114    /// Get parameter as color
115    pub fn get_color(&self, key: &str) -> Option<[u8; 4]> {
116        self.custom.get(key).and_then(|v| {
117            if let EffectValue::Color(c) = v {
118                Some(*c)
119            } else {
120                None
121            }
122        })
123    }
124}
125
126/// Plugin registry for managing plugins
127pub struct PluginRegistry {
128    effects: AHashMap<String, Arc<dyn EffectPlugin>>,
129}
130
131impl PluginRegistry {
132    /// Create a new plugin registry
133    pub fn new() -> Self {
134        Self {
135            effects: AHashMap::new(),
136        }
137    }
138
139    /// Register an effect plugin
140    pub fn register_effect(&mut self, plugin: Arc<dyn EffectPlugin>) {
141        self.effects.insert(plugin.name().to_string(), plugin);
142    }
143
144    /// Get an effect plugin by name
145    pub fn get_effect(&self, name: &str) -> Option<Arc<dyn EffectPlugin>> {
146        self.effects.get(name).cloned()
147    }
148
149    /// List all registered effects
150    pub fn list_effects(&self) -> Vec<String> {
151        self.effects.keys().cloned().collect()
152    }
153
154    /// Remove an effect plugin
155    pub fn unregister_effect(&mut self, name: &str) -> Option<Arc<dyn EffectPlugin>> {
156        self.effects.remove(name)
157    }
158
159    /// Clear all plugins
160    pub fn clear(&mut self) {
161        self.effects.clear();
162    }
163}
164
165impl Default for PluginRegistry {
166    fn default() -> Self {
167        Self::new()
168    }
169}