use crate::util::{move_towards_vec3, vec3_lerp}; use bevy::input::mouse::{MouseScrollUnit, MouseWheel}; use bevy::prelude::*; use bevy::render::camera::ScalingMode; use bevy::{input::mouse::MouseMotion, transform::TransformSystem}; use bevy_ecs_ldtk::prelude::*; use super::darkness::{PointLight2D, ShadowMesh, SpotLight2D}; pub struct GameCameraPlugin; impl Plugin for GameCameraPlugin { fn build(&self, app: &mut App) { app.configure_set( PostUpdate, CameraSystem.before(TransformSystem::TransformPropagate), ) .register_type::() .register_type::() .add_systems(Startup, camera_setup) .add_systems(Update, control_light) .add_systems( PostUpdate, (follow_detach_system, follow_system, free_system).in_set(CameraSystem), ) .add_systems( PostUpdate, room_restraint .after(CameraSystem) .before(TransformSystem::TransformPropagate), ); } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, SystemSet)] pub struct CameraSystem; #[derive(Clone, Copy, PartialEq, Reflect)] pub enum FollowMovement { Instant, Linear(f32), Smooth(f32), } impl Default for FollowMovement { fn default() -> Self { Self::Instant } } #[derive(Default, Reflect, PartialEq)] pub enum CameraMode { #[default] Free, Follow, } #[derive(Default, Component, Reflect)] #[reflect(Component)] pub struct GameCamera { pub mode: CameraMode, } #[derive(Default, Component, Reflect)] #[reflect(Component)] pub struct CameraFollow { pub target: Option, pub movement: FollowMovement, } #[derive(Default, Component)] pub struct CameraRoomRestraint; fn camera_setup(mut commands: Commands) { commands.spawn(( Name::new("Game Camera"), Camera2dBundle { projection: OrthographicProjection { scaling_mode: ScalingMode::AutoMax { max_width: 256.0, max_height: 160.0, }, ..default() }, camera_2d: Camera2d { clear_color: bevy::core_pipeline::clear_color::ClearColorConfig::Custom( Color::rgb(0.0, 0.0, 0.0), ), }, transform: Transform::from_xyz(128.0, -73.0, 999.9), ..default() }, GameCamera::default(), Visibility::default(), ComputedVisibility::default(), CameraRoomRestraint, PointLight2D { radius: 30.0 }, ShadowMesh::default(), )); } fn follow_detach_system( mouse_input: Res>, mut mouse_events: EventReader, mut camera_query: Query<&mut GameCamera>, ) { let raw_mouse_motion: Vec2 = mouse_events.iter().map(|e| e.delta).sum(); for mut camera in camera_query.iter_mut() { if camera.mode != CameraMode::Free && mouse_input.pressed(MouseButton::Middle) && raw_mouse_motion != Vec2::ZERO { camera.mode = CameraMode::Free } } } fn free_system( mut free_query: Query<(&mut Transform, &GameCamera, &OrthographicProjection)>, mut mouse_events: EventReader, mouse_input: Res>, key_input: Res>, time: Res