Skip to content

Commit

Permalink
✨ A better way to render only some layers
Browse files Browse the repository at this point in the history
  • Loading branch information
ewen-lbh committed May 5, 2024
1 parent 021740f commit 877bf06
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 45 deletions.
12 changes: 5 additions & 7 deletions src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl Canvas {
objects: HashMap::new(),
name: name.to_string(),
_render_cache: None,
hidden: false,
})
.collect(),
..Self::default_settings()
Expand Down Expand Up @@ -233,6 +234,7 @@ impl Canvas {
name: name.to_string(),
objects,
_render_cache: None,
hidden: false,
}
}

Expand Down Expand Up @@ -267,6 +269,7 @@ impl Canvas {
name: layer_name.to_owned(),
objects,
_render_cache: None,
hidden: false,
}
}

Expand Down Expand Up @@ -512,7 +515,7 @@ impl Canvas {
)
}

pub fn render(&mut self, layers: &Vec<&str>, render_background: bool) -> Result<String> {
pub fn render(&mut self, render_background: bool) -> Result<String> {
let background_color = self.background.unwrap_or_default();
let mut svg = svg::Document::new();
if render_background {
Expand All @@ -525,12 +528,7 @@ impl Canvas {
.set("fill", background_color.render(&self.colormap)),
);
}
for layer in self
.layers
.iter_mut()
.filter(|layer| layers.contains(&"*") || layers.contains(&layer.name.as_str()))
.rev()
{
for layer in self.layers.iter_mut().filter(|layer| !layer.hidden).rev() {
svg = svg.add(layer.render(self.colormap.clone(), self.cell_size, layer.object_sizes));
}

Expand Down
16 changes: 15 additions & 1 deletion src/layer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ColorMapping, ColoredObject, Fill, Filter, ObjectSizes, Region};
use crate::{ColorMapping, ColoredObject, Fill, Filter, ObjectSizes, Region, Toggleable};
use std::{collections::HashMap, fmt::Display};

#[derive(Debug, Clone, Default)]
Expand All @@ -7,6 +7,7 @@ pub struct Layer {
pub object_sizes: ObjectSizes,
pub objects: HashMap<String, ColoredObject>,
pub name: String,
pub hidden: bool,
pub _render_cache: Option<svg::node::element::Group>,
}

Expand All @@ -17,9 +18,22 @@ impl Layer {
objects: HashMap::new(),
name: name.to_string(),
_render_cache: None,
hidden: false,
}
}

pub fn hide(&mut self) {
self.hidden = true;
}

pub fn show(&mut self) {
self.hidden = false;
}

pub fn toggle(&mut self) {
self.hidden.toggle();
}

pub fn object(&mut self, name: &str) -> &mut ColoredObject {
self.objects.get_mut(name).unwrap()
}
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,15 @@ impl<'a, C> Context<'a, C> {
}
}

trait Toggleable {
fn toggle(&mut self);
}

impl Toggleable for bool {
fn toggle(&mut self) {
*self = !*self;
}
}

