use std::collections::HashMap;
use bevy::prelude::*;
use crate::render::{NoesisRenderState, NoesisSet};
#[derive(Component, Clone, Default, Debug)]
pub struct NoesisSvg {
pub sources: HashMap<String, String>,
}
impl NoesisSvg {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn path(mut self, name: impl Into<String>, svg: impl Into<String>) -> Self {
self.sources.insert(name.into(), svg.into());
self
}
pub fn set_path(&mut self, name: impl Into<String>, svg: impl Into<String>) {
self.sources.insert(name.into(), svg.into());
}
}
#[derive(Message, Debug, Clone, PartialEq)]
pub struct NoesisSvgChanged {
pub view: Entity,
pub name: String,
pub bounds: [f32; 4],
}
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn sync_svg_bridge(
views: Query<(Entity, Ref<NoesisSvg>)>,
state: Option<NonSendMut<NoesisRenderState>>,
mut changed: MessageWriter<NoesisSvgChanged>,
) {
let Some(mut state) = state else {
return;
};
for (entity, svg) in &views {
if !svg.is_changed() && !state.scene_rebuilt_this_frame(entity) {
continue;
}
for (name, bounds) in state.apply_svg_for(entity, &svg.sources) {
changed.write(NoesisSvgChanged {
view: entity,
name,
bounds,
});
}
}
}
pub struct NoesisSvgPlugin;
impl Plugin for NoesisSvgPlugin {
fn build(&self, app: &mut App) {
app.add_message::<NoesisSvgChanged>()
.add_systems(PostUpdate, sync_svg_bridge.in_set(NoesisSet::Apply));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_collects_sources() {
let s = NoesisSvg::new()
.path("Icon", "M0 0 L40 0 L40 20 Z")
.path("Glyph", "M0 0 L10 10");
assert_eq!(
s.sources.get("Icon").map(String::as_str),
Some("M0 0 L40 0 L40 20 Z"),
);
assert_eq!(
s.sources.get("Glyph").map(String::as_str),
Some("M0 0 L10 10"),
);
}
}