Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feeling out straw-man project architectures with Bevy #13

Merged
merged 10 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,810 changes: 1,522 additions & 1,288 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ repository = "https://github.com/philiplinden/clocss-abm"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy = { version = "0.12.0", features = ["dynamic_linking"] }
bevy-inspector-egui = { version = "0.22.1", features = ["highlight_changes"] }
bevy_egui = "0.24.0"
bevy_rapier3d = { version = "0.23.0", features = ["enhanced-determinism", "debug-render"] }
hifitime = "3.8.5"
krabmaga = { version = "0.4.1", features = ["visualization"] }
uom = "0.35.0"
particular = { version = "0.6.1", features = ["gpu"] }
rand = "0.8.5"
uuid = { version = "1.6.1", features = ["v4"] }

# Enable a small amount of optimization in debug mode
[profile.dev]
Expand Down
Binary file added assets/emojis/animals/butterfly.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/animals/crab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/animals/rabbit2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/animals/snail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/animals/turtle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock1030.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock1130.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock1230.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock130.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock230.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock330.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock430.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock530.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock630.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock730.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/emojis/clocks/clock8.png
Binary file added assets/emojis/clocks/clock830.png
Binary file added assets/emojis/clocks/clock9.png
Binary file added assets/emojis/clocks/clock930.png
Binary file added assets/emojis/clocks/mantelpiece_clock.png
Binary file added assets/emojis/clown_face.png
Binary file added assets/emojis/cold_sweat.png
Binary file added assets/emojis/dots/large_blue_circle.png
Binary file added assets/emojis/dots/red_circle.png
Binary file added assets/emojis/dots/white_circle.png
Binary file added assets/emojis/faces/clown_face.png
Binary file added assets/emojis/faces/cold_sweat.png
Binary file added assets/emojis/faces/relieved.png
Binary file added assets/emojis/faces/sunglasses.png
Binary file added assets/emojis/faces/thinking_face.png
Binary file added assets/emojis/faces/tired_face.png
Binary file added assets/emojis/numbers/eight.png
Binary file added assets/emojis/numbers/five.png
Binary file added assets/emojis/numbers/four.png
Binary file added assets/emojis/numbers/keycap_ten.png
Binary file added assets/emojis/numbers/nine.png
Binary file added assets/emojis/numbers/one.png
Binary file added assets/emojis/numbers/seven.png
Binary file added assets/emojis/numbers/six.png
Binary file added assets/emojis/numbers/three.png
Binary file added assets/emojis/numbers/two.png
Binary file added assets/emojis/numbers/zero.png
Binary file added assets/emojis/relieved.png
Binary file added assets/emojis/sunglasses.png
Binary file added assets/emojis/thinking_face.png
Binary file added assets/emojis/tired_face.png
Binary file added assets/emojis/white_check_mark.png
Binary file added assets/emojis/x.png
149 changes: 149 additions & 0 deletions src/components/body.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use rand::prelude::*;

use crate::gui::select::{Clickable, CanFollow, Followed};


// Planetoids, stars, and other natural bodies are called CELESTIALS
// Artificial bodies are called SPACECRAFT or STATION



#[derive(Component, Clone)]
pub struct BodyMaterial {
pub mesh: Mesh,
pub material: StandardMaterial,
}

impl Default for BodyMaterial {
fn default() -> Self {
Self {
mesh: shape::Cube { size: 10.0 }.into(),
material: StandardMaterial::default(),
}
}
}

pub fn add_materials(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
query: Query<(Entity, &BodyMaterial), Added<BodyMaterial>>,
) {
for (entity, material) in &query {
let mut cmds = commands.entity(entity);
let BodyMaterial { mesh, material } = material.clone();

cmds.insert((
meshes.add(mesh),
materials.add(material),
VisibilityBundle::default(),
));
}
}

