forked from Game4all/bevy_vox_mesh
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove dependencies that depend on Bevy
- Loading branch information
Showing
11 changed files
with
151 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "utilities" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
bevy = "0.13.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
use bevy::{input::mouse::{MouseMotion, MouseWheel}, prelude::*, window::PrimaryWindow}; | ||
|
||
/// Tags an entity as capable of panning and orbiting. | ||
#[derive(Component)] | ||
pub struct PanOrbitCamera { | ||
/// The "focus point" to orbit around. It is automatically updated when panning the camera | ||
pub focus: Vec3, | ||
pub radius: f32, | ||
pub upside_down: bool, | ||
} | ||
|
||
impl Default for PanOrbitCamera { | ||
fn default() -> Self { | ||
PanOrbitCamera { | ||
focus: Vec3::ZERO, | ||
radius: 5.0, | ||
upside_down: false, | ||
} | ||
} | ||
} | ||
|
||
pub struct PanOrbitCameraPlugin; | ||
|
||
impl Plugin for PanOrbitCameraPlugin { | ||
fn build(&self, app: &mut App) { | ||
app | ||
.add_systems(Update, (on_spawn_camera, pan_orbit_camera)); | ||
} | ||
} | ||
|
||
fn on_spawn_camera( | ||
mut query: Query<(&Transform, &mut PanOrbitCamera), Added<PanOrbitCamera>> | ||
) { | ||
for (transform, mut pan_orbit_camera) in query.iter_mut() { | ||
pan_orbit_camera.radius = transform.translation.length(); | ||
} | ||
} | ||
|
||
/// Pan the camera with middle mouse click, zoom with scroll wheel, orbit with right mouse click. | ||
fn pan_orbit_camera( | ||
window_query: Query<&Window, With<PrimaryWindow>>, | ||
mut ev_motion: EventReader<MouseMotion>, | ||
mut ev_scroll: EventReader<MouseWheel>, | ||
input_mouse: Res<ButtonInput<MouseButton>>, | ||
mut query: Query<(&mut PanOrbitCamera, &mut Transform, &Projection)>, | ||
) { | ||
// change input mapping for orbit and panning here | ||
let orbit_button = MouseButton::Left; | ||
let pan_button = MouseButton::Right; | ||
|
||
let mut pan = Vec2::ZERO; | ||
let mut rotation_move = Vec2::ZERO; | ||
let mut scroll = 0.0; | ||
let mut orbit_button_changed = false; | ||
|
||
if input_mouse.pressed(orbit_button) { | ||
for ev in ev_motion.read() { | ||
rotation_move += ev.delta; | ||
} | ||
} else if input_mouse.pressed(pan_button) { | ||
// Pan only if we're not rotating at the moment | ||
for ev in ev_motion.read() { | ||
pan += ev.delta; | ||
} | ||
} | ||
for ev in ev_scroll.read() { | ||
scroll += ev.y * 0.005; | ||
} | ||
if input_mouse.just_released(orbit_button) || input_mouse.just_pressed(orbit_button) { | ||
orbit_button_changed = true; | ||
} | ||
|
||
for (mut pan_orbit, mut transform, projection) in query.iter_mut() { | ||
if orbit_button_changed { | ||
// only check for upside down when orbiting started or ended this frame | ||
// if the camera is "upside" down, panning horizontally would be inverted, so invert the input to make it correct | ||
let up = transform.rotation * Vec3::Y; | ||
pan_orbit.upside_down = up.y <= 0.0; | ||
} | ||
|
||
let mut any = false; | ||
if rotation_move.length_squared() > 0.0 { | ||
any = true; | ||
let window = get_primary_window_size(&window_query); | ||
let delta_x = { | ||
let delta = rotation_move.x / window.x * std::f32::consts::PI * 2.0; | ||
if pan_orbit.upside_down { -delta } else { delta } | ||
}; | ||
let delta_y = rotation_move.y / window.y * std::f32::consts::PI; | ||
let yaw = Quat::from_rotation_y(-delta_x); | ||
let pitch = Quat::from_rotation_x(-delta_y); | ||
transform.rotation = yaw * transform.rotation; // rotate around global y axis | ||
transform.rotation = transform.rotation * pitch; // rotate around local x axis | ||
} else if pan.length_squared() > 0.0 { | ||
any = true; | ||
// make panning distance independent of resolution and FOV, | ||
let window = get_primary_window_size(&window_query); | ||
if let Projection::Perspective(projection) = projection { | ||
pan *= Vec2::new(projection.fov * projection.aspect_ratio, projection.fov) / window; | ||
} | ||
// translate by local axes | ||
let right = transform.rotation * Vec3::X * -pan.x; | ||
let up = transform.rotation * Vec3::Y * pan.y; | ||
// make panning proportional to distance away from focus point | ||
let translation = (right + up) * pan_orbit.radius; | ||
pan_orbit.focus += translation; | ||
} else if scroll.abs() > 0.0 { | ||
any = true; | ||
pan_orbit.radius -= scroll * pan_orbit.radius * 0.2; | ||
// dont allow zoom to reach zero or you get stuck | ||
pan_orbit.radius = f32::max(pan_orbit.radius, 0.05); | ||
} | ||
|
||
if any { | ||
// emulating parent/child to make the yaw/y-axis rotation behave like a turntable | ||
// parent = x and y rotation | ||
// child = z-offset | ||
let rot_matrix = Mat3::from_quat(transform.rotation); | ||
transform.translation = pan_orbit.focus + rot_matrix.mul_vec3(Vec3::new(0.0, 0.0, pan_orbit.radius)); | ||
} | ||
} | ||
|
||
// consume any remaining events, so they don't pile up if we don't need them | ||
// (and also to avoid Bevy warning us about not checking events every frame update) | ||
ev_motion.clear(); | ||
} | ||
|
||
fn get_primary_window_size(window_query: &Query<&Window, With<PrimaryWindow>>) -> Vec2 { | ||
let window = window_query.get_single().expect("no window found"); | ||
let window = Vec2::new(window.width() as f32, window.height() as f32); | ||
window | ||
} |