Skip to content

Commit

Permalink
Remove scale field from PanOrbitCamera
Browse files Browse the repository at this point in the history
  • Loading branch information
kumikaya committed Feb 23, 2024
1 parent 8164eb9 commit 4c2666d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 62 deletions.
44 changes: 35 additions & 9 deletions examples/orthographic.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! Demonstrates usage with an orthographic camera
use bevy::prelude::*;
use bevy::render::camera::ScalingMode;
use bevy::{
input::{keyboard::KeyboardInput, ButtonState},
prelude::*,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};

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

Expand All @@ -17,6 +21,17 @@ fn setup(
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// help
commands.spawn(TextBundle {
text: Text {
sections: vec![TextSection {
value: "Press R to switch projection".to_string(),
..Default::default()
}],
..Default::default()
},
..default()
});
// Ground
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
Expand All @@ -42,18 +57,29 @@ fn setup(
// Camera
commands.spawn((
Camera3dBundle {
// Put the camera further away so clipping is less likely
transform: Transform::from_translation(Vec3::new(0.0, 5.5, 15.0)),
transform: Transform::from_translation(Vec3::new(0.0, 1.5, 6.0)),
projection: Projection::Orthographic(OrthographicProjection {
scaling_mode: ScalingMode::FixedVertical(2.0),
scaling_mode: ScalingMode::FixedVertical(1.0),
..default()
}),
..default()
},
PanOrbitCamera {
// Setting scale here will override the camera projection's initial scale
scale: Some(2.5),
..default()
},
PanOrbitCamera::default(),
));
}

fn switch_projection(
mut next_projection: Local<Projection>,
mut keyboard_events: EventReader<KeyboardInput>,
mut camera_query: Query<(&mut PanOrbitCamera, &mut Projection)>,
) {
for event in keyboard_events.read() {
if event.key_code == KeyCode::KeyR && event.state == ButtonState::Pressed {
let Ok((mut camera, mut projection)) = camera_query.get_single_mut() else {
return;
};
std::mem::swap(&mut *next_projection, &mut *projection);
camera.force_update = true;
}
}
}
61 changes: 9 additions & 52 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,6 @@ pub struct PanOrbitCamera {
/// Automatically updated.
/// Defaults to `None`.
pub radius: Option<f32>,
/// The scale of the orthographic projection. This field only applies to orthographic cameras.
/// If set to `None`, it will be calculated from the camera's current position during
/// initialization.
/// Automatically updated.
/// Defaults to `None`.
pub scale: Option<f32>,
/// Rotation in radians around the global Y axis (longitudinal). Updated automatically.
/// If both `alpha` and `beta` are `0.0`, then the camera will be looking forward, i.e. in
/// the `Vec3::NEG_Z` direction, with up being `Vec3::Y`.
Expand Down Expand Up @@ -164,12 +158,6 @@ pub struct PanOrbitCamera {
/// the mouse controls, e.g. with the keyboard.
/// Defaults to `1.0`.
pub target_radius: f32,
/// The target scale for orthographic projection. The camera will smoothly transition to this value.
/// This field is only applicable with Orthographic cameras.
/// Updated automatically, but you can also update it manually to control the camera independently
/// of the mouse controls, e.g. with the keyboard.
/// Defaults to `1.0`.
pub target_scale: f32,
/// Upper limit on the `alpha` value, in radians. Use this to restrict the maximum rotation
/// around the global Y axis.
/// Defaults to `None`.
Expand Down Expand Up @@ -298,11 +286,9 @@ impl Default for PanOrbitCamera {
enabled: true,
alpha: None,
beta: None,
scale: None,
target_alpha: 0.0,
target_beta: 0.0,
target_radius: 1.0,
target_scale: 1.0,
initialized: false,
alpha_upper_limit: None,
alpha_lower_limit: None,
Expand Down Expand Up @@ -473,23 +459,13 @@ fn pan_orbit_camera(
pan_orbit.target_radius = radius;
pan_orbit.target_focus = pan_orbit.focus;

if let Projection::Orthographic(ref mut p) = *projection {
// If user hasn't set initial scale value, we want to initialize it with the
// projection's scale, otherwise we want to override the projection's scale with
// the value the user provided.
if pan_orbit.scale.is_none() {
pan_orbit.scale = Some(p.scale);
}
p.scale = apply_zoom_limits(pan_orbit.scale.expect("Just set to Some above"));
pan_orbit.target_scale = p.scale;
}

util::update_orbit_transform(
alpha,
beta,
radius,
pan_orbit.focus,
&mut transform,
&mut projection,
&pan_orbit.base_transform,
);

Expand Down Expand Up @@ -607,23 +583,17 @@ fn pan_orbit_camera(
}
}
if (scroll_line + scroll_pixel).abs() > 0.0 {
// Choose different reference values based on the current projection
let pan_orbit = &mut *pan_orbit;
let (target_value, value) = if let Projection::Orthographic(_) = *projection {
(&mut pan_orbit.target_scale, &mut pan_orbit.scale)
} else {
(&mut pan_orbit.target_radius, &mut pan_orbit.radius)
};

// Calculate the impact of scrolling on the reference value
let line_delta = -scroll_line * (*target_value) * 0.2;
let pixel_delta = -scroll_pixel * (*target_value) * 0.2;
let line_delta = -scroll_line * (pan_orbit.target_radius) * 0.2;
let pixel_delta = -scroll_pixel * (pan_orbit.target_radius) * 0.2;

// Update the target value
*target_value += line_delta + pixel_delta;
pan_orbit.target_radius += line_delta + pixel_delta;

// If it is pixel-based scrolling, add it directly to the current value
*value = value.map(|value| apply_zoom_limits(value + pixel_delta));
pan_orbit.radius = pan_orbit
.radius
.map(|value| apply_zoom_limits(value + pixel_delta));

has_moved = true;
}
Expand All @@ -633,7 +603,6 @@ fn pan_orbit_camera(
pan_orbit.target_alpha = apply_alpha_limits(pan_orbit.target_alpha);
pan_orbit.target_beta = apply_beta_limits(pan_orbit.target_beta);
pan_orbit.target_radius = apply_zoom_limits(pan_orbit.target_radius);
pan_orbit.target_scale = apply_zoom_limits(pan_orbit.target_scale);

if !pan_orbit.allow_upside_down {
pan_orbit.target_beta = pan_orbit.target_beta.clamp(-PI / 2.0, PI / 2.0);
Expand All @@ -653,9 +622,6 @@ fn pan_orbit_camera(
|| pan_orbit.target_beta != beta
|| pan_orbit.target_radius != radius
|| pan_orbit.target_focus != pan_orbit.focus
// Scale will always be None for non-orthographic cameras, so we can't include it in
// the 'if let' above
|| Some(pan_orbit.target_scale) != pan_orbit.scale
|| pan_orbit.force_update
{
// Interpolate towards the target values
Expand All @@ -674,35 +640,26 @@ fn pan_orbit_camera(
pan_orbit.target_radius,
pan_orbit.zoom_smoothness,
);
let new_scale = util::lerp_and_snap_f32(
pan_orbit.scale.unwrap_or(pan_orbit.target_scale),
pan_orbit.target_scale,
pan_orbit.zoom_smoothness,
);
let new_focus = util::lerp_and_snap_vec3(
pan_orbit.focus,
pan_orbit.target_focus,
pan_orbit.pan_smoothness,
);

if let Projection::Orthographic(ref mut p) = *projection {
p.scale = new_scale;
}

util::update_orbit_transform(
new_alpha,
new_beta,
new_radius,
new_focus,
pan_orbit.focus,
&mut transform,
&mut projection,
&pan_orbit.base_transform,
);

// Update the current values
pan_orbit.alpha = Some(new_alpha);
pan_orbit.beta = Some(new_beta);
pan_orbit.radius = Some(new_radius);
pan_orbit.scale = Some(new_scale);
pan_orbit.focus = new_focus;
pan_orbit.force_update = false;
}
Expand Down
8 changes: 7 additions & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ pub fn calculate_from_translation_and_focus(translation: Vec3, focus: Vec3) -> (
pub fn update_orbit_transform(
alpha: f32,
beta: f32,
radius: f32,
mut radius: f32,
focus: Vec3,
transform: &mut Transform,
projection: &mut Projection,
basis: &Transform,
) {
let mut new_transform = *basis;
if let Projection::Orthographic(ref mut p) = *projection {
p.scale = radius;
// (near + far) / 2.0 ensures that objects near `focus` are not clipped
radius = (p.near + p.far) / 2.0;
}
new_transform.rotation *= Quat::from_rotation_y(alpha) * Quat::from_rotation_x(-beta);
new_transform.translation += focus + new_transform.rotation * Vec3::new(0.0, 0.0, radius);
*transform = new_transform;
Expand Down

0 comments on commit 4c2666d

Please sign in to comment.