bevy_simple_camera_controller 0.2.1

Minimalistic camera controller
Documentation
use bevy::prelude::{Camera3dBundle, Commands, Res, Transform};
use bevy::app::{Plugin, App, Update};
use bevy::utils::default;
use crate::builders::custom_camera_controller_builder::CameraControllerBuilderData;
use crate::controllers::look_at::{handle_look_at, LookAt};
use crate::input::capture_cursor::{CameraTag, capture_cursor, disable_capture_cursor};
use crate::data::camera_properties::{CameraProperties, InitialPosition};
use crate::input::input::{handle_disable_input, handle_keyboard_input, handle_mouse_input};
use crate::data::key_binding::{CameraMovementEvents, CameraRotationEvents};
use crate::controllers::movement::update_movement;
use crate::controllers::free_flight_rotation::update_free_flight_rotation;
use crate::controllers::orbit_rotation::update_orbit_rotation;
use crate::controllers::teleport::{handle_teleport, Teleport};

#[derive(Default)]
pub struct CameraControllerPlugin {
    pub initial_position: InitialPosition,
    pub properties: CameraProperties,
    pub builder_config: CameraControllerBuilderData,
}

impl CameraControllerPlugin {
    pub fn new(
        initial_position: InitialPosition,
        properties: CameraProperties,
        builder_config: CameraControllerBuilderData,
    ) -> Self {
        let mut camera_controller = Self {
            initial_position,
            properties,
            builder_config
        };

        camera_controller.properties.lock_y_axis_movement = camera_controller.builder_config.lock_y_axis_movement;
        camera_controller.properties.hide_cursor = camera_controller.builder_config.with_hide_cursor;
        camera_controller.properties.grab_cursor = camera_controller.builder_config.with_grab_cursor;

        if let Some(rotation_speed) = camera_controller.builder_config.rotation_speed {
            camera_controller.properties.rotation_speed = rotation_speed;
        }

        return camera_controller;
    }

    pub fn create_camera(
        mut commands: Commands,
        initial_position: Res<InitialPosition>
    ) {
        commands.spawn((Camera3dBundle {
            transform: Transform::from_xyz(
                initial_position.position.x,
                initial_position.position.y,
                initial_position.position.z,
            ).looking_at(
                initial_position.look_at,
                initial_position.up_vector,
            ),
            ..default()
        },
            CameraTag
        ));
    }
}

impl Plugin for CameraControllerPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(Update, handle_disable_input);

        if self.properties.grab_cursor {
            app.add_systems(Update, capture_cursor);
            app.add_systems(Update, disable_capture_cursor);
        }

        app.insert_resource(self.initial_position.clone());
        app.insert_resource(self.properties.clone());
        app.insert_resource(self.properties.key_bindings.clone());

        if self.builder_config.with_movement {
            app.add_event::<CameraMovementEvents>();
            app.observe(handle_keyboard_input);

            app.add_systems(Update, update_movement);
        }

        let multiple_rotation_controllers =
            self.builder_config.with_free_flight_rotation == true &&
            self.builder_config.with_orbit_rotation == true;
        assert_eq!(multiple_rotation_controllers, false, "Multiple rotation controllers is not supported");

        if self.builder_config.with_free_flight_rotation {
            app.add_event::<CameraRotationEvents>();
            app.observe(handle_mouse_input);

            app.add_systems(Update, update_free_flight_rotation);
        }

        if self.builder_config.with_orbit_rotation {
            app.add_event::<CameraRotationEvents>();
            app.observe(handle_mouse_input);

            app.add_systems(Update, update_orbit_rotation);
        }

        app.add_event::<LookAt>();
        app.observe(handle_look_at);

        app.add_event::<Teleport>();
        app.observe(handle_teleport);
    }
}