Skip to content
Snippets Groups Projects
main.rs 6.15 KiB
Newer Older
Finn Bear's avatar
Finn Bear committed
#![feature(derive_default_enum)]
Finn Bear's avatar
Finn Bear committed
#![feature(mixed_integer_ops)]
Finn Bear's avatar
Finn Bear committed

pub mod color;
Finn Bear's avatar
Finn Bear committed
pub mod component;
pub mod fade_in;
Finn Bear's avatar
Finn Bear committed
pub mod governor;
Finn Bear's avatar
Finn Bear committed
pub mod image;
pub mod slide;

use crate::fade_in::fade_in;
Finn Bear's avatar
Finn Bear committed
use crate::slide::s1_title::Title;
use crate::slide::s2_introduction::Introduction;
use crate::slide::s3_complexity::Complexity;
Finn Bear's avatar
Finn Bear committed
use crate::slide::s4_automata::Automata;
use crate::slide::s5_fractals::Fractals;
Finn Bear's avatar
Finn Bear committed
use crate::slide::s6_computation::Computation;
Finn Bear's avatar
Finn Bear committed
use crate::slide::s7_mosaic::Mosaic;
use crate::slide::s8_conclusion::Conclusion;
Finn Bear's avatar
Finn Bear committed
use crate::slide::Slide;
Finn Bear's avatar
Finn Bear committed
use eframe::egui::style::Margin;
use eframe::egui::{Key, Style, TextStyle, Visuals};
Finn Bear's avatar
Finn Bear committed
use eframe::epi::{Frame, Storage};
Finn Bear's avatar
Finn Bear committed
use eframe::{egui, epi};

Finn Bear's avatar
Finn Bear committed
// Entry point.
Finn Bear's avatar
Finn Bear committed
fn main() {
    let app = Cartoon::default();

Finn Bear's avatar
Finn Bear committed
    // 16:9 aspect ratio.
Finn Bear's avatar
Finn Bear committed
    let size = egui::Vec2::new(1280f32, 720f32);

Finn Bear's avatar
Finn Bear committed
    let native_options = eframe::NativeOptions {
Finn Bear's avatar
Finn Bear committed
        always_on_top: false,
        maximized: false,
        decorated: true,
        drag_and_drop_support: false,
        icon_data: None,
        initial_window_pos: None,
        initial_window_size: Some(size),
        min_window_size: None,
Finn Bear's avatar
Finn Bear committed
        max_window_size: Some(size),
        resizable: true,
Finn Bear's avatar
Finn Bear committed
        transparent: false,
    };

    eframe::run_native(Box::new(app), native_options);
}

Finn Bear's avatar
Finn Bear committed
/// Top-level state.
Finn Bear's avatar
Finn Bear committed
pub struct Cartoon {
Finn Bear's avatar
Finn Bear committed
    /// All slides (including their state).
Finn Bear's avatar
Finn Bear committed
    slides: Vec<Box<dyn Slide>>,
Finn Bear's avatar
Finn Bear committed
    /// Current index into [`slides`].
Finn Bear's avatar
Finn Bear committed
    slide_index: usize,
Finn Bear's avatar
Finn Bear committed
    /// When we started fading in the current slide, in seconds (with respect to `ctx.input().time`).
    transition_time: f64,
Finn Bear's avatar
Finn Bear committed
}

impl Default for Cartoon {
    fn default() -> Self {
Finn Bear's avatar
Finn Bear committed
        Self {
Finn Bear's avatar
Finn Bear committed
            slides: create_slides(),
Finn Bear's avatar
Finn Bear committed
            slide_index: 0,
            transition_time: 0.0,
Finn Bear's avatar
Finn Bear committed
        }
Finn Bear's avatar
Finn Bear committed
    }
}

Finn Bear's avatar
Finn Bear committed
/// Creates all the slides from default values. This will reset any and all animations and
/// transitions built into the slides.
///
/// This is also how the chronology of the slideshow is determined.
Finn Bear's avatar
Finn Bear committed
fn create_slides() -> Vec<Box<dyn Slide>> {
    vec![
        Box::new(Title::default()) as Box<dyn Slide>,
        Box::new(Introduction::default()),
        Box::new(Complexity::default()),
Finn Bear's avatar
Finn Bear committed
        Box::new(Automata::default()),
        Box::new(Fractals::default()),
Finn Bear's avatar
Finn Bear committed
        Box::new(Computation::default()),
Finn Bear's avatar
Finn Bear committed
        Box::new(Mosaic::default()),
        Box::new(Conclusion::default()),
Finn Bear's avatar
Finn Bear committed
    ]
}

