bevy_trackball 0.15.0

Coherent virtual trackball controller/camera plugin for Bevy
Documentation
use bevy::{
	prelude::*,
	window::{CursorGrabMode, CursorOptions},
};
use trackball::nalgebra::{Point3, Unit, UnitQuaternion};

use crate::{TrackballCamera, TrackballController, TrackballMessage};

#[allow(clippy::too_many_arguments)]
#[allow(clippy::too_many_lines)]
pub fn key(
	group: Entity,
	trackball_messages: &mut MessageWriter<TrackballMessage>,
	trackball: &TrackballCamera,
	controller: &mut TrackballController,
	cursor_options: &mut CursorOptions,
	key_input: &Res<ButtonInput<KeyCode>>,
	mouse_input: &Res<ButtonInput<MouseButton>>,
	zat: f32,
	w: f32,
	v: f32,
	t: f32,
) {
	let pressed = |key: Option<KeyCode>| key.is_some_and(|key| key_input.pressed(key));
	let just_pressed = |key: Option<KeyCode>| key.is_some_and(|key| key_input.just_pressed(key));
	let just_released = |key: Option<KeyCode>| key.is_some_and(|key| key_input.just_released(key));
	let pressed_button =
		|button: Option<MouseButton>| button.is_some_and(|button| mouse_input.pressed(button));
	if just_pressed(controller.input.reset_key) {
		trackball_messages.write(TrackballMessage::reset(group));
	}
	if just_pressed(controller.input.ortho_key) {
		trackball_messages.write(TrackballMessage::ortho(group, None));
	}
	if just_pressed(controller.input.gamer_key) {
		if controller.input.slide_far_key == Some(KeyCode::KeyW) {
			controller.input.map_esdf();
		} else {
			controller.input.map_wasd();
		}
	}
	for (key, vec) in [
		(controller.input.slide_far_key, Vec3::NEG_Z),
		(controller.input.slide_near_key, Vec3::Z),
		(controller.input.slide_left_key, Vec3::NEG_X),
		(controller.input.slide_right_key, Vec3::X),
		(controller.input.slide_up_key, Vec3::Y),
		(controller.input.slide_down_key, Vec3::NEG_Y),
	] {
		if pressed(key) {
			let v = v * controller.input.slide_key_transmission;
			trackball_messages.write(TrackballMessage::slide(group, (vec * v * t).into()));
		}
	}
	for (num, &(key, vec)) in [
		(controller.input.screw_left_key, Vec3::Z),
		(controller.input.screw_right_key, Vec3::NEG_Z),
		(controller.input.orbit_left_key, Vec3::NEG_Y),
		(controller.input.orbit_right_key, Vec3::Y),
		(controller.input.orbit_up_key, Vec3::NEG_X),
		(controller.input.orbit_down_key, Vec3::X),
	]
	.iter()
	.enumerate()
	{
		if pressed(key) {
			let w = w * if num < 2 {
				controller.input.screw_key_transmission
			} else {
				controller.input.orbit_key_transmission
			};
			trackball_messages.write(TrackballMessage::orbit(
				group,
				UnitQuaternion::from_axis_angle(&Unit::new_unchecked(vec.into()), w * t),
				Point3::origin(),
			));
		}
	}
	for key in [
		controller.input.first_left_key,
		controller.input.first_right_key,
		controller.input.first_up_key,
		controller.input.first_down_key,
	] {
		if just_pressed(key) {
			controller.first_count += 1;
		}
		if just_released(key) && controller.first_count != 0 {
			controller.first_count -= 1;
		}
	}
	if !pressed(controller.input.first_key) && !pressed_button(controller.input.first_button) {
		if controller.first_count == 0 {
			controller.first.discard();
		} else if !controller.first.enabled() {
			controller.first.capture(trackball.frame.yaw_axis());
		}
	}
	for (key, vec) in [
		(controller.input.first_left_key, Vec2::Y),
		(controller.input.first_right_key, Vec2::NEG_Y),
		(controller.input.first_up_key, Vec2::X),
		(controller.input.first_down_key, Vec2::NEG_X),
	] {
		if pressed(key) {
			let w = w * controller.input.first_key_transmission;
			let ang = vec * w * t;
			let yaw_axis = *controller.first.yaw_axis().unwrap();
			trackball_messages.write(TrackballMessage::first(group, ang.x, ang.y, yaw_axis));
		}
	}
	if just_pressed(controller.input.first_key) {
		controller.first.capture(trackball.frame.yaw_axis());
		cursor_options.grab_mode = CursorGrabMode::Locked;
		cursor_options.visible = false;
	}
	if just_released(controller.input.first_key) {
		controller.first.discard();
		cursor_options.grab_mode = CursorGrabMode::None;
		cursor_options.visible = true;
	}
	controller.scale.set_denominator(zat);
	if pressed(controller.input.scale_in_key) {
		let v = v * controller.input.scale_key_transmission;
		trackball_messages.write(TrackballMessage::scale(
			group,
			controller.scale.compute(v * t),
			Point3::origin(),
		));
	}
	if pressed(controller.input.scale_out_key) {
		let v = v * controller.input.scale_key_transmission;
		trackball_messages.write(TrackballMessage::scale(
			group,
			controller.scale.compute(-v * t),
			Point3::origin(),
		));
	}
}