#[derive(Bundle, Default)]
pub struct ParticleBundle {
pub rigidbody: RigidBody,
pub collider: Collider,
pub velocity: Velocity,
pub friction: Friction,
pub transform: TransformBundle,
pub mass: ColliderMassProperties,
pub read_mass: ReadMassProperties,
}

#[derive(Bundle, Default)]
pub struct BodyBundle {
pub can_select: Clickable,
pub can_follow: CanFollow,
pub body_material: BodyMaterial,
pub particle_bundle: ParticleBundle,
}

pub fn spawn_bodies(mut commands: Commands) {
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 50000.0,
shadows_enabled: true,
..default()
},
transform: Transform {
translation: Vec3::new(0.0, 0.0, 0.0),
rotation: Quat::from_rotation_x(std::f32::consts::PI / 2.5),
..default()
},
..default()
});

let main_mu = 5e7;

let main = commands
.spawn(BodyBundle {
can_select: Clickable { radius: 100.0 },
can_follow: CanFollow {
min_camera_distance: 200.0,
},
body_material: BodyMaterial {
mesh: shape::UVSphere {
radius: 100.0,
..default()
}
.into(),
material: StandardMaterial {
base_color: Color::rgb(0.6, 0.4, 0.2),
..default()
},
},
particle_bundle: ParticleBundle {
rigidbody: RigidBody::Dynamic,
collider: Collider::ball(100.0),
mass: ColliderMassProperties::Mass(main_mu),
..default()
},
})
.id();

commands.insert_resource(Followed(Some(main)));

// SPAWN DEBRIS
let mut rng = thread_rng();
let mut gen = || rng.gen_range(-8.0..=8.0) * 2.0;

let radius = 1.0;
let minor_mu = 25.0;

for _ in 0..2000 {
let distance = Vec3::new(315.0 + gen(), gen(), gen());
let velocity =
distance.cross(Vec3::Z).normalize() * ((main_mu + minor_mu) / distance.length()).sqrt();

commands.spawn(BodyBundle {
can_select: Clickable { radius },
can_follow: CanFollow {
min_camera_distance: 5.0,
},
body_material: BodyMaterial {
mesh: shape::UVSphere {
radius,
..default()
}
.into(),
material: StandardMaterial {
base_color: Color::rgb(0.5, 0.5, 0.5),
..default()
},
},
particle_bundle: ParticleBundle {
rigidbody: RigidBody::Dynamic,
collider: Collider::ball(radius),
velocity: Velocity::linear(velocity),
friction: Friction::coefficient(0.8),
transform: TransformBundle::from(Transform::from_translation(distance)),
mass: ColliderMassProperties::Mass(minor_mu),
..default()
},
});
}
}
98 changes: 98 additions & 0 deletions src/components/camera.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use bevy::{
input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel},
prelude::*,
};

#[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.add_systems(Startup, setup_camera)
.add_systems(PostUpdate, camera_controls);
}
}

