diff --git a/src/main.rs b/src/main.rs index b05255ab65cc7c715d1874f584d3e0e775b956a3..eb5de002219acb4469a36d728bbdc289bc7e5961 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![feature(derive_default_enum)] + pub mod image; pub mod slide; @@ -43,16 +45,20 @@ pub struct Cartoon { impl Default for Cartoon { fn default() -> Self { Self { - slides: vec![ - Box::new(Title::default()) as Box<dyn Slide>, - Box::new(Introduction::default()), - Box::new(Complexity::default()), - ], + slides: create_slides(), slide_index: 0, } } } +fn create_slides() -> Vec<Box<dyn Slide>> { + vec![ + Box::new(Title::default()) as Box<dyn Slide>, + Box::new(Introduction::default()), + Box::new(Complexity::default()), + ] +} + impl epi::App for Cartoon { fn name(&self) -> &str { "Generative Art Cartoon" @@ -94,8 +100,27 @@ impl epi::App for Cartoon { }); */ - if ctx.input().key_pressed(Key::Space) { - self.slide_index = (self.slide_index + 1) % self.slides.len(); + let advance = ctx.input().key_pressed(Key::Space) + || ctx.input().key_pressed(Key::ArrowRight) + || ctx.input().key_pressed(Key::D); + let retreat = ctx.input().key_pressed(Key::ArrowLeft) || ctx.input().key_pressed(Key::A); + + if advance || retreat { + self.slide_index = if advance { + if self.slides[self.slide_index].transition(ctx) { + let new = (self.slide_index + 1) % self.slides.len(); + if new == 0 { + self.slides = create_slides(); + } + ctx.request_repaint(); + new + } else { + self.slide_index + } + } else { + ctx.request_repaint(); + self.slide_index.saturating_sub(1) + }; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/src/slide.rs b/src/slide.rs index 4339fee53071380718b755ad4369203f927fc2c7..123ae606f4f0538e4b98ecb17929f5352f386654 100644 --- a/src/slide.rs +++ b/src/slide.rs @@ -7,4 +7,9 @@ pub mod s3_complexity; pub trait Slide { fn show(&mut self, ui: &mut Ui, ctx: &Context); + /// Returns whether "done." + /// Repaint automatically requested. + fn transition(&mut self, ctx: &Context) -> bool { + true + } } diff --git a/src/slide/s3_complexity.rs b/src/slide/s3_complexity.rs index 15b3a16d7b5b853bd9949b1f5daa4c9e77cb90d1..9886bd0df577d0fa8b739e39a1c68d991ca7a6e2 100644 --- a/src/slide/s3_complexity.rs +++ b/src/slide/s3_complexity.rs @@ -3,11 +3,33 @@ use crate::{Key, Slide}; use eframe::egui::text_edit::{CCursorRange, CursorRange, TextEditState}; use eframe::egui::{Align, Align2, Frame, Layout, TextEdit, Vec2}; use eframe::epaint::text::cursor::{CCursor, Cursor}; +use std::ops::RangeInclusive; #[derive(Default)] -pub struct Complexity {} +pub struct Complexity { + state: ComplexityState, + last_time: f64, +} + +#[derive(Default, Eq, PartialEq, Debug)] +enum ComplexityState { + #[default] + Before, + Selecting(usize), + Typing(usize), + After, +} impl Slide for Complexity { + fn transition(&mut self, ctx: &Context) -> bool { + if self.state == ComplexityState::Before { + self.state = ComplexityState::Selecting(0); + false + } else { + true + } + } + fn show(&mut self, ui: &mut Ui, ctx: &Context) { Window::new("complexity") .title_bar(false) @@ -16,15 +38,56 @@ impl Slide for Complexity { .anchor(Align2::CENTER_CENTER, Vec2::ZERO) .fixed_size(Vec2::new(440.0, 100.0)) .show(ctx, |ui| { + ui.ctx().request_repaint(); + let time = ui.input().time; + let time_delta = (time - self.last_time).min(1.0); + let made_progress = time_delta > 0.1; + if made_progress { + self.last_time = time; + } + ui.vertical_centered_justified(|ui| { let mut state = TextEditState::default(); - state.set_ccursor_range(Some(CCursorRange::two( - CCursor::new(0), - CCursor::new(7), - ))); - let text_edit = - ui.text_edit_singleline(&mut "Complex Rules âž¡ Complex Results?"); - text_edit.request_focus(); + let text; + match &mut self.state { + ComplexityState::Before => { + text = String::from("Complex Rules âž¡ Complex Results?"); + } + ComplexityState::Selecting(progress) => { + text = String::from("Complex Rules âž¡ Complex Results?"); + state.set_ccursor_range(Some(CCursorRange::two( + CCursor::new(0), + CCursor::new(*progress), + ))); + if made_progress { + if *progress == "Complex".len() { + self.state = ComplexityState::Typing(0); + } else { + *progress += 1; + } + } + } + ComplexityState::Typing(progress) => { + text = format!(" {} Rules âž¡ Complex Results?", &"Simple"[0..*progress]); + if made_progress { + if *progress == "Simple".len() { + self.state = ComplexityState::After; + } else { + *progress += 1; + } + } + } + ComplexityState::After => { + text = String::from(" Simple Rules âž¡ Complex Results!"); + } + } + + let text_edit = ui.text_edit_singleline(&mut text.as_str()); + if state.ccursor_range().is_some() { + text_edit.request_focus(); + } else { + text_edit.surrender_focus(); + } TextEdit::store_state(ctx, text_edit.id, state); }); });