Skip to content

Commit

Permalink
Remove built-in roll controls (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
Plonq authored Feb 12, 2024
1 parent eb6665d commit 50c9b1d
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 131 deletions.
7 changes: 0 additions & 7 deletions examples/advanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//! Orbit: Middle click
//! Pan: Shift + Middle click
//! Zoom: Mousewheel
//! Roll: A (roll left) and D (roll right)

use bevy::prelude::*;
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
Expand Down Expand Up @@ -79,12 +78,6 @@ fn setup(
modifier_pan: Some(KeyCode::ShiftLeft),
// Reverse the zoom direction
reversed_zoom: true,
// Enable roll in addition to orbit.
// Note: when enabling roll you probably also want to set `allow_upside_down` to `true`
// because upside down loses its meaning when you can roll freely.
key_roll_left: Some(KeyCode::A),
key_roll_right: Some(KeyCode::D),
roll_sensitivity: 0.5,
..default()
},
));
Expand Down
81 changes: 81 additions & 0 deletions examples/roll_axis.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Demonstrates how to 'roll' the camera, thus control the 3rd axis of rotation

use bevy::prelude::*;
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use std::f32::consts::TAU;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(PanOrbitCameraPlugin)
.add_systems(Startup, setup)
.add_systems(Update, roll_controls)
.run();
}

fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Ground
commands.spawn(PbrBundle {
mesh: meshes.add(shape::Plane::from_size(5.0).into()),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default()
});
// Cube
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// Light
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// Camera
commands.spawn((
Camera3dBundle {
transform: Transform::from_translation(Vec3::new(0.0, 1.5, 5.0)),
..default()
},
PanOrbitCamera {
// Changing the up vector (which rolling does) changes what 'up' means, so you likely
// want to allow upside down when rolling.
allow_upside_down: true,
..default()
},
));
}

/// Use left/right arrow keys to roll the camera
fn roll_controls(
mut pan_orbit_q: Query<(&mut PanOrbitCamera, &Transform)>,
time: Res<Time>,
key_input: Res<Input<KeyCode>>,
) {
if let Ok((mut pan_orbit, transform)) = pan_orbit_q.get_single_mut() {
let mut roll_angle = 0.0;
let roll_amount = TAU / 3.0 * time.delta_seconds();
if key_input.pressed(KeyCode::Left) {
roll_angle -= roll_amount;
}
if key_input.pressed(KeyCode::Right) {
roll_angle += roll_amount;
}
// Rotate the base transform by the roll amount around its current 'look' axis
pan_orbit
.base_transform
.rotate_axis(transform.local_z(), roll_angle);
// Whenever controlling the camera manually you must make it force update every frame
pan_orbit.force_update = true;
}
}
2 changes: 1 addition & 1 deletion examples/touch/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions examples/touch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,7 @@ fn setup_scene(
transform: Transform::from_translation(Vec3::new(0.0, 1.5, 5.0)),
..default()
},
PanOrbitCamera {
// Enable roll for demonstration purposes. Typically you wouldn't want to enable
// this. See documentation for `key_roll_left` / `key_roll_right` and `base_transform`
// for more information.
touch_roll_enabled: true,
..default()
},
PanOrbitCamera::default(),
));
}

Expand Down
57 changes: 4 additions & 53 deletions src/input.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
use crate::{ActiveCameraData, PanOrbitCamera};
use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
use bevy::input::touch::Touch;
use bevy::prelude::*;
use std::f32::consts::TAU;

use crate::traits::Midpoint;
use crate::{ActiveCameraData, PanOrbitCamera};

#[derive(Resource, Default, Debug)]
pub struct MouseKeyTracker {
pub orbit: Vec2,
pub pan: Vec2,
pub scroll_line: f32,
pub scroll_pixel: f32,
pub roll_angle: f32,
pub rotation_angle: f32,
pub orbit_button_changed: bool,
}

