Skip to content
Snippets Groups Projects
Commit a1075bd1 authored by Finn Bear's avatar Finn Bear
Browse files

Fractal slide progress.

parent decb8617
No related branches found
No related tags found
No related merge requests found
...@@ -32,3 +32,12 @@ pub fn fade_in_manual<R>( ...@@ -32,3 +32,12 @@ pub fn fade_in_manual<R>(
} }
add_contents(ui, alpha) add_contents(ui, alpha)
} }
/// Like `fade_in_manual` but provides alpha *decreases* over time.
pub fn fade_out_manual<R>(
ui: &mut Ui,
fade_start: f64,
add_contents: impl FnOnce(&mut Ui, f32) -> R,
) -> R {
fade_in_manual(ui, fade_start, |ui, alpha| add_contents(ui, 1.0 - alpha))
}
...@@ -72,18 +72,7 @@ impl Slide for Automata { ...@@ -72,18 +72,7 @@ impl Slide for Automata {
rules: None, rules: None,
}; };
// Seeded such that we get the same pattern every time, which is important since randomize_grid(&mut self.life);
// we draw arrows to preset coordinates.
let mut rng = ChaCha8Rng::seed_from_u64(123456789876543216);
// Randomize grid.
for y in 0..self.life.size_cells {
for x in 0..self.life.size_cells {
if rng.gen_bool(0.3) {
self.life.set_fill(x, y, Color32::BLACK);
}
}
}
} }
AutomataState::Static { alive, dead, rules } => { AutomataState::Static { alive, dead, rules } => {
// Enable arrows/text one by one. // Enable arrows/text one by one.
...@@ -311,3 +300,19 @@ fn conways_game_of_life(grid: &Grid, expansion: usize, alive_color: Color32, fad ...@@ -311,3 +300,19 @@ fn conways_game_of_life(grid: &Grid, expansion: usize, alive_color: Color32, fad
new new
} }
// Sets a deterministic subset of the grid (approximately 30% of it) to black.
pub fn randomize_grid(grid: &mut Grid) {
// Seeded such that we get the same pattern every time, which is important since
// we draw arrows to preset coordinates.
let mut rng = ChaCha8Rng::seed_from_u64(123456789876543216);
// Randomize grid.
for y in 0..grid.size_cells {
for x in 0..grid.size_cells {
if rng.gen_bool(0.3) {
grid.set_fill(x, y, Color32::BLACK);
}
}
}
}
...@@ -2,10 +2,13 @@ mod circle; ...@@ -2,10 +2,13 @@ mod circle;
mod mandelbrot; mod mandelbrot;
mod rectangle; mod rectangle;
use crate::color::set_alpha;
use crate::component::code::{pseudocode, Code}; use crate::component::code::{pseudocode, Code};
use crate::component::grid::Grid; use crate::component::grid::Grid;
use crate::egui::{Color32, Context, Frame, Ui}; use crate::egui::{Color32, Context, Frame, Ui};
use crate::fade_in::{fade_in_manual, fade_out_manual};
use crate::governor::Governor; use crate::governor::Governor;
use crate::slide::s4_automata::randomize_grid;
use crate::slide::s5_fractals::circle::circle; use crate::slide::s5_fractals::circle::circle;
use crate::slide::s5_fractals::mandelbrot::mandelbrot; use crate::slide::s5_fractals::mandelbrot::mandelbrot;
use crate::slide::s5_fractals::rectangle::rectangle; use crate::slide::s5_fractals::rectangle::rectangle;
...@@ -35,6 +38,11 @@ enum FractalsState { ...@@ -35,6 +38,11 @@ enum FractalsState {
/// When we started fading in the grid. /// When we started fading in the grid.
fade_start: f64, fade_start: f64,
}, },
/// Erasing the automata cells.
Erase {
/// When we started fading out the dots.
fade_start: f64,
},
Rectangle { Rectangle {
/// How many pixels of the grid we've filled in. /// How many pixels of the grid we've filled in.
pixels: usize, pixels: usize,
...@@ -65,6 +73,8 @@ impl Default for Fractals { ...@@ -65,6 +73,8 @@ impl Default for Fractals {
grid.size_cells = 128; grid.size_cells = 128;
randomize_grid(&mut grid);
// Grid cell stroke aliases too much at this resolution. // Grid cell stroke aliases too much at this resolution.
grid.stroke_width = 0.0; grid.stroke_width = 0.0;
...@@ -91,8 +101,11 @@ impl Slide for Fractals { ...@@ -91,8 +101,11 @@ impl Slide for Fractals {
self.code.alpha = 1.0; self.code.alpha = 1.0;
self.grid.alpha = 1.0; self.grid.alpha = 1.0;
self.state = FractalsState::Rectangle { pixels: 0 } self.state = FractalsState::Erase {
fade_start: ctx.input().time,
};
} }
FractalsState::Erase { .. } => self.state = FractalsState::Rectangle { pixels: 0 },
FractalsState::Rectangle { .. } => self.state = FractalsState::Circle { pixels: 0 }, FractalsState::Rectangle { .. } => self.state = FractalsState::Circle { pixels: 0 },
FractalsState::Circle { .. } => self.state = FractalsState::Mandelbrot { pixels: 0 }, FractalsState::Circle { .. } => self.state = FractalsState::Mandelbrot { pixels: 0 },
FractalsState::Mandelbrot { .. } => return true, FractalsState::Mandelbrot { .. } => return true,
...@@ -115,7 +128,7 @@ impl Slide for Fractals { ...@@ -115,7 +128,7 @@ impl Slide for Fractals {
// //
// Note that we use indirection via a reference but not a heap-allocated [`Box`]. We can get // Note that we use indirection via a reference but not a heap-allocated [`Box`]. We can get
// away with that since the function doesn't leave our stack frame. // away with that since the function doesn't leave our stack frame.
let algo: &dyn Fn(f32, f32) -> bool; let algo: Option<&dyn Fn(f32, f32) -> bool>;
// Limit to this many pixels. If [`None`], will render all pixels. // Limit to this many pixels. If [`None`], will render all pixels.
// We use a mutable reference so we can increment in one place. // We use a mutable reference so we can increment in one place.
...@@ -128,25 +141,36 @@ impl Slide for Fractals { ...@@ -128,25 +141,36 @@ impl Slide for Fractals {
} }
&mut FractalsState::Grid { fade_start } => { &mut FractalsState::Grid { fade_start } => {
// Fade in the code and grid. // Fade in the code and grid.
let elapsed = ui.ctx().input().time - fade_start; fade_in_manual(ui, fade_start, |_, alpha| {
let alpha = (elapsed * 2.0).min(1.0) as f32; self.code.alpha = alpha;
self.code.alpha = alpha; self.grid.alpha = alpha;
self.grid.alpha = alpha; });
algo = &|_, _| false; algo = None;
}
&mut FractalsState::Erase { fade_start } => {
fade_out_manual(ui, fade_start, |_, alpha| {
// Fade out the automata cells.
for (_, _, cell) in self.grid.iter_mut() {
if cell.a() > 0 {
*cell = set_alpha(Color32::BLACK, alpha);
}
}
});
algo = None;
} }
FractalsState::Rectangle { pixels } => { FractalsState::Rectangle { pixels } => {
self.code.code = pseudocode(include_str!("s5_fractals/rectangle.rs")); self.code.code = pseudocode(include_str!("s5_fractals/rectangle.rs"));
algo = &rectangle; algo = Some(&rectangle);
limit_pixels = Some(pixels) limit_pixels = Some(pixels)
} }
FractalsState::Circle { pixels } => { FractalsState::Circle { pixels } => {
self.code.code = pseudocode(include_str!("s5_fractals/circle.rs")); self.code.code = pseudocode(include_str!("s5_fractals/circle.rs"));
algo = &circle; algo = Some(&circle);
limit_pixels = Some(pixels); limit_pixels = Some(pixels);
} }
FractalsState::Mandelbrot { pixels } => { FractalsState::Mandelbrot { pixels } => {
self.code.code = pseudocode(include_str!("s5_fractals/mandelbrot.rs")); self.code.code = pseudocode(include_str!("s5_fractals/mandelbrot.rs"));
algo = &mandelbrot; algo = Some(&mandelbrot);
limit_pixels = Some(pixels); limit_pixels = Some(pixels);
} }
} }
...@@ -160,32 +184,34 @@ impl Slide for Fractals { ...@@ -160,32 +184,34 @@ impl Slide for Fractals {
} }
} }
// Effective limit for pixels. // Paint the grid.
let effective_limit = limit_pixels.map(|l| *l).unwrap_or(usize::MAX); if let Some(algo) = algo {
// Effective limit for pixels.
let effective_limit = limit_pixels.map(|l| *l).unwrap_or(usize::MAX);
// Store the resolution before mutably borrowing self.grid. // Store the resolution before mutably borrowing self.grid.
let size_cells = self.grid.size_cells; let size_cells = self.grid.size_cells;
// Paint the grid. for (i, (gx, gy, c)) in self.grid.iter_mut().enumerate() {
for (i, (gx, gy, c)) in self.grid.iter_mut().enumerate() { if i >= effective_limit {
if i >= effective_limit { *c = Color32::TRANSPARENT;
*c = Color32::TRANSPARENT; continue;
continue; }
}
// 0 to 1. // 0 to 1.
let nx = (gx as f32 + 0.5) / size_cells as f32; let nx = (gx as f32 + 0.5) / size_cells as f32;
let ny = (gy as f32 + 0.5) / size_cells as f32; let ny = (gy as f32 + 0.5) / size_cells as f32;
// -4 to 4. // -4 to 4.
let x = nx * 4.0 - 2.0; let x = nx * 4.0 - 2.0;
let y = ny * 4.0 - 2.0; let y = ny * 4.0 - 2.0;
*c = if algo(x, y) { *c = if algo(x, y) {
Color32::BLACK Color32::BLACK
} else { } else {
Color32::WHITE Color32::WHITE
}; };
}
} }
self.code.show(ui.ctx()); self.code.show(ui.ctx());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment