use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::time::{Duration, Instant};
use super::app::{Dim, DrawMode};
use super::layers::LayerState;
use super::panels::rule_edit_model::{Rule1DEdit, Rule2DEdit};
use super::render::default_palette;
use super::theme::ThemeChoice;
use cella_lib::*;
use egui::{Color32, Shape};
use lasso2::Spur;
#[derive(Default)]
pub(in crate::gui) struct Scenario {
pub(in crate::gui) d1: Option<Grid1D>,
pub(in crate::gui) d2: Option<Grid2D>,
pub(in crate::gui) dim: Option<Dim>,
pub(in crate::gui) initial_state: Option<GridState>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::gui) enum Pacing {
Interval,
Unbounded,
}
pub(in crate::gui) struct Playback {
pub(in crate::gui) playing: bool,
pub(in crate::gui) refresh_ms: u64,
pub(in crate::gui) last_tick: Instant,
pub(in crate::gui) pacing: Pacing,
pub(in crate::gui) run_to_steps: u64,
pub(in crate::gui) run_to_target: Option<u64>,
pub(in crate::gui) playing_before_run_to: bool,
pub(in crate::gui) elapsed: Duration,
pub(in crate::gui) timed_steps: u64,
pub(in crate::gui) play_start: Option<Instant>,
pub(in crate::gui) rate_window_start: Instant,
pub(in crate::gui) rate_window_steps: u64,
pub(in crate::gui) steps_per_s: f64,
}
impl Default for Playback {
fn default() -> Self {
Self {
playing: false,
refresh_ms: 100,
last_tick: Instant::now(),
pacing: Pacing::Interval,
run_to_steps: 100,
run_to_target: None,
playing_before_run_to: false,
elapsed: Duration::ZERO,
timed_steps: 0,
play_start: None,
rate_window_start: Instant::now(),
rate_window_steps: 0,
steps_per_s: 0.0,
}
}
}
pub(in crate::gui) struct ViewSettings {
pub(in crate::gui) scale: usize,
pub(in crate::gui) colors: HashMap<Spur, Color32>,
pub(in crate::gui) palette: Vec<Color32>,
pub(in crate::gui) palette_index: usize,
pub(in crate::gui) config_colors: BTreeMap<String, String>,
pub(in crate::gui) shape_buf: Vec<Shape>,
pub(in crate::gui) inactive_color: Color32,
pub(in crate::gui) show_grid_lines: bool,
pub(in crate::gui) grid_line_color: Color32,
pub(in crate::gui) history_1d: VecDeque<Vec<CellType>>,
pub(in crate::gui) history_limit_1d: usize,
pub(in crate::gui) min_view_rows_1d: usize,
pub(in crate::gui) last_viewport_size: Option<egui::Vec2>,
pub(in crate::gui) inspector: bool,
pub(in crate::gui) layers: LayerState,
}
impl Default for ViewSettings {
fn default() -> Self {
Self {
scale: 8,
colors: HashMap::new(),
palette: default_palette(),
palette_index: 0,
config_colors: BTreeMap::new(),
shape_buf: Vec::new(),
inactive_color: Color32::from_rgb(30, 30, 35),
show_grid_lines: true,
grid_line_color: Color32::from_rgb(60, 60, 70),
history_1d: VecDeque::new(),
history_limit_1d: 100,
min_view_rows_1d: 3,
last_viewport_size: None,
inspector: true,
layers: LayerState::default(),
}
}
}
pub(in crate::gui) struct EditState {
pub(in crate::gui) draw_mode: DrawMode,
pub(in crate::gui) selected_draw_type: Option<CellType>,
pub(in crate::gui) undo_stack: Vec<Vec<(usize, CellType)>>,
pub(in crate::gui) current_paint_batch: Option<Vec<(usize, CellType)>>,
pub(in crate::gui) stroke_touched: HashSet<usize>,
pub(in crate::gui) brush: u8,
pub(in crate::gui) brush_shape: Neighborhood2D,
pub(in crate::gui) stamp: usize,
pub(in crate::gui) fill_density: f32,
pub(in crate::gui) fill_type: Option<CellType>,
pub(in crate::gui) fill_seed: u64,
pub(in crate::gui) fill_clear: bool,
pub(in crate::gui) rule_undo: Vec<Vec<(String, ParamValue)>>,
pub(in crate::gui) mutate_sigma: f64,
}
pub(in crate::gui) const RULE_UNDO_CAP: usize = 16;
impl Default for EditState {
fn default() -> Self {
Self {
draw_mode: DrawMode::Cycle,
selected_draw_type: Some(CellType::inactive()),
undo_stack: Vec::new(),
current_paint_batch: None,
stroke_touched: HashSet::new(),
brush: 0,
brush_shape: Neighborhood2D::Moore,
stamp: 0,
fill_density: 0.3,
fill_type: None,
fill_seed: 1,
fill_clear: true,
rule_undo: Vec::new(),
mutate_sigma: 0.2,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub(in crate::gui) struct PendingExport {
pub(in crate::gui) path: std::path::PathBuf,
pub(in crate::gui) steps: u32,
pub(in crate::gui) fps: u32,
pub(in crate::gui) looping: bool,
}
#[derive(Default)]
pub(in crate::gui) struct ExportState {
pub(in crate::gui) pending: Option<PendingExport>,
pub(in crate::gui) with_history_1d: bool,
pub(in crate::gui) total: usize,
pub(in crate::gui) progress: Option<Arc<AtomicUsize>>,
pub(in crate::gui) join: Option<std::thread::JoinHandle<Result<(), String>>>,
pub(in crate::gui) message: Option<String>,
}
pub(in crate::gui) struct StatsState {
pub(in crate::gui) history: BTreeMap<Spur, VecDeque<(u64, u64)>>,
pub(in crate::gui) show: BTreeMap<Spur, bool>,
pub(in crate::gui) window_len: usize,
}
impl Default for StatsState {
fn default() -> Self {
Self {
history: BTreeMap::new(),
show: BTreeMap::new(),
window_len: 300,
}
}
}
#[derive(Default)]
pub(in crate::gui) struct EditorState {
pub(in crate::gui) rule_1d: Option<Rule1DEdit>,
pub(in crate::gui) rule_2d: Option<Rule2DEdit>,
pub(in crate::gui) error_msg: Option<String>,
pub(in crate::gui) custom_types: BTreeSet<Spur>,
pub(in crate::gui) new_type_name: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(in crate::gui) enum ControlTab {
#[default]
Scenario,
Edit,
Style,
Stats,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(in crate::gui) enum WorkbenchTab {
#[default]
Rule,
Model,
Explore,
}
pub(in crate::gui) struct Chrome {
pub(in crate::gui) font_scale: f32,
pub(in crate::gui) applied_font_scale: f32,
pub(in crate::gui) base_text_styles: BTreeMap<egui::TextStyle, egui::FontId>,
pub(in crate::gui) status_message: Option<String>,
pub(in crate::gui) theme: ThemeChoice,
pub(in crate::gui) applied_theme: Option<ThemeChoice>,
pub(in crate::gui) left_open: bool,
pub(in crate::gui) right_open: bool,
pub(in crate::gui) control_tab: ControlTab,
pub(in crate::gui) workbench_tab: WorkbenchTab,
pub(in crate::gui) show_shortcuts: bool,
pub(in crate::gui) pending_snapshot_load: Option<PendingSnapshotLoad>,
pub(in crate::gui) notice: Option<Notice>,
}
#[derive(Clone, Debug, PartialEq)]
pub(in crate::gui) struct Notice {
pub(in crate::gui) title: String,
pub(in crate::gui) lines: Vec<String>,
}
pub(in crate::gui) struct PendingSnapshotLoad {
pub(in crate::gui) cfg: cella_lib::config::CellaConfig,
pub(in crate::gui) name: String,
}
impl Chrome {
pub(in crate::gui) fn new(ctx: &egui::Context) -> Self {
Self {
font_scale: 1.0,
applied_font_scale: 1.0,
base_text_styles: ctx.style_of(egui::Theme::Dark).text_styles.clone(),
status_message: None,
theme: ThemeChoice::default(),
applied_theme: None,
left_open: true,
right_open: true,
control_tab: ControlTab::default(),
workbench_tab: WorkbenchTab::default(),
show_shortcuts: false,
pending_snapshot_load: None,
notice: None,
}
}
}
pub(in crate::gui) struct Inputs {
pub(in crate::gui) grid_width: usize,
pub(in crate::gui) grid_height: usize,
pub(in crate::gui) custom_code: String,
pub(in crate::gui) custom_n: u8,
}
impl Default for Inputs {
fn default() -> Self {
Self {
grid_width: 50,
grid_height: 30,
custom_code: "30".into(),
custom_n: 1,
}
}
}