@@ -3,31 +3,32 @@ use bevy::core_pipeline::{
33 bloom:: Bloom ,
44 tonemapping:: { DebandDither , Tonemapping } ,
55} ;
6- #[ cfg( feature ="top_down_camera" ) ]
7- use bevy:: input:: mouse:: { MouseButtonInput , MouseMotion } ;
6+ #[ cfg( feature ="top_down" ) ]
7+ use bevy_enhanced_input:: prelude:: * ;
8+ #[ cfg( feature ="third_person" ) ]
89use bevy_third_person_camera:: * ;
910
1011pub fn plugin ( app : & mut App ) {
1112 app. add_systems ( Startup , spawn_camera)
12- . add_systems ( OnEnter ( Screen :: Title ) , add_skybox_to_camera)
13- . add_systems ( OnEnter ( Screen :: Gameplay ) , add_tpv_cam)
13+ . add_systems ( OnEnter ( Screen :: Title ) , add_skybox_to_camera) ;
14+
15+ #[ cfg( feature ="third_person" ) ]
16+ app. add_systems ( OnEnter ( Screen :: Gameplay ) , add_tpv_cam)
1417. add_systems ( OnExit ( Screen :: Gameplay ) , rm_tpv_cam)
1518. add_observer ( toggle_cam_cursor) ;
1619
17- #[ cfg( feature ="top_down_camera" ) ]
18- app. add_systems ( Update , camera_mouse_pan) ;
20+ #[ cfg( feature ="top_down" ) ]
21+ app. add_systems ( OnEnter ( Screen :: Gameplay ) , move_camera_to_top_down)
22+ . add_observer ( camera_mouse_pan)
23+ . add_observer ( camera_zoom) ;
1924}
2025
21- pub fn spawn_camera ( mut commands : Commands , # [ cfg ( feature = "top_down_camera" ) ] cfg : Res < Config > ) {
26+ pub fn spawn_camera ( mut commands : Commands ) {
2227 commands. spawn ( (
2328SceneCamera ,
2429Camera3d :: default ( ) ,
2530Msaa :: Sample4 ,
2631IsDefaultUiCamera ,
27- #[ cfg ( feature ="top_down_camera" ) ]
28- Transform :: from_xyz ( 0.0 , cfg. player . spawn_pos . 1 +50.0 , 0.0 )
29- . looking_at ( cfg. player . spawn_pos . into ( ) , Vec3 :: X ) , // X is 'up' in this case
30- #[ cfg ( not ( feature ="top_down_camera" ) ) ]
3132Transform :: from_xyz ( 100. , 50. , 100. ) . looking_at ( Vec3 :: ZERO , Vec3 :: Y ) ,
3233Camera {
3334hdr : true ,
@@ -42,6 +43,7 @@ pub fn spawn_camera(mut commands: Commands, #[cfg(feature = "top_down_camera")]
4243}
4344
4445// TODO: add top down camera as well
46+ #[ cfg( feature ="third_person" ) ]
4547fn add_tpv_cam (
4648cfg : Res < Config > ,
4749mut commands : Commands ,
@@ -81,6 +83,7 @@ fn add_tpv_cam(
8183Ok ( ( ) )
8284}
8385
86+ #[ cfg( feature ="third_person" ) ]
8487fn rm_tpv_cam ( mut commands : Commands , mut camera : Query < Entity , With < SceneCamera > > ) {
8588if let Ok ( camera) = camera. single_mut ( ) {
8689 commands
@@ -90,33 +93,85 @@ fn rm_tpv_cam(mut commands: Commands, mut camera: Query<Entity, With<SceneCamera
9093}
9194}
9295
96+ #[ cfg( feature ="third_person" ) ]
9397fn toggle_cam_cursor ( _: Trigger < CamCursorToggle > , mut cam : Query < & mut ThirdPersonCamera > ) {
9498let Ok ( mut cam) = cam. single_mut ( ) else {
9599return ;
96100} ;
97101 cam. cursor_lock_active = !cam. cursor_lock_active ;
98102}
99103
100- /// Pans the camera using right mouse drag
101- #[ cfg( feature ="top_down_camera" ) ]
104+ #[ cfg( feature ="top_down" ) ]
105+ fn move_camera_to_top_down ( cfg : Res < Config > , mut camera : Query < & mut Transform , With < SceneCamera > > ) {
106+ let Ok ( mut cam) = camera. single_mut ( ) else {
107+ return ;
108+ } ;
109+
110+ // *cam = Transform::from_xyz(0.0, cfg.player.spawn_pos.1 + 10.0, 0.0)
111+ // .looking_at(cfg.player.spawn_pos.into(), Vec3::Y);
112+ cam. rotate_y ( -0.6 ) ;
113+ }
114+
115+ /// Pans the camera using mouse drag
116+ #[ cfg( feature ="top_down" ) ]
102117fn camera_mouse_pan (
103118on : Trigger < Fired < Pan > > ,
104- config : Res < Config > ,
105- mut query : Query < & mut Transform , With < SceneCamera > > ,
119+ time : Res < Time > ,
120+ cfg : Res < Config > ,
121+ windows : Query < & Window > ,
122+ mut cam : Query < & mut Transform , With < SceneCamera > > ,
123+ ) {
124+ let Ok ( window) = windows. single ( ) else {
125+ return ;
126+ } ;
127+ let Some ( cursor_pos) = window. cursor_position ( ) else {
128+ return ;
129+ } ;
130+ let Ok ( mut cam) = cam. single_mut ( ) else {
131+ return ;
132+ } ;
133+
134+ let mut movement =Vec3 :: ZERO ;
135+
136+ // Check screen borders and set movement direction
137+ if cursor_pos. x <= cfg. camera . edge_margin {
138+ movement +=Vec3 :: Z ; // left edge → move camera left (Z+)
139+ } else if cursor_pos. x >= window. width ( ) - cfg. camera . edge_margin {
140+ movement += -Vec3 :: Z ; // right edge → move right (Z-)
141+ }
142+
143+ if cursor_pos. y <= cfg. camera . edge_margin {
144+ movement += -Vec3 :: X ; // bottom edge → move down (X-)
145+ } else if cursor_pos. y >= window. height ( ) - cfg. camera . edge_margin {
146+ movement +=Vec3 :: X ; // top edge → move up (X+)
147+ }
148+
149+ if movement !=Vec3 :: ZERO {
150+ cam. translation += movement. normalize ( ) * cfg. camera . speed * time. delta_secs ( ) ;
151+ }
152+ }
153+
154+ #[ cfg( feature ="top_down" ) ]
155+ fn camera_zoom (
156+ on : Trigger < Fired < ScrollZoom > > ,
157+ cfg : Res < Config > ,
158+ player : Query < & mut Transform , ( With < Player > , Without < SceneCamera > ) > ,
159+ mut cam : Query < & mut Transform , With < SceneCamera > > ,
106160) {
107- // let mut delta = Vec2::ZERO;
108- //
109- // delta += on.delta;
110- //
111- // if delta == Vec2::ZERO {
112- // return;
113- // }
114- //
115- // let mut transform = query.single_mut();
116- //
117- // // Move in XZ plane, based on mouse drag direction
118- // let right = Vec3::Z * delta.x * config.camera.speed;
119- // let forward = Vec3::X * -delta.y * config.camera.speed;
120- //
121- // transform.translation += right + forward;
161+ let Ok ( mut cam) = cam. single_mut ( ) else {
162+ return ;
163+ } ;
164+ let Ok ( player) = player. single ( ) else {
165+ return ;
166+ } ;
167+
168+ info ! ( "scroll: {}" , on. value) ;
169+
170+ let new_height =( cam. translation . y - on. value . y * cfg. camera . zoom_speed )
171+ . clamp ( cfg. camera . min_height , cfg. camera . max_height ) ;
172+
173+ cam. translation . y = new_height;
174+ let ( x, z) =( cam. translation . x , cam. translation . z ) ;
175+
176+ // cam.look_at(Vec3::new(x, player.translation.y, z), Vec3::X);
122177}