Skip to content

Commit

Permalink
Update ring-formation and pocket-solar-system to bevy 0.12
Browse files Browse the repository at this point in the history
  • Loading branch information
Canleskis committed Dec 30, 2023
1 parent 97b97cf commit da69f74
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 152 deletions.
4 changes: 2 additions & 2 deletions examples/pocket-solar-system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ license.workspace = true

[dependencies]
particular = { path = "../../particular" }
bevy = "0.11.2"
bevy_egui = "0.21"
bevy = "0.12.1"
bevy_egui = "0.24"
crossbeam-channel = "0"
humantime = "2"

Expand Down
113 changes: 32 additions & 81 deletions examples/pocket-solar-system/src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,17 @@ use bevy::{
prelude::*,
};

#[derive(Resource, Deref, DerefMut, Default)]
pub struct Followed(pub Option<Entity>);

#[derive(Component, Default)]
pub struct CanFollow {
pub min_camera_distance: f32,
pub saved_transform: Transform,
}

#[derive(Component, Default)]
pub struct OrbitCamera {
pub min_distance: f32,
pub focus: Vec3,
}

pub struct CameraPlugin;

impl Plugin for CameraPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<Followed>()
.add_systems(
Update,
(followed_save_transform, followed_set_parent_camera).chain(),
)
.add_systems(PostUpdate, camera_controls);
app.add_systems(PostUpdate, camera_controls);
}
}

