diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 169 |
1 files changed, 147 insertions, 22 deletions
diff --git a/src/main.rs b/src/main.rs index 6e9f760..59c4a24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,165 @@ +#![feature(array_chunks)] +use cpal::{ + BufferSize, SampleRate, StreamConfig, + traits::{DeviceTrait, HostTrait, StreamTrait}, +}; +use glam::{Vec2, vec2}; +use sdl2::event::Event; use std::{ + collections::VecDeque, env::args, f32::consts::PI, fs::read_to_string, - io::{BufWriter, Write, stdout}, - time::Instant, + sync::mpsc::{Receiver, channel}, + thread::sleep, + time::{Duration, Instant}, }; fn main() { - let mut out = BufWriter::new(stdout()); - let objects = parse_file(&read_to_string(&args().nth(1).unwrap()).unwrap()); - let start = Instant::now(); - loop { - let time = start.elapsed().as_secs_f32(); - let mut points = Vec::new(); + let mut points = VecDeque::new(); + let (mouse_tx, mouse_rx) = channel(); + + let mut state = State::new(mouse_rx); + let mut frames = 0; + let mut last_stats = Instant::now(); + + let host = cpal::default_host(); + let outdev = host.default_output_device().unwrap(); + let outstream = outdev + .build_output_stream( + &StreamConfig { + buffer_size: BufferSize::Default, + channels: 2, + sample_rate: SampleRate(48_000), + }, + move |data: &mut [f32], _| { + let time = start.elapsed().as_secs_f32(); + + while points.len() < data.len() / 2 { + state.draw(&mut points, time); + frames += 1; + } + if last_stats.elapsed().as_secs() >= 1 { + last_stats = Instant::now(); + eprintln!("FPS = {frames}"); + frames = 0; + } + for [x, y] in data.array_chunks_mut::<2>() { + let p = points.pop_front().unwrap(); + *x = p.x; + *y = p.y; + } + }, + |err| eprintln!("{err}"), + None, + ) + .unwrap(); + + outstream.play().unwrap(); + + let sdl = sdl2::init().unwrap(); + let video = sdl.video().unwrap(); + + let mut window = video + .window("Input capture", 256, 256) + .resizable() + .build() + .unwrap(); - for h in &objects { - let t = h.time as f32 / 1000.; - let trel = time - t; - if trel > 0. || trel < -1. { - continue; + let mut events = sdl.event_pump().unwrap(); + + let mut last_draw = Instant::now(); + 'blub: loop { + for event in events.poll_iter() { + match event { + Event::Window { .. } => {} + Event::MouseButtonDown { .. } => { + window.set_mouse_grab(true); + mouse_tx.send(Vec2::NEG_INFINITY).unwrap(); + } + Event::MouseMotion { xrel, yrel, .. } => { + mouse_tx.send(vec2(xrel as f32, -yrel as f32)).unwrap(); + } + Event::Quit { .. } => break 'blub, + _ => (), } - let x = h.x as f32 / 512.; - let y = h.y as f32 / 384.; + } + + if last_draw.elapsed().as_secs_f32() > 0.1 { + last_draw = Instant::now(); + let mut surf = window.surface(&events).unwrap(); + surf.fill_rect( + sdl2::rect::Rect::new(0, 0, 100, 100), + sdl2::pixels::Color::RED, + ) + .unwrap(); + surf.finish().unwrap(); + } + + sleep(Duration::from_millis(1)); + } +} - let r = 0.1 + trel / -10.; - for i in 0..20 { - let t = i as f32 / 20. * PI * 2.; - points.push((x + t.sin() * r, y + t.cos() * r)); +struct State { + mouse: Vec2, + mouse_rx: Receiver<Vec2>, + objects: Vec<HitObject>, +} + +impl State { + pub fn new(mouse_rx: Receiver<Vec2>) -> Self { + let objects = parse_file(&read_to_string(&args().nth(1).unwrap()).unwrap()); + Self { + mouse: Vec2::ZERO, + mouse_rx, + objects, + } + } + pub fn draw(&mut self, points: &mut VecDeque<Vec2>, time: f32) { + for x in self.mouse_rx.try_iter() { + if x.is_finite() { + self.mouse += x / 100.; + } else { + self.mouse *= 0.; } } + for i in 0..200 { + let t = i as f32 / 30. * PI * 2.; + points.push_back((Vec2::from_angle(t) * 2.).clamp(Vec2::NEG_ONE, Vec2::ONE)); + } + for _ in 0..200 { + points.push_back(self.mouse); + } + render_frame(&self.objects, points, time); + } +} - for (x, y) in points { - out.write_all(&f32::to_le_bytes(x)).unwrap(); - out.write_all(&f32::to_le_bytes(y)).unwrap(); +fn render_frame(obs: &[HitObject], points: &mut VecDeque<Vec2>, time: f32) { + let mut render_any = false; + for h in obs { + let t = h.time as f32 / 1000.; + let trel = time - t; + if trel > 0. || trel < -1. { + continue; } + render_any = true; + let center = vec2(h.x as f32 / 512., h.y as f32 / 384.) * 2. - 1.; + + let base_r = 0.1; + let approach_r = base_r + trel / -5.; + draw_circle(points, center, base_r, 200); + draw_circle(points, center, approach_r, 200); + } + if !render_any { + points.extend((0..100).map(|_| Vec2::ZERO)); + } +} + +fn draw_circle(points: &mut VecDeque<Vec2>, center: Vec2, r: f32, res: usize) { + for i in 0..res { + let t = i as f32 / res as f32 * PI * 2.; + points.push_back(center + Vec2::from_angle(t) * r); } } |