#[allow(clippy::too_many_arguments)]
pub fn mouse_key_tracker(
mut camera_movement: ResMut<MouseKeyTracker>,
mouse_input: Res<Input<MouseButton>>,
Expand All @@ -25,7 +23,6 @@ pub fn mouse_key_tracker(
mut scroll_events: EventReader<MouseWheel>,
active_cam: Res<ActiveCameraData>,
orbit_cameras: Query<&PanOrbitCamera>,
time: Res<Time>,
) {
// Always consume event reader events to prevent them building up and causing spikes
let mouse_delta = mouse_motion.read().map(|event| event.delta).sum::<Vec2>();
Expand All @@ -43,7 +40,6 @@ pub fn mouse_key_tracker(
let mut pan = Vec2::ZERO;
let mut scroll_line = 0.0;
let mut scroll_pixel = 0.0;
let mut roll_angle = 0.0;
let mut orbit_button_changed = false;

// Orbit and pan
Expand All @@ -58,19 +54,6 @@ pub fn mouse_key_tracker(
scroll_line += scroll_line_delta;
scroll_pixel += scroll_pixel_delta;

// Roll
let roll_amount = TAU * 0.3 * time.delta_seconds();
if let Some(roll_left_key) = pan_orbit.key_roll_left {
if key_input.pressed(roll_left_key) {
roll_angle -= roll_amount;
}
}
if let Some(roll_right_key) = pan_orbit.key_roll_right {
if key_input.pressed(roll_right_key) {
roll_angle += roll_amount;
}
}

// Other
if orbit_just_pressed(pan_orbit, &mouse_input, &key_input)
|| orbit_just_released(pan_orbit, &mouse_input, &key_input)
Expand All @@ -82,7 +65,6 @@ pub fn mouse_key_tracker(
camera_movement.pan = pan;
camera_movement.scroll_line = scroll_line;
camera_movement.scroll_pixel = scroll_pixel;
camera_movement.roll_angle = roll_angle;
camera_movement.orbit_button_changed = orbit_button_changed;
}
}
Expand All @@ -97,10 +79,9 @@ pub struct TouchTracker {

impl TouchTracker {
/// Return orbit, pan, and zoom values based on touch data
pub fn calculate_movement(&self) -> (Vec2, Vec2, f32, f32) {
pub fn calculate_movement(&self) -> (Vec2, Vec2, f32) {
let mut orbit = Vec2::ZERO;
let mut pan = Vec2::ZERO;
let mut roll_angle = 0.0;
let mut zoom_pixel = 0.0;

// Only match when curr and prev have same number of touches, for simplicity.
Expand Down Expand Up @@ -128,32 +109,11 @@ impl TouchTracker {
let curr_dist = curr1_pos.distance(curr2_pos);
let prev_dist = prev1_pos.distance(prev2_pos);
zoom_pixel += (curr_dist - prev_dist) * 0.015;

// Roll
let prev_vec = prev2_pos - prev1_pos;
let curr_vec = curr2_pos - curr1_pos;
let prev_angle_negy = prev_vec.angle_between(Vec2::NEG_Y);
let curr_angle_negy = curr_vec.angle_between(Vec2::NEG_Y);
let prev_angle_posy = prev_vec.angle_between(Vec2::Y);
let curr_angle_posy = curr_vec.angle_between(Vec2::Y);
let roll_angle_negy = prev_angle_negy - curr_angle_negy;
let roll_angle_posy = prev_angle_posy - curr_angle_posy;
// The angle between -1deg and +1deg is 358deg according to Vec2::angle_between,
// but we want the answer to be +2deg (or -2deg if swapped). Therefore, we calculate
// two angles - one from UP and one from DOWN, and use the smallest absolute value
// of the two. This is necessary to get a predictable result when the two touches
// swap sides (change from one being on the left and one being on the right to the
// other way round).
if roll_angle_negy.abs() < roll_angle_posy.abs() {
roll_angle = roll_angle_negy;
} else {
roll_angle = roll_angle_posy;
}
}
_ => {}
}

(orbit, pan, roll_angle, zoom_pixel)
(orbit, pan, zoom_pixel)
}
}

Expand Down Expand Up @@ -260,12 +220,3 @@ pub fn pan_just_pressed(
.modifier_orbit
.map_or(true, |modifier| !key_input.pressed(modifier))
}

pub fn roll_just_pressed(pan_orbit: &PanOrbitCamera, key_input: &Res<Input<KeyCode>>) -> bool {
pan_orbit
.key_roll_left
.map_or(false, |key| key_input.just_pressed(key))
|| pan_orbit
.key_roll_right
.map_or(false, |key| key_input.just_pressed(key))
}
Loading

0 comments on commit 50c9b1d

Please sign in to comment.