Expand All @@ -35,9 +22,12 @@ pub fn camera_controls(
input_mouse: Res<Input<MouseButton>>,
mut scroll_events: EventReader<MouseWheel>,
mut motion_events: EventReader<MouseMotion>,
mut query_camera: Query<(&mut Transform, &OrbitCamera, Ref<Parent>)>,
mut query_camera: Query<(&mut Transform, &OrbitCamera)>,
mut radius: Local<Option<f32>>,
) {
let Ok((mut transform, orbit, parent)) = query_camera.get_single_mut() else {
let radius = radius.get_or_insert(500.0);

let Ok((mut transform, orbit)) = query_camera.get_single_mut() else {
return;
};
let Ok(window) = query_windows.get_single() else {
Expand All @@ -47,82 +37,43 @@ pub fn camera_controls(
let window_size = Vec2::new(window.width(), window.height());

let scroll = scroll_events
.iter()
.read()
.map(|ev| match ev.unit {
bevy::input::mouse::MouseScrollUnit::Pixel => ev.y * 0.005,
bevy::input::mouse::MouseScrollUnit::Line => ev.y * 1.0,
})
.sum::<f32>();

let motion = input_mouse
.pressed(MouseButton::Right)
.then(|| motion_events.iter().map(|ev| ev.delta).sum::<Vec2>())
.unwrap_or_default();
*radius -= *radius * scroll * 0.2;
*radius = radius.clamp(orbit.min_distance, 10000.0);

let delta = input_mouse
.pressed(MouseButton::Right)
.then(|| motion_events.read().map(|ev| ev.delta).sum::<Vec2>())
.unwrap_or_default()
/ window_size
* std::f32::consts::PI;
motion_events.clear();

let is_moving = motion.length_squared() != 0.0;
let is_zooming = scroll != 0.0;
let Transform {
mut rotation,
scale,
..
} = *transform;

let delta = motion / window_size * std::f32::consts::PI;
let mut rotation = transform.rotation;
rotation *= Quat::from_rotation_y(-delta.x * 2.0);
rotation *= Quat::from_rotation_x(-delta.y);

let mut distance = transform.translation.length();
distance -= distance * scroll * 0.2;

if is_moving || is_zooming || parent.is_changed() {
*transform = Transform {
translation: Mat3::from_quat(rotation).mul_vec3(Vec3::new(
0.0,
0.0,
distance.clamp(orbit.min_distance, 1000.0),
)),
rotation,
..*transform
}
}
}

fn followed_save_transform(
followed: Res<Followed>,
mut query_can_follow: Query<&mut CanFollow>,
query_camera: Query<&Transform, With<Camera>>,
mut previous_followed: Local<Option<Entity>>,
) {
if followed.is_changed() {
let can_follow = previous_followed.and_then(|e| query_can_follow.get_mut(e).ok());
let Ok(&transform) = query_camera.get_single() else {
return;
};

if let Some(mut can_follow) = can_follow {
can_follow.saved_transform = transform;
}
}
*previous_followed = **followed;
}

fn followed_set_parent_camera(
mut commands: Commands,
followed: Res<Followed>,
mut query_camera: Query<(Entity, &mut Transform, &mut OrbitCamera), With<Camera>>,
query_can_follow: Query<&CanFollow>,
) {
if !followed.is_changed() {
return;
let translation = orbit.focus
+ Mat3::from_quat(rotation).mul_vec3(Vec3::new(
0.0,
0.0,
*radius,
));

*transform = Transform {
translation,
rotation,
scale,
}

let Some(followed) = **followed else { return };
let Ok((camera_entity, mut transform, mut orbit)) = query_camera.get_single_mut() else {
return;
};
let Ok(selectable) = query_can_follow.get(followed) else {
return;
};

commands.entity(camera_entity).set_parent(followed);
orbit.min_distance = selectable.min_camera_distance;
*transform = selectable.saved_transform;
}
1 change: 0 additions & 1 deletion examples/pocket-solar-system/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ impl BodyBundle {
},
can_follow: CanFollow {
min_camera_distance: setting.radius * 3.0,
saved_transform: Transform::from_xyz(0.0, 0.0, setting.radius * 20.0),
},
particle_bundle: ParticleBundle {
mass: Mass(setting.mu),
Expand Down
4 changes: 2 additions & 2 deletions examples/pocket-solar-system/src/orbit_prediction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fn compute_prediction(
mut progress: Local<usize>,
) {
let mut steps_per_frame = 5000;
let event = compute_event.iter().next();
let event = compute_event.read().next();
let dt = physics.delta_time;

if let Some(&ComputePredictionEvent { steps }) = event {
Expand Down Expand Up @@ -153,7 +153,7 @@ fn compute_prediction(
mut query: Query<(Entity, &Velocity, &Position, &Mass, &mut PredictionState)>,
mut receiver: Local<Option<PredictionReceiver>>,
) {
let event = compute_event.iter().next();
let event = compute_event.read().next();
let dt = physics.delta_time;

if let Some(&ComputePredictionEvent { steps }) = event {
Expand Down
2 changes: 1 addition & 1 deletion examples/pocket-solar-system/src/physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Acceleration>()
.register_type::<Velocity>()
.add_schedule(PhysicsSchedule, Schedule::new())
.add_schedule(Schedule::new(PhysicsSchedule))
.configure_sets(
PhysicsSchedule,
(PhysicsSet::First, PhysicsSet::Main, PhysicsSet::Last).chain(),
Expand Down
58 changes: 44 additions & 14 deletions examples/pocket-solar-system/src/selection.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
use crate::camera::OrbitCamera;
use bevy::prelude::*;

#[derive(Resource, Deref, DerefMut, Default)]
pub struct Followed(pub Option<Entity>);

#[derive(Component, Default)]
pub struct CanSelect {
pub radius: f32,
pub struct CanFollow {
pub min_camera_distance: f32,
}

#[derive(Component, Default)]
pub struct Selected;

#[derive(Component, Default)]
pub struct CanSelect {
pub radius: f32,
}

#[derive(Event, Deref, DerefMut)]
pub struct ClickEvent(pub Option<Entity>);

pub struct SelectionPlugin;

impl Plugin for SelectionPlugin {
fn build(&self, app: &mut App) {
app.add_event::<ClickEvent>()
.add_systems(Update, (entity_picker, select_clicked).chain());
app.init_resource::<Followed>()
.add_event::<ClickEvent>()
.add_systems(Update, (entity_picker, select_clicked).chain())
.add_systems(PostUpdate, sync_followed.before(crate::camera_controls));
}
}

fn entity_picker(
mut ctxs: bevy_egui::EguiContexts,
mut click_entity_events: EventWriter<ClickEvent>,
mouse_input: Res<Input<MouseButton>>,
query_window: Query<&Window>,
Expand All @@ -31,9 +43,14 @@ fn entity_picker(
return;
}

if ctxs.ctx_mut().is_pointer_over_area() {
return;
}

let Ok(window) = query_window.get_single() else {
return;
};

let Ok((camera_transform, camera)) = query_camera.get_single() else {
return;
};
Expand All @@ -44,11 +61,11 @@ fn entity_picker(
.and_then(|ray| {
query_can_select
.iter()
.fold(None, |acc, (entity, transform, selectable)| {
.fold(None, |acc, (entity, transform, can_select)| {
let distance = transform.translation - ray.origin;
let proj = ray.direction.dot(distance);
let mag = distance.length_squared();
let radius = selectable.radius + mag.sqrt() / 150.0;
let radius = can_select.radius + mag.sqrt() / 150.0;
let d = (proj * proj + radius * radius >= mag).then_some((entity, mag));

acc.filter(|&(_, mag2)| d.is_none() || mag2 < mag).or(d)
Expand All @@ -61,15 +78,10 @@ fn entity_picker(

fn select_clicked(
mut commands: Commands,
mut ctxs: bevy_egui::EguiContexts,
mut selection_events: EventReader<ClickEvent>,
query_selected: Query<Entity, With<Selected>>,
) {
if ctxs.ctx_mut().is_pointer_over_area() {
return;
}

for &ClickEvent(entity) in &mut selection_events {
for &ClickEvent(entity) in selection_events.read() {
for entity in &query_selected {
commands.entity(entity).remove::<Selected>();
}
Expand All @@ -80,6 +92,23 @@ fn select_clicked(
}
}

fn sync_followed(
followed: Res<Followed>,
query_can_follow: Query<(&Transform, &CanFollow)>,
mut query_camera: Query<&mut OrbitCamera>,
) {
let Some((followed_transform, can_follow)) =
followed.and_then(|e| query_can_follow.get(e).ok())
else {
return;
};

for mut orbit in &mut query_camera {
orbit.min_distance = can_follow.min_camera_distance;
orbit.focus = followed_transform.translation;
}
}

fn _show_pickable_zone(
mut gizmos: Gizmos,
query_camera: Query<&GlobalTransform, With<Camera>>,
Expand All @@ -89,9 +118,10 @@ fn _show_pickable_zone(
return;
};

for (transform, selectable) in &query_can_select {
for (transform, can_select) in &query_can_select {
let distance = transform.translation - camera_transform.translation();
let radius = selectable.radius + distance.length() / 200.0;
let mag = distance.length_squared();
let radius = can_select.radius + mag.sqrt() / 150.0;
gizmos.circle(
transform.translation,
distance.normalize(),
Expand Down
2 changes: 1 addition & 1 deletion examples/pocket-solar-system/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ fn update_labels_color(
}
};

for entity in deselected.iter() {
for entity in deselected.read() {
set_label_color(entity, Color::GRAY);
}

Expand Down
6 changes: 3 additions & 3 deletions examples/ring-formation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ license.workspace = true

[dependencies]
particular = { path = "../../particular", features = ["parallel"]}
bevy = "0.11.2"
bevy_rapier3d = { version = "0", features = ["simd-stable"] }
bevy_egui = "0.21"
bevy = "0.12.1"
bevy_rapier3d = { version = "0.23", features = ["simd-stable"] }
bevy_egui = "0.24"
rand = "0"
humantime = "2"

Expand Down
9 changes: 5 additions & 4 deletions examples/ring-formation/src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct CameraPlugin;

impl Plugin for CameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, camera_controls);
app.add_systems(PostUpdate, camera_controls);
}
}

Expand All @@ -37,18 +37,19 @@ pub fn camera_controls(
let window_size = Vec2::new(window.width(), window.height());

let scroll = scroll_events
.iter()
.read()
.map(|ev| match ev.unit {
bevy::input::mouse::MouseScrollUnit::Pixel => ev.y * 0.005,
bevy::input::mouse::MouseScrollUnit::Line => ev.y * 1.0,
})
.sum::<f32>();

*radius -= *radius * scroll * 0.2;
*radius = radius.clamp(orbit.min_distance, 10000.0);

let delta = input_mouse
.pressed(MouseButton::Right)
.then(|| motion_events.iter().map(|ev| ev.delta).sum::<Vec2>())
.then(|| motion_events.read().map(|ev| ev.delta).sum::<Vec2>())
.unwrap_or_default()
/ window_size
* std::f32::consts::PI;
Expand All @@ -67,7 +68,7 @@ pub fn camera_controls(
+ Mat3::from_quat(rotation).mul_vec3(Vec3::new(
0.0,
0.0,
radius.clamp(orbit.min_distance, 10000.0),
*radius,
));

*transform = Transform {
Expand Down
Loading

0 comments on commit da69f74

Please sign in to comment.