diff --git a/src/main.rs b/src/main.rs index e781d22..d6d0063 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,95 @@ -use crate::shape_follow::ShapeFollowPlugin; -use crate::utils::get_cursor_world_pos; -use bevy::color::palettes::basic::{RED, WHITE}; +use crate::camera::CameraPlugin; +use crate::logic_sim::LogicSimPlugin; use bevy::prelude::*; mod fps_counter; +mod logic_sim; mod shape_follow; mod utils; fn main() { App::new() .add_plugins(( DefaultPlugins, - fps_counter::FpsCounterPlugin, - ShapeFollowPlugin, + CameraPlugin, + // fps_counter::FpsCounterPlugin, + // ShapeFollowPlugin, + LogicSimPlugin, )) - .add_systems(Startup, (setup_camera, change_window_mode)) - .add_systems(Update, draw_cursor) .run(); } -const CURSOR_SIZE: f32 = 10.0; -fn change_window_mode(mut windows: Query<&mut Window>) { - let mut window = windows.single_mut(); - // window.mode = WindowMode::Fullscreen(MonitorSelection::Current); - window.present_mode = bevy::window::PresentMode::AutoNoVsync; -} -fn setup_camera(mut commands: Commands) { - commands.spawn(Camera2d); -} -fn draw_cursor( - camera_query: Single<(&Camera, &GlobalTransform)>, - windows: Query<&Window>, - mut gizmos: Gizmos, -) { - let Some(point) = get_cursor_world_pos(camera_query, windows) else { - return; - }; +mod camera { + use crate::utils::get_cursor_world_pos; + use bevy::color::palettes::basic::WHITE; + use bevy::input::common_conditions::input_pressed; + use bevy::input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll}; + use bevy::prelude::*; - gizmos.circle_2d(point, CURSOR_SIZE, WHITE); + const CURSOR_SIZE: f32 = 10.0; + fn change_window_mode(mut windows: Query<&mut Window>) { + let mut window = windows.single_mut(); + // window.mode = WindowMode::Fullscreen(MonitorSelection::Current); + window.present_mode = bevy::window::PresentMode::AutoNoVsync; + } + + pub struct CameraPlugin; + impl Plugin for CameraPlugin { + fn build(&self, app: &mut App) { + app.insert_resource(CameraSettings { + zoom_speed: 0.05, + orthographic_zoom_range: 0.01..1000.0, + }) + .add_systems(Startup, (change_window_mode, setup_camera)) + .add_systems(Update, draw_cursor) + .add_systems(Update, zoom) + .add_systems(Update, handle_pan.run_if(input_pressed(MouseButton::Right))); + } + } + fn setup_camera(mut commands: Commands) { + commands.spawn(Camera2d); + } + fn draw_cursor( + camera_query: Single<(&Camera, &GlobalTransform)>, + windows: Query<&Window>, + mut gizmos: Gizmos, + ) { + let Some(point) = get_cursor_world_pos(camera_query, windows) else { + return; + }; + + gizmos.circle_2d(point, CURSOR_SIZE, WHITE); + } + + fn handle_pan( + mut camera: Single<(&mut Transform, &OrthographicProjection), With>, + move_event: Res, + ) { + let (camera, camera_projection) = &mut *camera; + camera.translation.x -= move_event.delta.x * camera_projection.scale; + camera.translation.y += move_event.delta.y * camera_projection.scale; + println!("{:?} {:?}", camera_projection.scale, move_event.delta); + } + fn zoom( + mut camera: Single<&mut OrthographicProjection, With>, + camera_settings: Res, + mouse_wheel_input: Res, + ) { + // We want scrolling up to zoom in, decreasing the scale, so we negate the delta. + let delta_zoom = -mouse_wheel_input.delta.y * camera_settings.zoom_speed; + // When changing scales, logarithmic changes are more intuitive. + // To get this effect, we add 1 to the delta, so that a delta of 0 + // results in no multiplicative effect, positive values result in a multiplicative increase, + // and negative values result in multiplicative decreases. + let multiplicative_zoom = 1. + delta_zoom; + + camera.scale = (camera.scale * multiplicative_zoom).clamp( + camera_settings.orthographic_zoom_range.start, + camera_settings.orthographic_zoom_range.end, + ); + } + #[derive(Resource)] + pub struct CameraSettings { + zoom_speed: f32, + orthographic_zoom_range: std::ops::Range, + } }