diff --git a/src/cartoon.rs b/src/cartoon.rs index f2842129a51f09c8bc0a99529bf5f2d5c80d0d5b..9fada364507c9df12adf7736d862770c5f04b456 100644 --- a/src/cartoon.rs +++ b/src/cartoon.rs @@ -3,10 +3,11 @@ use crate::slide::s1_title::Title; use crate::slide::s2_introduction::Introduction; use crate::slide::s3_complexity::Complexity; use crate::slide::s4_automata::Automata; -use crate::slide::s5_fractals::Fractals; -use crate::slide::s6_computation::Computation; -use crate::slide::s7_mosaic::Mosaic; -use crate::slide::s8_conclusion::Conclusion; +use crate::slide::s5_emergence::Emergence; +use crate::slide::s6_fractals::Fractals; +use crate::slide::s7_computation::Computation; +use crate::slide::s8_mosaic::Mosaic; +use crate::slide::s9_conclusion::Conclusion; use crate::slide::Slide; use eframe::egui::style::Margin; use eframe::egui::{Key, Style, TextStyle, Visuals}; @@ -58,6 +59,7 @@ fn create_slides() -> Vec<Box<dyn Slide>> { Box::new(Introduction::default()), Box::new(Complexity::default()), Box::new(Automata::default()), + Box::new(Emergence::default()), Box::new(Fractals::default()), Box::new(Computation::default()), Box::new(Mosaic::default()), diff --git a/src/component.rs b/src/component.rs index c72f31f7cfb019ae37f5ffe13651b1ee6ed4fbec..e0590fcdf4f48f70e9ec22900b9fd52a051d450c 100644 --- a/src/component.rs +++ b/src/component.rs @@ -3,6 +3,7 @@ pub mod arrow; pub mod code; +pub mod example_list; pub mod grid; pub mod image; pub mod triangle; diff --git a/src/slide/s6_computation.rs b/src/component/example_list.rs similarity index 68% rename from src/slide/s6_computation.rs rename to src/component/example_list.rs index 02c78bb007e4d967b985adb871717c16f2a5910d..9e744faef64b04ea2a47c1e78e884489e5613022 100644 --- a/src/slide/s6_computation.rs +++ b/src/component/example_list.rs @@ -1,19 +1,19 @@ use crate::component::image::Image; -use crate::ctx_img; use crate::egui::{Context, Frame, Ui}; use crate::fade_in::{fade_in, fade_in_manual}; -use crate::slide::Slide; use eframe::egui::style::Margin; use eframe::egui::{Pos2, TextureHandle}; #[derive(Default)] -pub struct Computation { - /// Will fade in one by one. - examples: Vec<ComputationExample>, +pub struct ExampleList { + /// Heading text. + title: &'static str, + /// Examples to show. + examples: Vec<Example>, } /// One bullet point and texture combination. -struct ComputationExample { +pub struct Example { /// Bullet point text. label: &'static str, /// Texture handle to render on the right side. @@ -22,7 +22,7 @@ struct ComputationExample { fade_start: Option<f64>, } -impl ComputationExample { +impl Example { pub fn new(label: &'static str, texture: TextureHandle) -> Self { Self { label, @@ -32,8 +32,15 @@ impl ComputationExample { } } -impl Slide for Computation { - fn transition(&mut self, ctx: &Context) -> bool { +impl ExampleList { + pub fn new(title: &'static str) -> Self { + Self { + title, + examples: Vec::new(), + } + } + + pub fn transition(&mut self, ctx: &Context) -> bool { for example in &mut self.examples { if example.fade_start.is_none() { // If any image has not yet started fading in, fade it in and don't go to next slide. @@ -44,24 +51,20 @@ impl Slide for Computation { true } - fn show(&mut self, ui: &mut Ui) { + /// Will call setter function once to populate examples. + pub fn show(&mut self, ui: &mut Ui, setter: impl FnOnce() -> Vec<Example>) { if self.examples.is_empty() { - // For now, these images are somewhat like placeholders. - self.examples = vec![ - ComputationExample::new("Raytracing", ctx_img!(ui.ctx(), "raytracing0.png")), - ComputationExample::new("Raymarching", ctx_img!(ui.ctx(), "raymarching1.png")), - ComputationExample::new("Particle simulation", ctx_img!(ui.ctx(), "atom0.png")), - ComputationExample::new("Fluid simulation", ctx_img!(ui.ctx(), "fluid0.png")), - ] + self.examples = setter(); } const IMAGE_SCALE: f32 = 256.0; let window_width = ui.available_width(); let window_height = ui.available_height(); let window_width_per_image = window_width / self.examples.len() as f32; + let aspect_ratio_gap = (window_width_per_image - IMAGE_SCALE) * 0.5; Frame::none().margin(Margin::same(20.0)).show(ui, |ui| { - ui.heading("More Computation-based Art"); + ui.heading(self.title); ui.add_space(8.0); for (i, example) in self.examples.iter().enumerate() { if let Some(fade_start) = example.fade_start { @@ -70,9 +73,9 @@ impl Slide for Computation { }); fade_in_manual(ui, fade_start, |ui, alpha| { let position = Pos2::new( - (window_width_per_image - IMAGE_SCALE) * 0.5 + aspect_ratio_gap + window_width * (i as f32) / self.examples.len() as f32, - window_height - IMAGE_SCALE * 1.1, + window_height - IMAGE_SCALE - aspect_ratio_gap, ); Image::default() .height(IMAGE_SCALE) diff --git a/src/image/placeholder0.png b/src/image/placeholder0.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8c2b9db3de79d3c2d8b0b059be597579860205 Binary files /dev/null and b/src/image/placeholder0.png differ diff --git a/src/image/placeholder1.png b/src/image/placeholder1.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8c2b9db3de79d3c2d8b0b059be597579860205 Binary files /dev/null and b/src/image/placeholder1.png differ diff --git a/src/slide.rs b/src/slide.rs index 2151fb979419ee189416c00690a13aba30d78143..1241c6a261aefab690c63c634137152101a0ea29 100644 --- a/src/slide.rs +++ b/src/slide.rs @@ -6,10 +6,11 @@ pub mod s1_title; pub mod s2_introduction; pub mod s3_complexity; pub mod s4_automata; -pub mod s5_fractals; -pub mod s6_computation; -pub mod s7_mosaic; -pub mod s8_conclusion; +pub mod s5_emergence; +pub mod s6_fractals; +pub mod s7_computation; +pub mod s8_mosaic; +pub mod s9_conclusion; /// An interface for all slides. pub trait Slide { diff --git a/src/slide/s5_emergence.rs b/src/slide/s5_emergence.rs new file mode 100644 index 0000000000000000000000000000000000000000..1fe26e6e7417e2ed3f6ca5131d6a1d320192f8d7 --- /dev/null +++ b/src/slide/s5_emergence.rs @@ -0,0 +1,33 @@ +use crate::component::example_list::{Example, ExampleList}; +use crate::ctx_img; +use crate::egui::{Context, Ui}; +use crate::slide::Slide; + +pub struct Emergence { + inner: ExampleList, +} + +impl Default for Emergence { + fn default() -> Self { + Self { + inner: ExampleList::new("More Emergence-based Art"), + } + } +} + +impl Slide for Emergence { + fn transition(&mut self, ctx: &Context) -> bool { + self.inner.transition(ctx) + } + + fn show(&mut self, ui: &mut Ui) { + let ctx = ui.ctx().clone(); + self.inner.show(ui, || { + vec![ + Example::new("Langton's ant", ctx_img!(ctx, "placeholder0.png")), + Example::new("Flocking simulation", ctx_img!(ctx, "placeholder1.png")), + Example::new("Slime mold simulation", ctx_img!(ctx, "slime0.png")), + ] + }); + } +} diff --git a/src/slide/s5_fractals.rs b/src/slide/s6_fractals.rs similarity index 96% rename from src/slide/s5_fractals.rs rename to src/slide/s6_fractals.rs index 806221a54d49b36a65e3fa660d292064f0bec6ef..3fd922174940bd327629dea703fb3c461a0651d5 100644 --- a/src/slide/s5_fractals.rs +++ b/src/slide/s6_fractals.rs @@ -10,9 +10,9 @@ use crate::egui::{Color32, Context, Frame, Ui}; use crate::fade_in::{fade_in_manual, fade_out_manual}; use crate::governor::Governor; use crate::slide::s4_automata::randomize_grid; -use crate::slide::s5_fractals::circle::circle; -use crate::slide::s5_fractals::mandelbrot::mandelbrot; -use crate::slide::s5_fractals::rectangle::rectangle; +use crate::slide::s6_fractals::circle::circle; +use crate::slide::s6_fractals::mandelbrot::mandelbrot; +use crate::slide::s6_fractals::rectangle::rectangle; use crate::slide::Slide; use eframe::egui::style::Margin; use eframe::egui::{Align2, Vec2}; @@ -172,17 +172,17 @@ impl Slide for Fractals { // No-op (arrows are rendered below). } FractalsState::Rectangle { pixels } => { - self.code.code = pseudocode(include_str!("s5_fractals/rectangle.rs")); + self.code.code = pseudocode(include_str!("s6_fractals/rectangle.rs")); algo = Some(&rectangle); limit_pixels = Some(pixels) } FractalsState::Circle { pixels } => { - self.code.code = pseudocode(include_str!("s5_fractals/circle.rs")); + self.code.code = pseudocode(include_str!("s6_fractals/circle.rs")); algo = Some(&circle); limit_pixels = Some(pixels); } FractalsState::Mandelbrot { pixels } => { - self.code.code = pseudocode(include_str!("s5_fractals/mandelbrot.rs")); + self.code.code = pseudocode(include_str!("s6_fractals/mandelbrot.rs")); algo = Some(&mandelbrot); limit_pixels = Some(pixels); } diff --git a/src/slide/s5_fractals/README.md b/src/slide/s6_fractals/README.md similarity index 100% rename from src/slide/s5_fractals/README.md rename to src/slide/s6_fractals/README.md diff --git a/src/slide/s5_fractals/circle.rs b/src/slide/s6_fractals/circle.rs similarity index 100% rename from src/slide/s5_fractals/circle.rs rename to src/slide/s6_fractals/circle.rs diff --git a/src/slide/s5_fractals/mandelbrot.rs b/src/slide/s6_fractals/mandelbrot.rs similarity index 100% rename from src/slide/s5_fractals/mandelbrot.rs rename to src/slide/s6_fractals/mandelbrot.rs diff --git a/src/slide/s5_fractals/rectangle.rs b/src/slide/s6_fractals/rectangle.rs similarity index 100% rename from src/slide/s5_fractals/rectangle.rs rename to src/slide/s6_fractals/rectangle.rs diff --git a/src/slide/s7_computation.rs b/src/slide/s7_computation.rs new file mode 100644 index 0000000000000000000000000000000000000000..9802ef505f9ce49929f89bddaafd4e4cad3e3f69 --- /dev/null +++ b/src/slide/s7_computation.rs @@ -0,0 +1,34 @@ +use crate::component::example_list::{Example, ExampleList}; +use crate::ctx_img; +use crate::egui::{Context, Ui}; +use crate::slide::Slide; + +pub struct Computation { + inner: ExampleList, +} + +impl Default for Computation { + fn default() -> Self { + Self { + inner: ExampleList::new("More Computation-based Art"), + } + } +} + +impl Slide for Computation { + fn transition(&mut self, ctx: &Context) -> bool { + self.inner.transition(ctx) + } + + fn show(&mut self, ui: &mut Ui) { + let ctx = ui.ctx().clone(); + self.inner.show(ui, || { + vec![ + Example::new("Raytracing", ctx_img!(ctx, "raytracing0.png")), + Example::new("Raymarching", ctx_img!(ctx, "raymarching1.png")), + Example::new("Particle simulation", ctx_img!(ctx, "atom0.png")), + Example::new("Fluid simulation", ctx_img!(ctx, "fluid0.png")), + ] + }); + } +} diff --git a/src/slide/s7_mosaic.rs b/src/slide/s8_mosaic.rs similarity index 100% rename from src/slide/s7_mosaic.rs rename to src/slide/s8_mosaic.rs diff --git a/src/slide/s8_conclusion.rs b/src/slide/s9_conclusion.rs similarity index 100% rename from src/slide/s8_conclusion.rs rename to src/slide/s9_conclusion.rs