Finn Bear's avatar
Finn Bear committed
impl epi::App for Cartoon {
Finn Bear's avatar
Finn Bear committed
    /// The title of the window, which is mostly irrelevant.
Finn Bear's avatar
Finn Bear committed
    fn name(&self) -> &str {
        "Generative Art Cartoon"
    }

Finn Bear's avatar
Finn Bear committed
    /// Called once at window initialization.
Finn Bear's avatar
Finn Bear committed
    fn setup(&mut self, ctx: &egui::Context, _frame: &Frame, _storage: Option<&dyn Storage>) {
Finn Bear's avatar
Finn Bear committed
        // Top level style overrides.
Finn Bear's avatar
Finn Bear committed
        let mut style = Style::default();
        style.animation_time = 0.5;
        style.visuals = Visuals::light();
Finn Bear's avatar
Finn Bear committed
        style.spacing.window_margin = Margin::same(24.0);
Finn Bear's avatar
Finn Bear committed

        // Increase font sizes a lot.
Finn Bear's avatar
Finn Bear committed
        {
            let header_style = style.text_styles.get_mut(&TextStyle::Heading).unwrap();
            header_style.size = 48.0;
        }
        {
            let body_style = style.text_styles.get_mut(&TextStyle::Body).unwrap();
            body_style.size = 30.0;
        }
Finn Bear's avatar
Finn Bear committed
        {
            let small_style = style.text_styles.get_mut(&TextStyle::Small).unwrap();
            small_style.size = 22.0;
        }
Finn Bear's avatar
Finn Bear committed
        // TODO(finnb): This doesn't work. May have to fork syntax coloring code to fix it.
Finn Bear's avatar
Finn Bear committed
        /*
        {
            let monospaced_style = style.text_styles.get_mut(&TextStyle::Monospace).unwrap();
            monospaced_style.size = 22.0;
        }
Finn Bear's avatar
Finn Bear committed
         */
Finn Bear's avatar
Finn Bear committed
        ctx.set_style(style);
Finn Bear's avatar
Finn Bear committed
        // Start fading in title slide now.
        self.transition_time = ctx.input().time;
Finn Bear's avatar
Finn Bear committed
    }

Finn Bear's avatar
Finn Bear committed
    /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
Finn Bear's avatar
Finn Bear committed
    fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) {
Finn Bear's avatar
Finn Bear committed
        // For inspiration and more examples, go to https://emilk.github.io/egui

        /*
        egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
            egui::menu::bar(ui, |ui| {
                ui.menu_button("File", |ui| {
                    if ui.button("Quit").clicked() {
                        frame.quit();
                    }
                });
            });
        });
         */

Finn Bear's avatar
Finn Bear committed
        // Go forward one slide (don't wait for intra-slide transitions).
        //
        // This will wrap around to the beginning.
Finn Bear's avatar
Finn Bear committed
        let force_advance =
            ctx.input().key_pressed(Key::ArrowRight) || ctx.input().key_pressed(Key::D);
Finn Bear's avatar
Finn Bear committed

        // Play the next intra-slide transition or, if there isn't one, then go forward one slide.
        //
        // This will wrap around to the beginning.
Finn Bear's avatar
Finn Bear committed
        let advance = force_advance || ctx.input().key_pressed(Key::Space);
Finn Bear's avatar
Finn Bear committed

        // Go backward one slide (don't wait for intra-slide transitions).
        //
        // This will wrap around to the end.
Finn Bear's avatar
Finn Bear committed
        let retreat = ctx.input().key_pressed(Key::ArrowLeft) || ctx.input().key_pressed(Key::A);

        if advance || retreat {
            self.slide_index = if advance {
Finn Bear's avatar
Finn Bear committed
                if force_advance || self.slides[self.slide_index].transition(ctx) {
Finn Bear's avatar
Finn Bear committed
                    let new = (self.slide_index + 1) % self.slides.len();
                    if new == 0 {
Finn Bear's avatar
Finn Bear committed
                        // We wrapped around to the beginning, so create slides to reset transitions.
Finn Bear's avatar
Finn Bear committed
                        self.slides = create_slides();
                    }
                    self.transition_time = ctx.input().time;
Finn Bear's avatar
Finn Bear committed
                    ctx.request_repaint();
                    new
                } else {
                    self.slide_index
                }
            } else {
                ctx.request_repaint();
                self.transition_time = ctx.input().time;
Finn Bear's avatar
Finn Bear committed
                self.slide_index
                    .checked_sub(1)
                    .unwrap_or(self.slides.len() - 1)
Finn Bear's avatar
Finn Bear committed
            };
Finn Bear's avatar
Finn Bear committed
        }

        egui::CentralPanel::default().show(ctx, |ui| {
Finn Bear's avatar
Finn Bear committed
            // The current slide may be fading in.
            fade_in(ui, self.transition_time, |ui| {
Finn Bear's avatar
Finn Bear committed
                // Render the current slide.
                self.slides[self.slide_index].show(ui);
            });
Finn Bear's avatar
Finn Bear committed
        });
Finn Bear's avatar
Finn Bear committed
    }
Finn Bear's avatar
Finn Bear committed
}