Skip to main content

fatui_mouse/
main.rs

1use std::ops::Add;
2
3use fatui::{
4	Event, InputState, KeyCode,
5	grid::Grid,
6	pos::{Size, X, Y},
7};
8use owo_colors::{AnsiColors, Style};
9use rand::Rng;
10
11fn main() {
12	let mut backend = fatui::open().expect("couldn't open a default backend");
13	let mut rng = rand::rng();
14	let mut _is = InputState::default();
15	let mut sparkles: Grid<usize> = Grid::new(Size::rnew(0, 0));
16	loop {
17		let mut frame = backend.step().unwrap().with(&mut _is);
18		sparkles.resize(frame.size());
19		match frame.input().event() {
20			Event::Close => break,
21			Event::KeyPress(KeyCode::Esc) => break,
22			Event::KeyPress(KeyCode::Char('c')) if frame.input().keys().ctrl() => break,
23			Event::Redraw => {
24				for y in frame.rows() {
25					for x in 0..frame.size().width.0 {
26						let x = X(x);
27						let val = sparkles.row(y).unwrap()[x];
28						if val > 0 {
29							sparkles.row_mut(y).unwrap()[x] -= 1;
30							frame.row(y)[x].char = rng.random_range(' '..'~');
31							frame.row(y)[x].style = Style::new().color(match rng.random_range(0..8) {
32								0 => AnsiColors::BrightBlack,
33								1 => AnsiColors::BrightRed,
34								2 => AnsiColors::BrightGreen,
35								3 => AnsiColors::BrightYellow,
36								4 => AnsiColors::BrightBlue,
37								5 => AnsiColors::BrightMagenta,
38								6 => AnsiColors::BrightCyan,
39								7 => AnsiColors::BrightWhite,
40								_ => unreachable!(),
41							});
42						} else {
43							frame.row(y)[x] = Default::default();
44						}
45					}
46				}
47			}
48			&Event::MouseMove(pos) => {
49				// calculate the smaller of width/height as the radius,
50				// accounting for characters being 2:1 tall:wide (ish)
51				let xr = 2.max(frame.size().width.0 / 5);
52				let yr = 1.max(frame.size().height.0 / 10);
53				let radius = xr.min(yr) * 2;
54				let r2 = radius * radius;
55				let xmin = pos.x.0.saturating_sub(radius * 2);
56				let xmax = pos.x.0.add(radius * 2).min(frame.size().width.0);
57				let ymin = pos.y.0.saturating_sub(yr);
58				let ymax = pos.y.0.add(yr).min(frame.size().height.0);
59				for y in ymin..ymax {
60					for x in xmin..xmax {
61						let dist = (x.abs_diff(pos.x.0) / 2).pow(2) + y.abs_diff(pos.y.0).pow(2) + 1;
62						if dist > r2 {
63							continue;
64						}
65						let max = 20 * radius / dist;
66						let strength = rng.random_range(0..max);
67						if !rng.random_ratio(1, dist as u32 * dist as u32) {
68							continue;
69						}
70						sparkles.row_mut(Y(y)).unwrap()[X(x)] += strength;
71					}
72				}
73			}
74			_ => (),
75		}
76	}
77}