use std::collections::HashMap;
use crate::turtle::TurtleContainer;
use crate::{ArenaId, LSystem};
#[cfg(feature = "image_renderer")]
pub use crate::image_renderer::ImageRendererOptionsBuilder;
#[cfg(feature = "image_renderer")]
pub use crate::image_renderer::VideoRendererOptionsBuilder;
pub trait Renderer<S> {
type Output;
fn render(self, system: &LSystem, options: &S) -> Self::Output;
}
pub struct TurtleRenderer<Q: TurtleContainer> {
pub(crate) state: Q,
state_actions: HashMap<ArenaId, Box<dyn Fn(&mut Q)>>,
aliases: HashMap<ArenaId, ArenaId>,
}
impl<Q: TurtleContainer> TurtleRenderer<Q> {
pub fn new(state: Q) -> Self {
Self {
state,
state_actions: HashMap::new(),
aliases: HashMap::new(),
}
}
pub fn register<F: 'static + Fn(&mut Q)>(&mut self, arena_id: ArenaId, modifier: F) {
self.aliases.insert(arena_id, arena_id);
self.state_actions.insert(arena_id, Box::from(modifier));
}
pub fn register_multiple<F: 'static + Fn(&mut Q)>(
&mut self,
arena_ids: &[ArenaId],
modifier: F,
) {
if let Some(id) = arena_ids.first() {
for aliased_id in arena_ids.iter() {
self.aliases.insert(*aliased_id, *id);
}
self.register(*id, modifier);
}
}
pub(crate) fn compute(&mut self, system_state: &[ArenaId]) {
for arena_id in system_state {
if self.aliases.contains_key(arena_id) {
let alias = self.aliases[arena_id];
if self.state_actions.contains_key(&alias) {
self.state_actions[&alias](&mut self.state);
}
}
}
}
}
#[derive(Default)]
pub struct DataRendererOptions {}
impl<Q: TurtleContainer> Renderer<DataRendererOptions> for TurtleRenderer<Q> {
type Output = Vec<(i32, i32, i32, i32)>;
fn render(mut self, system: &LSystem, _options: &DataRendererOptions) -> Self::Output {
self.compute(system.get_state());
self.state.inner().inner().lines().to_vec()
}
}