diff --git a/src/bin/wireframe/main.rs b/src/bin/wireframe/main.rs index b6cdd8f..eac3a61 100644 --- a/src/bin/wireframe/main.rs +++ b/src/bin/wireframe/main.rs @@ -1,11 +1,11 @@ -use glam::{mat4, vec2, vec3, vec4, Mat4, Quat, Vec3}; +use glam::{mat4, vec2, vec3, vec4, Mat4, Quat, Vec2, Vec3}; use glium::{ backend::glutin::SimpleWindowBuilder, implement_vertex, uniform, winit::event::{Event, WindowEvent}, Program, Surface, VertexBuffer, }; -use winit::event_loop::EventLoop; +use winit::{event::ElementState, event_loop::EventLoop}; #[derive(Copy, Clone)] struct Vertex { @@ -13,6 +13,40 @@ struct Vertex { } implement_vertex!(Vertex, position); +struct DragCtl { + state: S, + ctl: Option<(Vec2, S)>, +} + +impl DragCtl { + pub fn new(state: S) -> Self { + Self { state, ctl: None } + } + + pub fn state(&self) -> S { + self.state + } + + pub fn on_button(&mut self, pos: Vec2, state: ElementState) { + match state { + ElementState::Pressed => { + assert!(self.ctl.is_none()); + self.ctl = Some((pos, self.state)); + } + ElementState::Released => { + assert!(self.ctl.is_some()); + self.ctl = None; + } + } + } + + pub fn on_move(&mut self, pos: Vec2, f: impl FnOnce(S, Vec2) -> S) { + if let Some((old_pos, old_state)) = self.ctl { + self.state = f(old_state, pos - old_pos); + } + } +} + fn main() { let event_loop = EventLoop::builder().build().unwrap(); let (window, display) = SimpleWindowBuilder::new() @@ -41,8 +75,7 @@ fn main() { let vertex_buffer = VertexBuffer::new(&display, &shape).unwrap(); let mut cur_pos = vec2(0., 0.); - let mut drag_start = None; - let mut cam_rot = Quat::IDENTITY; + let mut cam_rot = DragCtl::new(Quat::IDENTITY); #[allow(deprecated)] event_loop @@ -54,7 +87,7 @@ fn main() { * std::f32::consts::SQRT_2; let proj = make_proj_matrix(vec3(size.x, size.y, 2.), (0.125, 1024.125)); - let view = Mat4::from_quat(cam_rot); + let view = Mat4::from_quat(cam_rot.state()); let mut target = display.draw(); target.clear_color(0.0, 0.0, 0.2, 1.0); @@ -81,12 +114,7 @@ fn main() { state, button, } => match button { - winit::event::MouseButton::Left => match state { - winit::event::ElementState::Pressed => { - drag_start = Some((cur_pos, cam_rot)) - } - winit::event::ElementState::Released => drag_start = None, - }, + winit::event::MouseButton::Left => cam_rot.on_button(cur_pos, state), _ => {} }, @@ -97,12 +125,10 @@ fn main() { let size = window.inner_size(); let size = vec2(size.width as f32, size.height as f32); cur_pos = vec2(position.x as f32, position.y as f32) / size; - if let Some((drag_start, drag_init_rot)) = drag_start { - let offset = cur_pos - drag_start; - cam_rot = Quat::from_euler(glam::EulerRot::YXZ, offset.x, offset.y, 0.) - * drag_init_rot; + cam_rot.on_move(cur_pos, |init, off| { window.request_redraw(); - } + Quat::from_euler(glam::EulerRot::YXZ, off.x, off.y, 0.) * init + }); } WindowEvent::Resized(window_size) => {