pub fn camera_controls(
query_windows: Query<&Window>,
input_mouse: Res<Input<MouseButton>>,
mut scroll_events: EventReader<MouseWheel>,
mut motion_events: EventReader<MouseMotion>,
mut query_camera: Query<(&mut Transform, &OrbitCamera)>,
mut radius: Local<Option<f32>>,
) {
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 {
return;
};

let window_size = Vec2::new(window.width(), window.height());

let scroll = scroll_events
.read()
.map(|ev| match ev.unit {
MouseScrollUnit::Pixel => ev.y * 0.005,
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.read().map(|ev| ev.delta).sum::<Vec2>())
.unwrap_or_default()
/ window_size
* std::f32::consts::PI;
motion_events.clear();

let Transform {
mut rotation,
scale,
..
} = *transform;

rotation *= Quat::from_rotation_y(-delta.x * 2.0);
rotation *= Quat::from_rotation_x(-delta.y);

let translation =
orbit.focus + Mat3::from_quat(rotation).mul_vec3(Vec3::new(0.0, 0.0, *radius));

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

fn setup_camera(mut commands: Commands) {
commands.spawn((
Camera3dBundle {
transform: Transform::from_xyz(0.0, 0.0, 200.0)
.looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
camera: Camera {
hdr: true,
..default()
},
..default()
},
OrbitCamera {
min_distance: 2.0,
focus: Vec3::ZERO,
},
bevy::core_pipeline::bloom::BloomSettings {
intensity: 0.15,
..default()
},
));
}
26 changes: 26 additions & 0 deletions src/components/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use hifitime::{Duration, Epoch};

#[derive(Clone, Debug)]
pub struct Clock {
// Observed time
pub epoch: Epoch,
}

impl Default for Clock {
fn default() -> Self {
Clock {
epoch: Epoch::from_unix_seconds(0.),
}
}
}

impl Clock {
pub fn new(epoch: Epoch) -> Self {

Check warning on line 18 in src/components/clock.rs

View workflow job for this annotation

GitHub Actions / build-rust

associated items `new` and `tick` are never used
Clock {
epoch,
}
}
pub fn tick(&mut self, elapsed: Duration) {
self.epoch = self.epoch + elapsed
}
}
65 changes: 65 additions & 0 deletions src/components/label.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use bevy::prelude::*;

pub struct EntityLabelPlugin;
impl Plugin for EntityLabelPlugin {
fn build(&self, app: &mut App) {
app.add_systems(First, spawn_labels)
.add_systems(Update, update_labels_position);
}
}

#[derive(Component, Default)]
pub struct Labelled {
pub style: TextStyle,
pub offset: Vec2,
}

#[derive(Component, Deref, DerefMut)]
struct LabelEntity(Entity);

fn spawn_labels(
mut commands: Commands,
query_labelled: Query<(Entity, &Name, &Labelled), Added<Labelled>>,
) {
for (entity, name, labelled) in &query_labelled {
let id = commands
.spawn(TextBundle::from_section(
name.to_string(),
labelled.style.clone(),
))
.id();

commands.entity(entity).insert(LabelEntity(id));
}
}

fn update_labels_position(
query_camera: Query<(&Camera, &GlobalTransform)>,
query_labelled: Query<(&LabelEntity, &Labelled, &GlobalTransform)>,
mut query_labels: Query<(&mut Style, &Node)>,
) {
let (camera, camera_transform) = query_camera.single();

for (entity, label, transform) in &query_labelled {
let Ok((mut style, node)) = query_labels.get_mut(**entity) else {
continue;
};

let rotation_matrix = Mat3::from_quat(camera_transform.to_scale_rotation_translation().1);
let viewport_position = camera
.world_to_viewport(
camera_transform,
transform.translation() + rotation_matrix.mul_vec3(label.offset.extend(0.0)),
)
.map(|position| position - node.size() / 2.0);

if let Some(viewport_position) = viewport_position {
style.position_type = PositionType::Absolute;
style.left = Val::Px(viewport_position.x);
style.top = Val::Px(viewport_position.y);
style.display = Display::Flex;
} else {
style.display = Display::None;
}
}
}
4 changes: 4 additions & 0 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod body;
mod clock;
pub mod camera;
mod label;
22 changes: 22 additions & 0 deletions src/gui/debug/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub mod performance;

use performance::FpsMonitorPlugin;
// use labels::EntityLabelPlugin;

use bevy::input::common_conditions::input_toggle_active;
use bevy::prelude::*;
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use bevy_rapier3d::render::RapierDebugRenderPlugin;

pub struct DebugUiPlugin;

impl Plugin for DebugUiPlugin {
fn build(&self, app: &mut App) {
app.add_plugins((
FpsMonitorPlugin,
// EntityLabelPlugin,
WorldInspectorPlugin::default().run_if(input_toggle_active(true, KeyCode::Escape)),
RapierDebugRenderPlugin::default(),
));
}
}
Loading
Loading