bevy_third_person_camera_2 0.1.0

Simple and flexible plugin for Bevy game engine
Documentation
use bevy::{
    input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll},
    prelude::*,
};

use crate::{
    CameraOffset, Roll, TargetOffset,
    components::{ThirdPersonCamTarget, ThirdPersonCamera},
    events::{RotateAroundTarget, SetLocalCam, Zoom},
    plugin_settings::ThirdPersonCameraSettings,
};

pub fn spawn_offset_s(
    mut commands: Commands,
    tp_cam_settings: Res<ThirdPersonCameraSettings>,
    tp_cam_q: Query<Entity, (Added<ThirdPersonCamera>, Without<CameraOffset>)>,
) {
    for tp_cam_entity in tp_cam_q {
        commands.entity(tp_cam_entity).insert((
            CameraOffset(tp_cam_settings.default_camera_offset),
            TargetOffset(tp_cam_settings.default_target_offset),
        ));
    }
}

pub fn rotate_camera_s(
    mut rotate_er: EventReader<RotateAroundTarget>,
    camera_settings: Res<ThirdPersonCameraSettings>,
    mut camera_transform_q: Query<&mut Transform, With<ThirdPersonCamera>>,
) {
    for rotate_ev in rotate_er.read() {
        let Ok(mut camera_transform) = camera_transform_q.get_mut(rotate_ev.camera) else {
            return;
        };

        let (mut yaw, mut pitch, roll) = camera_transform.rotation.to_euler(EulerRot::YXZ);

        yaw -= camera_settings.cam_speed * rotate_ev.delta.x;

        pitch = (pitch - camera_settings.cam_speed * rotate_ev.delta.y)
            .clamp(camera_settings.pitch_min, camera_settings.pitch_max);

        camera_transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
    }
}

pub fn roll_camera_s(
    mut roll_er: EventReader<Roll>,
    mut tp_cam_transform: Query<&mut Transform, With<ThirdPersonCamera>>,
) {
    for roll_event in roll_er.read() {
        if let Ok(mut cam_transform) = tp_cam_transform.get_mut(roll_event.camera) {
            debug!("roll_event: {:?}", roll_event);
            cam_transform.rotate_local_z(roll_event.value);
        }
    }
}

pub fn translate_camera_s(
    target_transform_q: Query<&Transform, (With<ThirdPersonCamTarget>, Without<ThirdPersonCamera>)>,
    mut camera_transform_q: Query<
        (&mut Transform, &ThirdPersonCamera, &CameraOffset, &TargetOffset),
        Without<ThirdPersonCamTarget>,
    >,
) {
    camera_transform_q.par_iter_mut().for_each(
        |(mut camera_transform, third_person_camera, cam_offset, target_offset)| {
            let Ok(target_transform) = target_transform_q.get(third_person_camera.target) else {
                error!("{} query failed {:?}", third_person_camera.target, target_transform_q);
                return;
            };

            let target_point = target_transform.translation + target_offset.0;
            camera_transform.translation = target_point - camera_transform.rotation * cam_offset.0;
        },
    );
}

pub fn zoom_s(mut zoom_er: EventReader<Zoom>, mut third_person_camera_q: Query<&mut CameraOffset>) {
    for zoom_event in zoom_er.read() {
        if let Ok(mut cam_offset) = third_person_camera_q.get_mut(zoom_event.camera) {
            cam_offset.0.z += zoom_event.value
        } else {
            error!("{} query failed {:?}", zoom_event.camera, third_person_camera_q);
        }
    }
}

pub fn mouse_rotation_control_s(
    mouse_motion: Res<AccumulatedMouseMotion>,
    camera_settings: Res<ThirdPersonCameraSettings>,
    mut rotate_ew: EventWriter<RotateAroundTarget>,
) {
    if let Some(camera) = camera_settings.local_cam {
        rotate_ew.write(RotateAroundTarget {
            camera,
            delta: mouse_motion.delta * camera_settings.mouse_speed,
        });
    };
}

pub fn keyboard_rotation_control_s(
    time: Res<Time>,
    keys: Res<ButtonInput<KeyCode>>,
    camera_settings: Res<ThirdPersonCameraSettings>,
    mut rotate_ew: EventWriter<RotateAroundTarget>,
    mut roll_ew: EventWriter<Roll>,
) {
    if let Some(camera) = camera_settings.local_cam {
        let mut yaw = 0.0;
        let mut pitch = 0.0;

        if keys.pressed(camera_settings.up) {
            pitch -= camera_settings.cam_speed * time.delta_secs();
        }
        if keys.pressed(camera_settings.down) {
            pitch += camera_settings.cam_speed * time.delta_secs();
        }
        pitch = pitch.clamp(camera_settings.pitch_min, camera_settings.pitch_max);

        if keys.pressed(camera_settings.left) {
            yaw -= camera_settings.cam_speed * time.delta_secs();
        }
        if keys.pressed(camera_settings.right) {
            yaw += camera_settings.cam_speed * time.delta_secs();
        }
        if yaw != 0.0 || pitch != 0.0 {
            rotate_ew.write(RotateAroundTarget {
                camera: camera,
                delta: Vec2::new(yaw, pitch),
            });
        }

        let mut roll = 0.0;
        if keys.pressed(camera_settings.roll_clockwise) {
            debug!("clockwise");
            roll += camera_settings.cam_speed * time.delta_secs()
        } else if keys.pressed(camera_settings.roll_counterclockwise) {
            debug!("counterclockwise");
            roll -= camera_settings.cam_speed * time.delta_secs()
        }
        if roll != 0.0 {
            roll_ew.write(Roll { camera, value: roll });
        }
    };
}

pub fn scroll_zoom_s(
    wheel_move: Res<AccumulatedMouseScroll>,
    third_person_cam_settings: Res<ThirdPersonCameraSettings>,
    mut zoom_ew: EventWriter<Zoom>,
) {
    if let Some(camera) = third_person_cam_settings.local_cam {
        zoom_ew.write(Zoom {
            camera,
            value: wheel_move.delta.y,
        });
    };
}

pub fn set_local_cam(
    mut set_local_cam_er: EventReader<SetLocalCam>,
    mut camera_settings: ResMut<ThirdPersonCameraSettings>,
) {
    for set_local_cam_event in set_local_cam_er.read() {
        camera_settings.local_cam = Some(set_local_cam_event.0)
    }
}

pub fn target_trasf_gizmo(
    mut gizmos: Gizmos,
    character_global_t_q: Query<(&GlobalTransform, &ThirdPersonCamTarget)>,
    target_offset_q: Query<&TargetOffset>,
) {
    for (character_global_t, third_person_cam_target) in character_global_t_q.iter() {
        let mut transf = character_global_t.compute_transform();
        for camera_entity in third_person_cam_target.iter() {
            if let Ok(target_offset) = target_offset_q.get(camera_entity) {
                transf.translation += target_offset.0;
                gizmos.axes(transf, 2.0);
            }
        }
    }
}