#[allow(unused)]
fn main() {}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn run(args: cli::Args) -> Result<()> {

if args.cmd_image && !args.cmd_video {
canvas = examples::dna_analysis_machine();
let rendered = canvas.render(&vec!["*"], true)?;
let rendered = canvas.render(true)?;
if args.arg_file.ends_with(".svg") {
std::fs::write(args.arg_file, rendered).unwrap();
} else {
Expand Down
24 changes: 12 additions & 12 deletions src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ impl ColoredObject {
colormap: &ColorMapping,
id: &str,
) -> svg::node::element::Group {
let group = self.object.render(cell_size, object_sizes, id);
let mut group = self.object.render(cell_size, object_sizes, id);

let rendered_transforms = self
match self
.transformations
.render_attribute(colormap, !self.object.fillable());
.render_attribute(colormap, !self.object.fillable())
{
(key, _) if key.is_empty() => (),
(key, value) => group = group.set(key, value),
}

let mut css = String::new();
if !matches!(self.object, Object::RawSVG(..)) {
Expand All @@ -81,9 +85,7 @@ impl ColoredObject {
.join(" ")
.as_ref();

group
.set("style", css)
.set(rendered_transforms.0, rendered_transforms.1)
group.set("style", css)
}
}

Expand Down Expand Up @@ -177,9 +179,8 @@ impl<T: RenderAttribute> RenderAttribute for Vec<T> {
fn render_fill_attribute(&self, colormap: &ColorMapping) -> (String, String) {
(
self.first()
.unwrap()
.render_fill_attribute(colormap)
.0
.map(|v| v.render_fill_attribute(colormap).0)
.unwrap_or_default()
.clone(),
self.iter()
.map(|v| v.render_fill_attribute(colormap).1.clone())
Expand All @@ -190,9 +191,8 @@ impl<T: RenderAttribute> RenderAttribute for Vec<T> {
fn render_stroke_attribute(&self, colormap: &ColorMapping) -> (String, String) {
(
self.first()
.unwrap()
.render_stroke_attribute(colormap)
.0
.map(|v| v.render_stroke_attribute(colormap).0)
.unwrap_or_default()
.clone(),
self.iter()
.map(|v| v.render_stroke_attribute(colormap).1.clone())
Expand Down
40 changes: 27 additions & 13 deletions src/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::{
preview,
sync::SyncData,
ui::{self, setup_progress_bar, Log as _},
Canvas, ColoredObject, Context, MidiSynchronizer, MusicalDurationUnit, Syncable,
Canvas, ColoredObject, Context, LayerAnimationUpdateFunction, MidiSynchronizer,
MusicalDurationUnit, Syncable,
};

pub type BeatNumber = usize;
Expand Down Expand Up @@ -449,6 +450,23 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
Self { commands, ..self }
}

pub fn bind_amplitude(
self,
layer: &'static str,
stem: &'static str,
update: &'static LayerAnimationUpdateFunction,
) -> Self {
self.with_hook(Hook {
when: Box::new(move |_, _, _, _| true),
render_function: Box::new(move |canvas, context| {
let amplitude = context.stem(stem).amplitude_relative();
update(amplitude, canvas.layer(layer), context.ms)?;
canvas.layer(layer).flush();
Ok(())
}),
})
}

pub fn total_frames(&self) -> usize {
self.fps * (self.duration_ms() + self.start_rendering_at) / 1000
}
Expand All @@ -470,7 +488,7 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
let mut rendered_frames: HashMap<usize, String> = HashMap::new();
let progress_bar = self.setup_progress_bar();

for (frame, _, ms) in self.render_frames(&progress_bar, vec!["*"], true)? {
for (frame, _, ms) in self.render_frames(&progress_bar, true)? {
rendered_frames.insert(ms, frame);
}

Expand All @@ -493,7 +511,7 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
workers_count: usize,
preview_only: bool,
) -> Result<()> {
self.render_composition(output_file, vec!["*"], true, workers_count, preview_only)
self.render(output_file, true, workers_count, preview_only)
}

pub fn render_layers_in(&self, output_directory: String, workers_count: usize) -> Result<()> {
Expand All @@ -503,9 +521,8 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
.iter()
.map(|l| vec![l.name.as_str()])
{
self.render_composition(
self.render(
format!("{}/{}.mov", output_directory, composition.join("+")),
composition,
false,
workers_count,
false,
Expand All @@ -518,7 +535,6 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
pub fn render_frames(
&self,
progress_bar: &ProgressBar,
composition: Vec<&str>,
render_background: bool,
) -> Result<Vec<(String, usize, usize)>> {
let mut context = Context {
Expand Down Expand Up @@ -611,7 +627,7 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
}

if context.frame != previous_rendered_frame {
let rendered = canvas.render(&composition, render_background)?;
let rendered = canvas.render(render_background)?;

previous_rendered_beat = context.beat;
previous_rendered_frame = context.frame;
Expand All @@ -627,10 +643,9 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
ui::setup_progress_bar(self.total_frames() as u64, "Rendering")
}

pub fn render_composition(
pub fn render(
&self,
output_file: String,
composition: Vec<&str>,
render_background: bool,
workers_count: usize,
_preview_only: bool,
Expand All @@ -651,9 +666,7 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
self.progress_bar.set_prefix("Rendering");
self.progress_bar.set_message("");

for (frame, no, ms) in
self.render_frames(&self.progress_bar, composition, render_background)?
{
for (frame, no, ms) in self.render_frames(&self.progress_bar, render_background)? {
frames_to_write.push((frame, no, ms));
}

Expand Down Expand Up @@ -697,7 +710,8 @@ impl<AdditionalContext: Default> Video<AdditionalContext> {
frames_output_directory,
aspect_ratio,
resolution,
).unwrap();
)
.unwrap();
progress_bar.inc(1);
}
})
Expand Down
16 changes: 5 additions & 11 deletions src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ pub fn map_to_midi_controller() {}

#[wasm_bindgen]
pub fn render_canvas_into(selector: String) -> () {
let svgstring = canvas().render(&vec!["*"], false).unwrap_throw();
let svgstring = canvas().render(false).unwrap_throw();
append_new_div_inside(svgstring, selector)
}

#[wasm_bindgen]
pub fn render_canvas_at(selector: String) -> () {
let svgstring = canvas().render(&vec!["*"], false).unwrap_throw();
let svgstring = canvas().render(false).unwrap_throw();
replace_content_with(svgstring, selector)
}

Expand Down Expand Up @@ -135,15 +135,9 @@ impl From<(MidiEvent, MidiEventData)> for MidiMessage {
}

#[wasm_bindgen]
pub fn render_canvas(layers_pattern: Option<String>, render_background: Option<bool>) -> () {
pub fn render_canvas(render_background: Option<bool>) -> () {
canvas()
.render(
&match layers_pattern {
Some(ref pattern) => vec![pattern],
None => vec!["*"],
},
render_background.unwrap_or(false),
)
.render(render_background.unwrap_or(false))
.unwrap_throw();
}

Expand Down Expand Up @@ -214,7 +208,7 @@ pub struct LayerWeb {
#[wasm_bindgen]
impl LayerWeb {
pub fn render(&self) -> String {
canvas().render(&vec![&self.name], false).unwrap_throw()
canvas().render(false).unwrap_throw()
}

pub fn render_into(&self, selector: String) -> () {
Expand Down

0 comments on commit 877bf06

Please sign in to comment.