Skip to content

Commit

Permalink
Remove dependencies that depend on Bevy
Browse files Browse the repository at this point in the history
  • Loading branch information
Utsira committed Jun 7, 2024
1 parent 5604690 commit dd7223c
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
workspace = { members = ["utilities"] }
[package]
name = "bevy_vox_scene"
description = "A Bevy engine plugin for loading Magica Voxel world files and render materials directly in Bevy as a scene graph."
Expand Down Expand Up @@ -47,6 +48,6 @@ serde = "1.0.193"

[dev-dependencies]
bevy = "0.13.0"
bevy_panorbit_camera = "0.14.0"
utilities = { path = "utilities" }
rand = "0.8.5"
async-std = { version = "1.12.0", features = ["attributes"] }
2 changes: 1 addition & 1 deletion examples/emissive-model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{core_pipeline::bloom::BloomSettings, prelude::*};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/modify-scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bevy::{
input::keyboard::KeyboardInput,
prelude::*,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneHook, VoxelSceneHookBundle};
use rand::Rng;
use std::f32::consts::PI;
Expand Down
2 changes: 1 addition & 1 deletion examples/modify-voxels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy::{
prelude::*,
time::common_conditions::on_timer,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{
ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModelInstance, VoxelRegion,
VoxelRegionMode, VoxelSceneHook, VoxelSceneHookBundle,
Expand Down
2 changes: 1 addition & 1 deletion examples/scene-slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
},
prelude::*,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};

/// Asset labels aren't just for loading individual models within a scene, they can load any named group within a scene, a "slice" of the scene
Expand Down
2 changes: 1 addition & 1 deletion examples/ssao-model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
pbr::ScreenSpaceAmbientOcclusionBundle,
prelude::*,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};

/// Press any key to toggle Screen Space Ambient Occlusion
Expand Down
2 changes: 1 addition & 1 deletion examples/transmission-scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
},
prelude::*,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/voxel-collisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy::{
prelude::*,
time::common_conditions::on_timer,
};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{
ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModelCollection, VoxelModelInstance,
VoxelQueryable, VoxelRegion, VoxelRegionMode, VoxelScene, VoxelSceneBundle, VoxelSceneHook,
Expand Down
2 changes: 1 addition & 1 deletion examples/voxel-generation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{core_pipeline::bloom::BloomSettings, prelude::*};
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
use bevy_vox_scene::{
VoxScenePlugin, Voxel, VoxelModelCollection, VoxelModelInstance, VoxelPalette, SDF,
};
Expand Down
9 changes: 9 additions & 0 deletions utilities/Cargo.toml
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"
132 changes: 132 additions & 0 deletions utilities/src/lib.rs
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
}

0 comments on commit dd7223c

Please sign in to comment.